Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -332,6 +332,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/os/IDropBoxManagerService.aidl \ core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \ core/java/com/android/internal/os/IResultReceiver.aidl \ core/java/com/android/internal/os/IShellCallback.aidl \ core/java/com/android/internal/statusbar/IStatusBar.aidl \ core/java/com/android/internal/statusbar/IStatusBarService.aidl \ core/java/com/android/internal/textservice/ISpellCheckerService.aidl \ Loading cmds/am/src/com/android/commands/am/Am.java +51 −216 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import android.app.ActivityManager; import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityContainer; import android.app.IActivityController; import android.app.IActivityManager; Loading @@ -46,7 +45,6 @@ import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Rect; Loading @@ -55,10 +53,11 @@ import android.os.Build; import android.os.Bundle; 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.ShellCommand; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; Loading @@ -72,6 +71,7 @@ import com.android.internal.util.Preconditions; import java.io.BufferedReader; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; Loading @@ -96,6 +96,7 @@ public class Am extends BaseCommand { // Amount we reduce the stack size by when testing a task re-size. private static final int STACK_BOUNDS_INSET = 10; public static final String NO_CLASS_ERROR_CODE = "Error type 3"; private IActivityManager mAm; private IPackageManager mPm; Loading Loading @@ -198,7 +199,7 @@ public class Am extends BaseCommand { " --track-allocation: enable tracking of object allocations\n" + " --user <USER_ID> | current: Specify which user to run as; if not\n" + " specified then run as the current user.\n" + " --stack <STACK_ID>: Specify into which stack should the activity be put." + " --stack <STACK_ID>: Specify into which stack should the activity be put.\n" + "\n" + "am startservice: start a Service. Options are:\n" + " --user <USER_ID> | current: Specify which user to run as; if not\n" + Loading Loading @@ -385,17 +386,13 @@ public class Am extends BaseCommand { String op = nextArgRequired(); if (op.equals("start")) { runStart(); runAmCmd(getRawArgs()); } else if (op.equals("startservice")) { runStartService(); } else if (op.equals("stopservice")) { runStopService(); } else if (op.equals("force-stop")) { runForceStop(); } else if (op.equals("kill")) { runKill(); } else if (op.equals("kill-all")) { runKillAll(); } else if (op.equals("force-stop") || op.equals("kill") || op.equals("kill-all")) { runAmCmd(getRawArgs()); } else if (op.equals("instrument")) { runInstrument(); } else if (op.equals("trace-ipc")) { Loading Loading @@ -475,6 +472,49 @@ public class Am extends BaseCommand { return userId; } static final class MyShellCallback extends ShellCallback { @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { 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 { try { mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, new MyShellCallback(), 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?"); } } private Intent makeIntent(int defUser) throws URISyntaxException { mStartFlags = 0; mWaitOption = false; Loading Loading @@ -558,211 +598,6 @@ public class Am extends BaseCommand { } } private void runStart() throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); if (mUserId == UserHandle.USER_ALL) { System.err.println("Error: Can't start service with user 'all'"); return; } String mimeType = intent.getType(); if (mimeType == null && intent.getData() != null && "content".equals(intent.getData().getScheme())) { mimeType = mAm.getProviderMimeType(intent.getData(), mUserId); } do { if (mStopOption) { String packageName; if (intent.getComponent() != null) { packageName = intent.getComponent().getPackageName(); } else { List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0, mUserId).getList(); if (activities == null || activities.size() <= 0) { System.err.println("Error: Intent does not match any activities: " + intent); return; } else if (activities.size() > 1) { System.err.println("Error: Intent matches multiple activities; can't stop: " + intent); return; } packageName = activities.get(0).activityInfo.packageName; } System.out.println("Stopping: " + packageName); mAm.forceStopPackage(packageName, mUserId); Thread.sleep(250); } System.out.println("Starting: " + intent); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ParcelFileDescriptor fd = null; ProfilerInfo profilerInfo = null; if (mProfileFile != null) { try { fd = openForSystemServer( new File(mProfileFile), ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_TRUNCATE | ParcelFileDescriptor.MODE_WRITE_ONLY); } catch (FileNotFoundException e) { System.err.println("Error: Unable to open file: " + mProfileFile); System.err.println("Consider using a file under /data/local/tmp/"); return; } profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop); } IActivityManager.WaitResult result = null; int res; final long startTime = SystemClock.uptimeMillis(); ActivityOptions options = null; if (mStackId != INVALID_STACK_ID) { options = ActivityOptions.makeBasic(); options.setLaunchStackId(mStackId); } if (mWaitOption) { result = mAm.startActivityAndWait(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); res = result.result; } else { res = mAm.startActivityAsUser(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); } final long endTime = SystemClock.uptimeMillis(); PrintStream out = mWaitOption ? System.out : System.err; boolean launched = false; switch (res) { case ActivityManager.START_SUCCESS: launched = true; break; case ActivityManager.START_SWITCHES_CANCELED: launched = true; out.println( "Warning: Activity not started because the " + " current activity is being kept for the user."); break; case ActivityManager.START_DELIVERED_TO_TOP: launched = true; out.println( "Warning: Activity not started, intent has " + "been delivered to currently running " + "top-most instance."); break; case ActivityManager.START_RETURN_INTENT_TO_CALLER: launched = true; out.println( "Warning: Activity not started because intent " + "should be handled by the caller"); break; case ActivityManager.START_TASK_TO_FRONT: launched = true; out.println( "Warning: Activity not started, its current " + "task has been brought to the front"); break; case ActivityManager.START_INTENT_NOT_RESOLVED: out.println( "Error: Activity not started, unable to " + "resolve " + intent.toString()); break; case ActivityManager.START_CLASS_NOT_FOUND: out.println(NO_CLASS_ERROR_CODE); out.println("Error: Activity class " + intent.getComponent().toShortString() + " does not exist."); break; case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: out.println( "Error: Activity not started, you requested to " + "both forward and receive its result"); break; case ActivityManager.START_PERMISSION_DENIED: out.println( "Error: Activity not started, you do not " + "have permission to access it."); break; case ActivityManager.START_NOT_VOICE_COMPATIBLE: out.println( "Error: Activity not started, voice control not allowed for: " + intent); break; case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY: out.println( "Error: Not allowed to start background user activity" + " that shouldn't be displayed for all users."); break; default: out.println( "Error: Activity not started, unknown error code " + res); break; } if (mWaitOption && launched) { if (result == null) { result = new IActivityManager.WaitResult(); result.who = intent.getComponent(); } System.out.println("Status: " + (result.timeout ? "timeout" : "ok")); if (result.who != null) { System.out.println("Activity: " + result.who.flattenToShortString()); } if (result.thisTime >= 0) { System.out.println("ThisTime: " + result.thisTime); } if (result.totalTime >= 0) { System.out.println("TotalTime: " + result.totalTime); } System.out.println("WaitTime: " + (endTime-startTime)); System.out.println("Complete"); } mRepeat--; if (mRepeat > 0) { mAm.unhandledBack(); } } while (mRepeat > 0); } private void runForceStop() throws Exception { int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("--user")) { userId = parseUserArg(nextArgRequired()); } else { System.err.println("Error: Unknown option: " + opt); return; } } mAm.forceStopPackage(nextArgRequired(), userId); } private void runKill() throws Exception { int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("--user")) { userId = parseUserArg(nextArgRequired()); } else { System.err.println("Error: Unknown option: " + opt); return; } } mAm.killBackgroundProcesses(nextArgRequired(), userId); } private void runKillAll() throws Exception { mAm.killAllBackgroundProcesses(); } private void sendBroadcast() throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); IntentReceiver receiver = new IntentReceiver(); Loading cmds/pm/src/com/android/commands/pm/Pm.java +37 −1 Original line number Diff line number Diff line Loading @@ -49,9 +49,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IUserManager; 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.SystemClock; import android.os.UserHandle; import android.os.UserManager; Loading @@ -68,6 +71,7 @@ import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; Loading Loading @@ -284,13 +288,45 @@ public final class Pm { } } static final class MyShellCallback extends ShellCallback { @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { File file = new File(path); 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; } } private int runShellCommand(String serviceName, String[] args) { final HandlerThread handlerThread = new HandlerThread("results"); handlerThread.start(); try { ServiceManager.getService(serviceName).shellCommand( FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, new ResultReceiver(new Handler(handlerThread.getLooper()))); args, new MyShellCallback(), new ResultReceiver(new Handler(handlerThread.getLooper()))); return 0; } catch (RemoteException e) { e.printStackTrace(); Loading core/java/android/os/Binder.java +10 −6 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import libcore.io.IoUtils; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; Loading Loading @@ -361,13 +360,14 @@ public class Binder implements IBinder { ParcelFileDescriptor out = data.readFileDescriptor(); ParcelFileDescriptor err = data.readFileDescriptor(); String[] args = data.readStringArray(); ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data); ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data); try { if (out != null) { shellCommand(in != null ? in.getFileDescriptor() : null, out.getFileDescriptor(), err != null ? err.getFileDescriptor() : out.getFileDescriptor(), args, resultReceiver); args, shellCallback, resultReceiver); } } finally { IoUtils.closeQuietly(in); Loading Loading @@ -459,13 +459,15 @@ public class Binder implements IBinder { * @param out The raw file descriptor that normal command messages should be written to. * @param err The raw file descriptor that command error messages should be written to. * @param args Command-line arguments. * @param callback Callback through which to interact with the invoking shell. * @param resultReceiver Called when the command has finished executing, with the result code. * @throws RemoteException * @hide */ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { onShellCommand(in, out, err, args, resultReceiver); String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { onShellCommand(in, out, err, args, callback, resultReceiver); } /** Loading @@ -477,7 +479,7 @@ public class Binder implements IBinder { * @hide */ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { FileOutputStream fout = new FileOutputStream(err != null ? err : out); PrintWriter pw = new FastPrintWriter(fout); pw.println("No shell command implementation."); Loading Loading @@ -650,13 +652,15 @@ final class BinderProxy implements IBinder { } public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeFileDescriptor(in); data.writeFileDescriptor(out); data.writeFileDescriptor(err); data.writeStringArray(args); ShellCallback.writeToParcel(callback, data); resultReceiver.writeToParcel(data, 0); try { transact(SHELL_COMMAND_TRANSACTION, data, reply, 0); Loading core/java/android/os/IBinder.java +3 −1 Original line number Diff line number Diff line Loading @@ -220,11 +220,13 @@ public interface IBinder { * @param out The raw file descriptor that normal command messages should be written to. * @param err The raw file descriptor that command error messages should be written to. * @param args Command-line arguments. * @param shellCallback Optional callback to the caller's shell to perform operations in it. * @param resultReceiver Called when the command has finished executing, with the result code. * @hide */ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException; String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) throws RemoteException; /** * Perform a generic operation with the object. Loading Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -332,6 +332,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/os/IDropBoxManagerService.aidl \ core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \ core/java/com/android/internal/os/IResultReceiver.aidl \ core/java/com/android/internal/os/IShellCallback.aidl \ core/java/com/android/internal/statusbar/IStatusBar.aidl \ core/java/com/android/internal/statusbar/IStatusBarService.aidl \ core/java/com/android/internal/textservice/ISpellCheckerService.aidl \ Loading
cmds/am/src/com/android/commands/am/Am.java +51 −216 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import android.app.ActivityManager; import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityContainer; import android.app.IActivityController; import android.app.IActivityManager; Loading @@ -46,7 +45,6 @@ import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.Rect; Loading @@ -55,10 +53,11 @@ import android.os.Build; import android.os.Bundle; 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.ShellCommand; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; Loading @@ -72,6 +71,7 @@ import com.android.internal.util.Preconditions; import java.io.BufferedReader; import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; Loading @@ -96,6 +96,7 @@ public class Am extends BaseCommand { // Amount we reduce the stack size by when testing a task re-size. private static final int STACK_BOUNDS_INSET = 10; public static final String NO_CLASS_ERROR_CODE = "Error type 3"; private IActivityManager mAm; private IPackageManager mPm; Loading Loading @@ -198,7 +199,7 @@ public class Am extends BaseCommand { " --track-allocation: enable tracking of object allocations\n" + " --user <USER_ID> | current: Specify which user to run as; if not\n" + " specified then run as the current user.\n" + " --stack <STACK_ID>: Specify into which stack should the activity be put." + " --stack <STACK_ID>: Specify into which stack should the activity be put.\n" + "\n" + "am startservice: start a Service. Options are:\n" + " --user <USER_ID> | current: Specify which user to run as; if not\n" + Loading Loading @@ -385,17 +386,13 @@ public class Am extends BaseCommand { String op = nextArgRequired(); if (op.equals("start")) { runStart(); runAmCmd(getRawArgs()); } else if (op.equals("startservice")) { runStartService(); } else if (op.equals("stopservice")) { runStopService(); } else if (op.equals("force-stop")) { runForceStop(); } else if (op.equals("kill")) { runKill(); } else if (op.equals("kill-all")) { runKillAll(); } else if (op.equals("force-stop") || op.equals("kill") || op.equals("kill-all")) { runAmCmd(getRawArgs()); } else if (op.equals("instrument")) { runInstrument(); } else if (op.equals("trace-ipc")) { Loading Loading @@ -475,6 +472,49 @@ public class Am extends BaseCommand { return userId; } static final class MyShellCallback extends ShellCallback { @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { 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 { try { mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, new MyShellCallback(), 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?"); } } private Intent makeIntent(int defUser) throws URISyntaxException { mStartFlags = 0; mWaitOption = false; Loading Loading @@ -558,211 +598,6 @@ public class Am extends BaseCommand { } } private void runStart() throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); if (mUserId == UserHandle.USER_ALL) { System.err.println("Error: Can't start service with user 'all'"); return; } String mimeType = intent.getType(); if (mimeType == null && intent.getData() != null && "content".equals(intent.getData().getScheme())) { mimeType = mAm.getProviderMimeType(intent.getData(), mUserId); } do { if (mStopOption) { String packageName; if (intent.getComponent() != null) { packageName = intent.getComponent().getPackageName(); } else { List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0, mUserId).getList(); if (activities == null || activities.size() <= 0) { System.err.println("Error: Intent does not match any activities: " + intent); return; } else if (activities.size() > 1) { System.err.println("Error: Intent matches multiple activities; can't stop: " + intent); return; } packageName = activities.get(0).activityInfo.packageName; } System.out.println("Stopping: " + packageName); mAm.forceStopPackage(packageName, mUserId); Thread.sleep(250); } System.out.println("Starting: " + intent); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ParcelFileDescriptor fd = null; ProfilerInfo profilerInfo = null; if (mProfileFile != null) { try { fd = openForSystemServer( new File(mProfileFile), ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_TRUNCATE | ParcelFileDescriptor.MODE_WRITE_ONLY); } catch (FileNotFoundException e) { System.err.println("Error: Unable to open file: " + mProfileFile); System.err.println("Consider using a file under /data/local/tmp/"); return; } profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop); } IActivityManager.WaitResult result = null; int res; final long startTime = SystemClock.uptimeMillis(); ActivityOptions options = null; if (mStackId != INVALID_STACK_ID) { options = ActivityOptions.makeBasic(); options.setLaunchStackId(mStackId); } if (mWaitOption) { result = mAm.startActivityAndWait(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); res = result.result; } else { res = mAm.startActivityAsUser(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); } final long endTime = SystemClock.uptimeMillis(); PrintStream out = mWaitOption ? System.out : System.err; boolean launched = false; switch (res) { case ActivityManager.START_SUCCESS: launched = true; break; case ActivityManager.START_SWITCHES_CANCELED: launched = true; out.println( "Warning: Activity not started because the " + " current activity is being kept for the user."); break; case ActivityManager.START_DELIVERED_TO_TOP: launched = true; out.println( "Warning: Activity not started, intent has " + "been delivered to currently running " + "top-most instance."); break; case ActivityManager.START_RETURN_INTENT_TO_CALLER: launched = true; out.println( "Warning: Activity not started because intent " + "should be handled by the caller"); break; case ActivityManager.START_TASK_TO_FRONT: launched = true; out.println( "Warning: Activity not started, its current " + "task has been brought to the front"); break; case ActivityManager.START_INTENT_NOT_RESOLVED: out.println( "Error: Activity not started, unable to " + "resolve " + intent.toString()); break; case ActivityManager.START_CLASS_NOT_FOUND: out.println(NO_CLASS_ERROR_CODE); out.println("Error: Activity class " + intent.getComponent().toShortString() + " does not exist."); break; case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: out.println( "Error: Activity not started, you requested to " + "both forward and receive its result"); break; case ActivityManager.START_PERMISSION_DENIED: out.println( "Error: Activity not started, you do not " + "have permission to access it."); break; case ActivityManager.START_NOT_VOICE_COMPATIBLE: out.println( "Error: Activity not started, voice control not allowed for: " + intent); break; case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY: out.println( "Error: Not allowed to start background user activity" + " that shouldn't be displayed for all users."); break; default: out.println( "Error: Activity not started, unknown error code " + res); break; } if (mWaitOption && launched) { if (result == null) { result = new IActivityManager.WaitResult(); result.who = intent.getComponent(); } System.out.println("Status: " + (result.timeout ? "timeout" : "ok")); if (result.who != null) { System.out.println("Activity: " + result.who.flattenToShortString()); } if (result.thisTime >= 0) { System.out.println("ThisTime: " + result.thisTime); } if (result.totalTime >= 0) { System.out.println("TotalTime: " + result.totalTime); } System.out.println("WaitTime: " + (endTime-startTime)); System.out.println("Complete"); } mRepeat--; if (mRepeat > 0) { mAm.unhandledBack(); } } while (mRepeat > 0); } private void runForceStop() throws Exception { int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("--user")) { userId = parseUserArg(nextArgRequired()); } else { System.err.println("Error: Unknown option: " + opt); return; } } mAm.forceStopPackage(nextArgRequired(), userId); } private void runKill() throws Exception { int userId = UserHandle.USER_ALL; String opt; while ((opt=nextOption()) != null) { if (opt.equals("--user")) { userId = parseUserArg(nextArgRequired()); } else { System.err.println("Error: Unknown option: " + opt); return; } } mAm.killBackgroundProcesses(nextArgRequired(), userId); } private void runKillAll() throws Exception { mAm.killAllBackgroundProcesses(); } private void sendBroadcast() throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); IntentReceiver receiver = new IntentReceiver(); Loading
cmds/pm/src/com/android/commands/pm/Pm.java +37 −1 Original line number Diff line number Diff line Loading @@ -49,9 +49,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IUserManager; 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.SystemClock; import android.os.UserHandle; import android.os.UserManager; Loading @@ -68,6 +71,7 @@ import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; Loading Loading @@ -284,13 +288,45 @@ public final class Pm { } } static final class MyShellCallback extends ShellCallback { @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) { File file = new File(path); 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; } } private int runShellCommand(String serviceName, String[] args) { final HandlerThread handlerThread = new HandlerThread("results"); handlerThread.start(); try { ServiceManager.getService(serviceName).shellCommand( FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, new ResultReceiver(new Handler(handlerThread.getLooper()))); args, new MyShellCallback(), new ResultReceiver(new Handler(handlerThread.getLooper()))); return 0; } catch (RemoteException e) { e.printStackTrace(); Loading
core/java/android/os/Binder.java +10 −6 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import libcore.io.IoUtils; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; Loading Loading @@ -361,13 +360,14 @@ public class Binder implements IBinder { ParcelFileDescriptor out = data.readFileDescriptor(); ParcelFileDescriptor err = data.readFileDescriptor(); String[] args = data.readStringArray(); ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data); ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data); try { if (out != null) { shellCommand(in != null ? in.getFileDescriptor() : null, out.getFileDescriptor(), err != null ? err.getFileDescriptor() : out.getFileDescriptor(), args, resultReceiver); args, shellCallback, resultReceiver); } } finally { IoUtils.closeQuietly(in); Loading Loading @@ -459,13 +459,15 @@ public class Binder implements IBinder { * @param out The raw file descriptor that normal command messages should be written to. * @param err The raw file descriptor that command error messages should be written to. * @param args Command-line arguments. * @param callback Callback through which to interact with the invoking shell. * @param resultReceiver Called when the command has finished executing, with the result code. * @throws RemoteException * @hide */ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { onShellCommand(in, out, err, args, resultReceiver); String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { onShellCommand(in, out, err, args, callback, resultReceiver); } /** Loading @@ -477,7 +479,7 @@ public class Binder implements IBinder { * @hide */ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { FileOutputStream fout = new FileOutputStream(err != null ? err : out); PrintWriter pw = new FastPrintWriter(fout); pw.println("No shell command implementation."); Loading Loading @@ -650,13 +652,15 @@ final class BinderProxy implements IBinder { } public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException { String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeFileDescriptor(in); data.writeFileDescriptor(out); data.writeFileDescriptor(err); data.writeStringArray(args); ShellCallback.writeToParcel(callback, data); resultReceiver.writeToParcel(data, 0); try { transact(SHELL_COMMAND_TRANSACTION, data, reply, 0); Loading
core/java/android/os/IBinder.java +3 −1 Original line number Diff line number Diff line Loading @@ -220,11 +220,13 @@ public interface IBinder { * @param out The raw file descriptor that normal command messages should be written to. * @param err The raw file descriptor that command error messages should be written to. * @param args Command-line arguments. * @param shellCallback Optional callback to the caller's shell to perform operations in it. * @param resultReceiver Called when the command has finished executing, with the result code. * @hide */ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ResultReceiver resultReceiver) throws RemoteException; String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) throws RemoteException; /** * Perform a generic operation with the object. Loading