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