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 android.app.ActivityManager; 20 import android.app.IActivityManager; 21 import android.content.pm.IPackageManager; 22 import android.os.ParcelFileDescriptor; 23 import android.os.RemoteException; 24 import android.os.ResultReceiver; 25 import android.os.SELinux; 26 import android.os.ServiceManager; 27 import android.os.ShellCallback; 28 import android.os.UserHandle; 29 import android.util.AndroidException; 30 31 import com.android.internal.os.BaseCommand; 32 33 import java.io.File; 34 import java.io.FileDescriptor; 35 import java.io.FileNotFoundException; 36 import java.io.IOException; 37 import java.io.PrintStream; 38 39 public class Am extends BaseCommand { 40 41 private IActivityManager mAm; 42 private IPackageManager mPm; 43 44 /** 45 * Command-line entry point. 46 * 47 * @param args The command-line arguments 48 */ main(String[] args)49 public static void main(String[] args) { 50 (new Am()).run(args); 51 } 52 53 @Override onShowUsage(PrintStream out)54 public void onShowUsage(PrintStream out) { 55 try { 56 runAmCmd(new String[] { "help" }); 57 } catch (AndroidException e) { 58 e.printStackTrace(System.err); 59 } 60 } 61 62 @Override onRun()63 public void onRun() throws Exception { 64 65 mAm = ActivityManager.getService(); 66 if (mAm == null) { 67 System.err.println(NO_SYSTEM_ERROR_CODE); 68 throw new AndroidException("Can't connect to activity manager; is the system running?"); 69 } 70 71 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 72 if (mPm == null) { 73 System.err.println(NO_SYSTEM_ERROR_CODE); 74 throw new AndroidException("Can't connect to package manager; is the system running?"); 75 } 76 77 String op = nextArgRequired(); 78 79 if (op.equals("instrument")) { 80 runInstrument(); 81 } else { 82 runAmCmd(getRawArgs()); 83 } 84 } 85 parseUserArg(String arg)86 int parseUserArg(String arg) { 87 int userId; 88 if ("all".equals(arg)) { 89 userId = UserHandle.USER_ALL; 90 } else if ("current".equals(arg) || "cur".equals(arg)) { 91 userId = UserHandle.USER_CURRENT; 92 } else { 93 userId = Integer.parseInt(arg); 94 } 95 return userId; 96 } 97 98 static final class MyShellCallback extends ShellCallback { 99 boolean mActive = true; 100 onOpenOutputFile(String path, String seLinuxContext)101 @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { 102 if (!mActive) { 103 System.err.println("Open attempt after active for: " + path); 104 return null; 105 } 106 File file = new File(path); 107 //System.err.println("Opening file: " + file.getAbsolutePath()); 108 //Log.i("Am", "Opening file: " + file.getAbsolutePath()); 109 final ParcelFileDescriptor fd; 110 try { 111 fd = ParcelFileDescriptor.open(file, 112 ParcelFileDescriptor.MODE_CREATE | 113 ParcelFileDescriptor.MODE_TRUNCATE | 114 ParcelFileDescriptor.MODE_WRITE_ONLY); 115 } catch (FileNotFoundException e) { 116 String msg = "Unable to open file " + path + ": " + e; 117 System.err.println(msg); 118 throw new IllegalArgumentException(msg); 119 } 120 if (seLinuxContext != null) { 121 final String tcon = SELinux.getFileContext(file.getAbsolutePath()); 122 if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) { 123 try { 124 fd.close(); 125 } catch (IOException e) { 126 } 127 String msg = "System server has no access to file context " + tcon; 128 System.err.println(msg + " (from path " + file.getAbsolutePath() 129 + ", context " + seLinuxContext + ")"); 130 throw new IllegalArgumentException(msg); 131 } 132 } 133 return fd; 134 } 135 } 136 runAmCmd(String[] args)137 void runAmCmd(String[] args) throws AndroidException { 138 final MyShellCallback cb = new MyShellCallback(); 139 try { 140 mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, 141 args, cb, new ResultReceiver(null) { }); 142 } catch (RemoteException e) { 143 System.err.println(NO_SYSTEM_ERROR_CODE); 144 throw new AndroidException("Can't call activity manager; is the system running?"); 145 } finally { 146 cb.mActive = false; 147 } 148 } 149 runInstrument()150 public void runInstrument() throws Exception { 151 Instrument instrument = new Instrument(mAm, mPm); 152 153 String opt; 154 while ((opt=nextOption()) != null) { 155 if (opt.equals("-p")) { 156 instrument.profileFile = nextArgRequired(); 157 } else if (opt.equals("-w")) { 158 instrument.wait = true; 159 } else if (opt.equals("-r")) { 160 instrument.rawMode = true; 161 } else if (opt.equals("-m")) { 162 instrument.proto = true; 163 } else if (opt.equals("-e")) { 164 final String argKey = nextArgRequired(); 165 final String argValue = nextArgRequired(); 166 instrument.args.putString(argKey, argValue); 167 } else if (opt.equals("--no_window_animation") 168 || opt.equals("--no-window-animation")) { 169 instrument.noWindowAnimation = true; 170 } else if (opt.equals("--user")) { 171 instrument.userId = parseUserArg(nextArgRequired()); 172 } else if (opt.equals("--abi")) { 173 instrument.abi = nextArgRequired(); 174 } else { 175 System.err.println("Error: Unknown option: " + opt); 176 return; 177 } 178 } 179 180 if (instrument.userId == UserHandle.USER_ALL) { 181 System.err.println("Error: Can't start instrumentation with user 'all'"); 182 return; 183 } 184 185 instrument.componentNameArg = nextArgRequired(); 186 187 instrument.run(); 188 } 189 } 190