1 /*
2  * Copyright (C) 2007 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.commands.am;
18 
19 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
20 import static android.app.ActivityManager.RESIZE_MODE_USER;
21 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
22 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
23 
24 import android.app.ActivityManager;
25 import android.app.ActivityManager.StackInfo;
26 import android.app.IActivityContainer;
27 import android.app.IActivityController;
28 import android.app.IActivityManager;
29 import android.app.IInstrumentationWatcher;
30 import android.app.Instrumentation;
31 import android.app.IStopUserCallback;
32 import android.app.ProfilerInfo;
33 import android.app.UiAutomationConnection;
34 import android.app.usage.ConfigurationStats;
35 import android.app.usage.IUsageStatsManager;
36 import android.app.usage.UsageStatsManager;
37 import android.content.ComponentCallbacks2;
38 import android.content.ComponentName;
39 import android.content.Context;
40 import android.content.IIntentReceiver;
41 import android.content.Intent;
42 import android.content.pm.IPackageManager;
43 import android.content.pm.InstrumentationInfo;
44 import android.content.pm.ParceledListSlice;
45 import android.content.pm.UserInfo;
46 import android.content.res.Configuration;
47 import android.graphics.Rect;
48 import android.os.Binder;
49 import android.os.Build;
50 import android.os.Bundle;
51 import android.os.ParcelFileDescriptor;
52 import android.os.RemoteException;
53 import android.os.ResultReceiver;
54 import android.os.SELinux;
55 import android.os.ServiceManager;
56 import android.os.ShellCallback;
57 import android.os.ShellCommand;
58 import android.os.SystemProperties;
59 import android.os.UserHandle;
60 import android.text.TextUtils;
61 import android.util.AndroidException;
62 import android.util.ArrayMap;
63 import android.util.Log;
64 import android.view.IWindowManager;
65 
66 import com.android.internal.os.BaseCommand;
67 import com.android.internal.util.HexDump;
68 import com.android.internal.util.Preconditions;
69 
70 import java.io.BufferedReader;
71 import java.io.File;
72 import java.io.FileDescriptor;
73 import java.io.FileNotFoundException;
74 import java.io.IOException;
75 import java.io.InputStreamReader;
76 import java.io.PrintStream;
77 import java.io.PrintWriter;
78 import java.net.URISyntaxException;
79 import java.util.ArrayList;
80 import java.util.Collections;
81 import java.util.Comparator;
82 import java.util.List;
83 
84 public class Am extends BaseCommand {
85 
86     private IActivityManager mAm;
87     private IPackageManager mPm;
88 
89     /**
90      * Command-line entry point.
91      *
92      * @param args The command-line arguments
93      */
main(String[] args)94     public static void main(String[] args) {
95         (new Am()).run(args);
96     }
97 
98     @Override
onShowUsage(PrintStream out)99     public void onShowUsage(PrintStream out) {
100         try {
101             runAmCmd(new String[] { "help" });
102         } catch (AndroidException e) {
103             e.printStackTrace(System.err);
104         }
105     }
106 
107     @Override
onRun()108     public void onRun() throws Exception {
109 
110         mAm = ActivityManager.getService();
111         if (mAm == null) {
112             System.err.println(NO_SYSTEM_ERROR_CODE);
113             throw new AndroidException("Can't connect to activity manager; is the system running?");
114         }
115 
116         mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
117         if (mPm == null) {
118             System.err.println(NO_SYSTEM_ERROR_CODE);
119             throw new AndroidException("Can't connect to package manager; is the system running?");
120         }
121 
122         String op = nextArgRequired();
123 
124         if (op.equals("instrument")) {
125             runInstrument();
126         } else {
127             runAmCmd(getRawArgs());
128         }
129     }
130 
parseUserArg(String arg)131     int parseUserArg(String arg) {
132         int userId;
133         if ("all".equals(arg)) {
134             userId = UserHandle.USER_ALL;
135         } else if ("current".equals(arg) || "cur".equals(arg)) {
136             userId = UserHandle.USER_CURRENT;
137         } else {
138             userId = Integer.parseInt(arg);
139         }
140         return userId;
141     }
142 
143     static final class MyShellCallback extends ShellCallback {
144         boolean mActive = true;
145 
onOpenOutputFile(String path, String seLinuxContext)146         @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
147             if (!mActive) {
148                 System.err.println("Open attempt after active for: " + path);
149                 return null;
150             }
151             File file = new File(path);
152             //System.err.println("Opening file: " + file.getAbsolutePath());
153             //Log.i("Am", "Opening file: " + file.getAbsolutePath());
154             final ParcelFileDescriptor fd;
155             try {
156                 fd = ParcelFileDescriptor.open(file,
157                         ParcelFileDescriptor.MODE_CREATE |
158                         ParcelFileDescriptor.MODE_TRUNCATE |
159                         ParcelFileDescriptor.MODE_WRITE_ONLY);
160             } catch (FileNotFoundException e) {
161                 String msg = "Unable to open file " + path + ": " + e;
162                 System.err.println(msg);
163                 throw new IllegalArgumentException(msg);
164             }
165             if (seLinuxContext != null) {
166                 final String tcon = SELinux.getFileContext(file.getAbsolutePath());
167                 if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) {
168                     try {
169                         fd.close();
170                     } catch (IOException e) {
171                     }
172                     String msg = "System server has no access to file context " + tcon;
173                     System.err.println(msg + " (from path " + file.getAbsolutePath()
174                             + ", context " + seLinuxContext + ")");
175                     throw new IllegalArgumentException(msg);
176                 }
177             }
178             return fd;
179         }
180     }
181 
runAmCmd(String[] args)182     void runAmCmd(String[] args) throws AndroidException {
183         final MyShellCallback cb = new MyShellCallback();
184         try {
185             mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
186                     args, cb, new ResultReceiver(null) { });
187         } catch (RemoteException e) {
188             System.err.println(NO_SYSTEM_ERROR_CODE);
189             throw new AndroidException("Can't call activity manager; is the system running?");
190         } finally {
191             cb.mActive = false;
192         }
193     }
194 
runInstrument()195     public void runInstrument() throws Exception {
196         Instrument instrument = new Instrument(mAm, mPm);
197 
198         String opt;
199         while ((opt=nextOption()) != null) {
200             if (opt.equals("-p")) {
201                 instrument.profileFile = nextArgRequired();
202             } else if (opt.equals("-w")) {
203                 instrument.wait = true;
204             } else if (opt.equals("-r")) {
205                 instrument.rawMode = true;
206             } else if (opt.equals("-m")) {
207                 instrument.proto = true;
208             } else if (opt.equals("-e")) {
209                 final String argKey = nextArgRequired();
210                 final String argValue = nextArgRequired();
211                 instrument.args.putString(argKey, argValue);
212             } else if (opt.equals("--no_window_animation")
213                     || opt.equals("--no-window-animation")) {
214                 instrument.noWindowAnimation = true;
215             } else if (opt.equals("--user")) {
216                 instrument.userId = parseUserArg(nextArgRequired());
217             } else if (opt.equals("--abi")) {
218                 instrument.abi = nextArgRequired();
219             } else {
220                 System.err.println("Error: Unknown option: " + opt);
221                 return;
222             }
223         }
224 
225         if (instrument.userId == UserHandle.USER_ALL) {
226             System.err.println("Error: Can't start instrumentation with user 'all'");
227             return;
228         }
229 
230         instrument.componentNameArg = nextArgRequired();
231 
232         instrument.run();
233     }
234 }
235