1 /*
2  * Copyright (C) 2017 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 com.android.server.am;
18 
19 import android.app.IInstrumentationWatcher;
20 import android.app.IUiAutomationConnection;
21 import android.content.ComponentName;
22 import android.content.pm.ApplicationInfo;
23 import android.os.Bundle;
24 import android.util.PrintWriterPrinter;
25 import android.util.proto.ProtoOutputStream;
26 
27 import java.io.PrintWriter;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 
31 class ActiveInstrumentation {
32     final ActivityManagerService mService;
33 
34     // Class installed to instrument app
35     ComponentName mClass;
36 
37     // All process names that should be instrumented
38     String[] mTargetProcesses;
39 
40     // The application being instrumented
41     ApplicationInfo mTargetInfo;
42 
43     // Whether the application is instrumented as an sdk running in the sdk_sandbox.
44     boolean mIsSdkInSandbox;
45 
46     // Where to save profiling
47     String mProfileFile;
48 
49     // Who is waiting
50     IInstrumentationWatcher mWatcher;
51 
52     // Connection to use the UI introspection APIs.
53     IUiAutomationConnection mUiAutomationConnection;
54 
55     // Whether the caller holds START_ACTIVITIES_FROM_BACKGROUND permission
56     boolean mHasBackgroundActivityStartsPermission;
57 
58     // Whether the caller holds START_FOREGROUND_SERVICES_FROM_BACKGROUND permission
59     boolean mHasBackgroundForegroundServiceStartsPermission;
60 
61     // As given to us
62     Bundle mArguments;
63 
64     // Any intermediate results that have been collected.
65     Bundle mCurResults;
66 
67     // Copy of instrumentationClass.
68     ComponentName mResultClass;
69 
70     // Contains all running processes that have active instrumentation.
71     final ArrayList<ProcessRecord> mRunningProcesses = new ArrayList<>();
72 
73     // Set to true when we have told the watcher the instrumentation is finished.
74     boolean mFinished;
75 
76     // The uid of the process who started this instrumentation.
77     int mSourceUid;
78 
79     // True if instrumentation should take place without restarting the target process.
80     boolean mNoRestart;
81 
ActiveInstrumentation(ActivityManagerService service)82     ActiveInstrumentation(ActivityManagerService service) {
83         mService = service;
84     }
85 
removeProcess(ProcessRecord proc)86     void removeProcess(ProcessRecord proc) {
87         mFinished = true;
88         mRunningProcesses.remove(proc);
89         if (mRunningProcesses.size() == 0) {
90             mService.mActiveInstrumentation.remove(this);
91         }
92     }
93 
toString()94     public String toString() {
95         StringBuilder sb = new StringBuilder(128);
96         sb.append("ActiveInstrumentation{");
97         sb.append(Integer.toHexString(System.identityHashCode(this)));
98         sb.append(' ');
99         sb.append(mClass.toShortString());
100         if (mFinished) {
101             sb.append(" FINISHED");
102         }
103         sb.append(" ");
104         sb.append(mRunningProcesses.size());
105         sb.append(" procs");
106         sb.append('}');
107         return sb.toString();
108     }
109 
dump(PrintWriter pw, String prefix)110     void dump(PrintWriter pw, String prefix) {
111         pw.print(prefix); pw.print("mClass="); pw.print(mClass);
112         pw.print(" mFinished="); pw.println(mFinished);
113         pw.print(prefix); pw.println("mRunningProcesses:");
114         for (int i=0; i<mRunningProcesses.size(); i++) {
115             pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
116             pw.println(mRunningProcesses.get(i));
117         }
118         pw.print(prefix); pw.print("mTargetProcesses=");
119         pw.println(Arrays.toString(mTargetProcesses));
120         pw.print(prefix); pw.print("mTargetInfo=");
121         pw.println(mTargetInfo);
122         if (mTargetInfo != null) {
123             mTargetInfo.dump(new PrintWriterPrinter(pw), prefix + "  ", 0);
124         }
125         if (mProfileFile != null) {
126             pw.print(prefix); pw.print("mProfileFile="); pw.println(mProfileFile);
127         }
128         if (mWatcher != null) {
129             pw.print(prefix); pw.print("mWatcher="); pw.println(mWatcher);
130         }
131         if (mUiAutomationConnection != null) {
132             pw.print(prefix); pw.print("mUiAutomationConnection=");
133             pw.println(mUiAutomationConnection);
134         }
135         pw.print("mHasBackgroundActivityStartsPermission=");
136         pw.println(mHasBackgroundActivityStartsPermission);
137         pw.print("mHasBackgroundForegroundServiceStartsPermission=");
138         pw.println(mHasBackgroundForegroundServiceStartsPermission);
139         pw.print(prefix); pw.print("mArguments=");
140         pw.println(mArguments);
141     }
142 
dumpDebug(ProtoOutputStream proto, long fieldId)143     void dumpDebug(ProtoOutputStream proto, long fieldId) {
144         long token = proto.start(fieldId);
145         mClass.dumpDebug(proto, ActiveInstrumentationProto.CLASS);
146         proto.write(ActiveInstrumentationProto.FINISHED, mFinished);
147         for (int i=0; i<mRunningProcesses.size(); i++) {
148             mRunningProcesses.get(i).dumpDebug(proto,
149                     ActiveInstrumentationProto.RUNNING_PROCESSES);
150         }
151         for (String p : mTargetProcesses) {
152             proto.write(ActiveInstrumentationProto.TARGET_PROCESSES, p);
153         }
154         if (mTargetInfo != null) {
155             mTargetInfo.dumpDebug(proto, ActiveInstrumentationProto.TARGET_INFO, 0);
156         }
157         proto.write(ActiveInstrumentationProto.PROFILE_FILE, mProfileFile);
158         proto.write(ActiveInstrumentationProto.WATCHER, mWatcher.toString());
159         proto.write(ActiveInstrumentationProto.UI_AUTOMATION_CONNECTION,
160                 mUiAutomationConnection.toString());
161         if (mArguments != null) {
162             mArguments.dumpDebug(proto, ActiveInstrumentationProto.ARGUMENTS);
163         }
164         proto.end(token);
165     }
166 }
167