1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.externalservice.common;
18 
19 import android.os.ConditionVariable;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.os.Message;
23 import android.os.Messenger;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.os.RemoteException;
27 import android.util.Log;
28 
29 /**
30  * A class that encapsulates information about a running service process
31  * and information about how it was created.
32  */
33 public class RunningServiceInfo implements Parcelable {
34     /** Timeout to wait for the condition variable to be opened when retrieving service info. */
35     public static final int CONDITION_TIMEOUT = 10 * 1000 /* 10 seconds */;
36 
37     /** The UNIX user ID of the running service process. */
38     public int uid;
39 
40     /** The UNIX process ID of the running service process. */
41     public int pid;
42 
43     /** The package name that the process is running under. */
44     public String packageName;
45 
46     /** The value reported from the test's ZygotePreload.getZygotePid(). */
47     public int zygotePid;
48 
49     /** The value reported from the test's ZygotePreload.getZygotePackage(). */
50     public String zygotePackage;
51 
writeToParcel(Parcel dest, int parcelableFlags)52     public void writeToParcel(Parcel dest, int parcelableFlags) {
53         dest.writeInt(uid);
54         dest.writeInt(pid);
55         dest.writeString(packageName);
56         dest.writeInt(zygotePid);
57         dest.writeString(zygotePackage);
58     }
59 
60     public static final Parcelable.Creator<RunningServiceInfo> CREATOR
61             = new Parcelable.Creator<RunningServiceInfo>() {
62         public RunningServiceInfo createFromParcel(Parcel source) {
63             RunningServiceInfo info = new RunningServiceInfo();
64             info.uid = source.readInt();
65             info.pid = source.readInt();
66             info.packageName = source.readString();
67             info.zygotePid = source.readInt();
68             info.zygotePackage = source.readString();
69             return info;
70         }
71         public RunningServiceInfo[] newArray(int size) {
72             return new RunningServiceInfo[size];
73         }
74     };
75 
describeContents()76     public int describeContents() {
77         return 0;
78     }
79 
80     public static class IdentifyHandler extends Handler {
81         private final String mLoggingTag;
82         private final ConditionVariable mCondition;
83 
IdentifyHandler(String loggingTag, ConditionVariable signalVariable)84         IdentifyHandler(String loggingTag, ConditionVariable signalVariable) {
85             super(Looper.getMainLooper());
86             this.mLoggingTag = loggingTag;
87             mCondition = signalVariable;
88         }
89 
90         RunningServiceInfo mInfo;
91 
92         @Override
handleMessage(Message msg)93         public void handleMessage(Message msg) {
94             Log.d(mLoggingTag, "Received message: " + msg);
95             switch (msg.what) {
96                 case ServiceMessages.MSG_IDENTIFY_RESPONSE:
97                     msg.getData().setClassLoader(RunningServiceInfo.class.getClassLoader());
98                     mInfo = msg.getData().getParcelable(ServiceMessages.IDENTIFY_INFO);
99                     mCondition.open();
100                     break;
101             }
102             super.handleMessage(msg);
103         }
104     };
105 
identifyService( Messenger service, String loggingTag, ConditionVariable signalVariable)106     public static RunningServiceInfo identifyService(
107             Messenger service,
108             String loggingTag,
109             ConditionVariable signalVariable) throws RemoteException {
110         IdentifyHandler handler = new IdentifyHandler(loggingTag, signalVariable);
111         Messenger local = new Messenger(handler);
112 
113         Message msg = Message.obtain(null, ServiceMessages.MSG_IDENTIFY);
114         msg.replyTo = local;
115 
116         signalVariable.close();
117         service.send(msg);
118 
119         if (!signalVariable.block(CONDITION_TIMEOUT)) {
120             return null;
121         }
122         return handler.mInfo;
123     }
124 }
125