| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.commands.am; |
| |
| import android.app.ActivityManager; |
| import android.app.IActivityManager; |
| import android.content.pm.IPackageManager; |
| import android.os.ParcelFileDescriptor; |
| import android.os.RemoteException; |
| import android.os.ResultReceiver; |
| import android.os.SELinux; |
| import android.os.ServiceManager; |
| import android.os.ShellCallback; |
| import android.os.UserHandle; |
| import android.util.AndroidException; |
| |
| import com.android.internal.os.BaseCommand; |
| |
| import java.io.File; |
| import java.io.FileDescriptor; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| |
| public class Am extends BaseCommand { |
| |
| private IActivityManager mAm; |
| private IPackageManager mPm; |
| |
| /** |
| * Command-line entry point. |
| * |
| * @param args The command-line arguments |
| */ |
| public static void main(String[] args) { |
| (new Am()).run(args); |
| } |
| |
| @Override |
| public void onShowUsage(PrintStream out) { |
| try { |
| runAmCmd(new String[] { "help" }); |
| } catch (AndroidException e) { |
| e.printStackTrace(System.err); |
| } |
| } |
| |
| @Override |
| public void onRun() throws Exception { |
| |
| mAm = ActivityManager.getService(); |
| if (mAm == null) { |
| System.err.println(NO_SYSTEM_ERROR_CODE); |
| throw new AndroidException("Can't connect to activity manager; is the system running?"); |
| } |
| |
| mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); |
| if (mPm == null) { |
| System.err.println(NO_SYSTEM_ERROR_CODE); |
| throw new AndroidException("Can't connect to package manager; is the system running?"); |
| } |
| |
| String op = nextArgRequired(); |
| |
| if (op.equals("instrument")) { |
| runInstrument(); |
| } else { |
| runAmCmd(getRawArgs()); |
| } |
| } |
| |
| int parseUserArg(String arg) { |
| int userId; |
| if ("all".equals(arg)) { |
| userId = UserHandle.USER_ALL; |
| } else if ("current".equals(arg) || "cur".equals(arg)) { |
| userId = UserHandle.USER_CURRENT; |
| } else { |
| userId = Integer.parseInt(arg); |
| } |
| return userId; |
| } |
| |
| static final class MyShellCallback extends ShellCallback { |
| boolean mActive = true; |
| |
| @Override public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, |
| String mode) { |
| if (!mActive) { |
| System.err.println("Open attempt after active for: " + path); |
| return null; |
| } |
| File file = new File(path); |
| //System.err.println("Opening file: " + file.getAbsolutePath()); |
| //Log.i("Am", "Opening file: " + file.getAbsolutePath()); |
| final ParcelFileDescriptor fd; |
| try { |
| fd = ParcelFileDescriptor.open(file, |
| ParcelFileDescriptor.MODE_CREATE | |
| ParcelFileDescriptor.MODE_TRUNCATE | |
| ParcelFileDescriptor.MODE_WRITE_ONLY); |
| } catch (FileNotFoundException e) { |
| String msg = "Unable to open file " + path + ": " + e; |
| System.err.println(msg); |
| throw new IllegalArgumentException(msg); |
| } |
| if (seLinuxContext != null) { |
| final String tcon = SELinux.getFileContext(file.getAbsolutePath()); |
| if (!SELinux.checkSELinuxAccess(seLinuxContext, tcon, "file", "write")) { |
| try { |
| fd.close(); |
| } catch (IOException e) { |
| } |
| String msg = "System server has no access to file context " + tcon; |
| System.err.println(msg + " (from path " + file.getAbsolutePath() |
| + ", context " + seLinuxContext + ")"); |
| throw new IllegalArgumentException(msg); |
| } |
| } |
| return fd; |
| } |
| } |
| |
| void runAmCmd(String[] args) throws AndroidException { |
| final MyShellCallback cb = new MyShellCallback(); |
| try { |
| mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, |
| args, cb, new ResultReceiver(null) { }); |
| } catch (RemoteException e) { |
| System.err.println(NO_SYSTEM_ERROR_CODE); |
| throw new AndroidException("Can't call activity manager; is the system running?"); |
| } finally { |
| cb.mActive = false; |
| } |
| } |
| |
| public void runInstrument() throws Exception { |
| Instrument instrument = new Instrument(mAm, mPm); |
| |
| String opt; |
| while ((opt=nextOption()) != null) { |
| if (opt.equals("-p")) { |
| instrument.profileFile = nextArgRequired(); |
| } else if (opt.equals("-w")) { |
| instrument.wait = true; |
| } else if (opt.equals("-r")) { |
| instrument.rawMode = true; |
| } else if (opt.equals("-m")) { |
| instrument.protoStd = true; |
| } else if (opt.equals("-f")) { |
| instrument.protoFile = true; |
| if (peekNextArg() != null && !peekNextArg().startsWith("-")) |
| instrument.logPath = nextArg(); |
| } else if (opt.equals("-e")) { |
| final String argKey = nextArgRequired(); |
| final String argValue = nextArgRequired(); |
| instrument.args.putString(argKey, argValue); |
| } else if (opt.equals("--no_window_animation") |
| || opt.equals("--no-window-animation")) { |
| instrument.noWindowAnimation = true; |
| } else if (opt.equals("--user")) { |
| instrument.userId = parseUserArg(nextArgRequired()); |
| } else if (opt.equals("--abi")) { |
| instrument.abi = nextArgRequired(); |
| } else { |
| System.err.println("Error: Unknown option: " + opt); |
| return; |
| } |
| } |
| |
| if (instrument.userId == UserHandle.USER_ALL) { |
| System.err.println("Error: Can't start instrumentation with user 'all'"); |
| return; |
| } |
| |
| instrument.componentNameArg = nextArgRequired(); |
| |
| instrument.run(); |
| } |
| } |