| /* |
| * Copyright (C) 2015 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.server.am; |
| |
| import android.app.IActivityManager; |
| import android.os.RemoteException; |
| import android.os.ShellCommand; |
| import android.os.UserHandle; |
| |
| import com.android.internal.util.ArrayUtils; |
| |
| import java.io.PrintWriter; |
| |
| class ActivityManagerShellCommand extends ShellCommand { |
| // IPC interface to activity manager -- don't need to do additional security checks. |
| final IActivityManager mInterface; |
| |
| // Internal service impl -- must perform security checks before touching. |
| final ActivityManagerService mInternal; |
| |
| final boolean mDumping; |
| |
| ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) { |
| mInterface = service; |
| mInternal = service; |
| mDumping = dumping; |
| } |
| |
| @Override |
| public int onCommand(String cmd) { |
| if (cmd == null) { |
| return handleDefaultCommands(cmd); |
| } |
| PrintWriter pw = getOutPrintWriter(); |
| try { |
| switch (cmd) { |
| case "force-stop": |
| return runForceStop(pw); |
| case "kill": |
| return runKill(pw); |
| case "kill-all": |
| return runKillAll(pw); |
| case "write": |
| return runWrite(pw); |
| case "track-associations": |
| return runTrackAssociations(pw); |
| case "untrack-associations": |
| return runUntrackAssociations(pw); |
| case "is-user-stopped": |
| return runIsUserStopped(pw); |
| case "lenient-background-check": |
| return runLenientBackgroundCheck(pw); |
| default: |
| return handleDefaultCommands(cmd); |
| } |
| } catch (RemoteException e) { |
| pw.println("Remote exception: " + e); |
| } |
| return -1; |
| } |
| |
| int runIsUserStopped(PrintWriter pw) { |
| int userId = UserHandle.parseUserArg(getNextArgRequired()); |
| boolean stopped = mInternal.isUserStopped(userId); |
| pw.println(stopped); |
| return 0; |
| } |
| |
| int runForceStop(PrintWriter pw) throws RemoteException { |
| int userId = UserHandle.USER_ALL; |
| |
| String opt; |
| while ((opt = getNextOption()) != null) { |
| if (opt.equals("--user")) { |
| userId = UserHandle.parseUserArg(getNextArgRequired()); |
| } else { |
| pw.println("Error: Unknown option: " + opt); |
| return -1; |
| } |
| } |
| mInterface.forceStopPackage(getNextArgRequired(), userId); |
| return 0; |
| } |
| |
| int runKill(PrintWriter pw) throws RemoteException { |
| int userId = UserHandle.USER_ALL; |
| |
| String opt; |
| while ((opt=getNextOption()) != null) { |
| if (opt.equals("--user")) { |
| userId = UserHandle.parseUserArg(getNextArgRequired()); |
| } else { |
| pw.println("Error: Unknown option: " + opt); |
| return -1; |
| } |
| } |
| mInterface.killBackgroundProcesses(getNextArgRequired(), userId); |
| return 0; |
| } |
| |
| int runKillAll(PrintWriter pw) throws RemoteException { |
| mInterface.killAllBackgroundProcesses(); |
| return 0; |
| } |
| |
| int runWrite(PrintWriter pw) { |
| mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, |
| "registerUidObserver()"); |
| mInternal.mRecentTasks.flush(); |
| pw.println("All tasks persisted."); |
| return 0; |
| } |
| |
| int runTrackAssociations(PrintWriter pw) { |
| mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, |
| "registerUidObserver()"); |
| synchronized (mInternal) { |
| if (!mInternal.mTrackingAssociations) { |
| mInternal.mTrackingAssociations = true; |
| pw.println("Association tracking started."); |
| } else { |
| pw.println("Association tracking already enabled."); |
| } |
| } |
| return 0; |
| } |
| |
| int runUntrackAssociations(PrintWriter pw) { |
| mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, |
| "registerUidObserver()"); |
| synchronized (mInternal) { |
| if (mInternal.mTrackingAssociations) { |
| mInternal.mTrackingAssociations = false; |
| mInternal.mAssociations.clear(); |
| pw.println("Association tracking stopped."); |
| } else { |
| pw.println("Association tracking not running."); |
| } |
| } |
| return 0; |
| } |
| |
| int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException { |
| String arg = getNextArg(); |
| if (arg != null) { |
| boolean state = Boolean.valueOf(arg) || "1".equals(arg); |
| mInterface.setLenientBackgroundCheck(state); |
| } |
| synchronized (mInternal) { |
| if (mInternal.mLenientBackgroundCheck) { |
| pw.println("Lenient background check enabled"); |
| } else { |
| pw.println("Lenient background check disabled"); |
| } |
| } |
| return 0; |
| } |
| |
| @Override |
| public void onHelp() { |
| PrintWriter pw = getOutPrintWriter(); |
| dumpHelp(pw, mDumping); |
| } |
| |
| static void dumpHelp(PrintWriter pw, boolean dumping) { |
| if (dumping) { |
| pw.println("Activity manager dump options:"); |
| pw.println(" [-a] [-c] [-p PACKAGE] [-h] [WHAT] ..."); |
| pw.println(" WHAT may be one of:"); |
| pw.println(" a[ctivities]: activity stack state"); |
| pw.println(" r[recents]: recent activities state"); |
| pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state"); |
| pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state"); |
| pw.println(" p[rocesses] [PACKAGE_NAME]: process state"); |
| pw.println(" o[om]: out of memory management"); |
| pw.println(" perm[issions]: URI permission grant state"); |
| pw.println(" prov[iders] [COMP_SPEC ...]: content provider state"); |
| pw.println(" provider [COMP_SPEC]: provider client-side state"); |
| pw.println(" s[ervices] [COMP_SPEC ...]: service state"); |
| pw.println(" as[sociations]: tracked app associations"); |
| pw.println(" service [COMP_SPEC]: service client-side state"); |
| pw.println(" package [PACKAGE_NAME]: all state related to given package"); |
| pw.println(" all: dump all activities"); |
| pw.println(" top: dump the top activity"); |
| pw.println(" WHAT may also be a COMP_SPEC to dump activities."); |
| pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),"); |
| pw.println(" a partial substring in a component name, a"); |
| pw.println(" hex object identifier."); |
| pw.println(" -a: include all available server state."); |
| pw.println(" -c: include client state."); |
| pw.println(" -p: limit output to given package."); |
| } else { |
| pw.println("Activity manager (activity) commands:"); |
| pw.println(" help"); |
| pw.println(" Print this help text."); |
| pw.println(" force-stop [--user <USER_ID> | all | current] <PACKAGE>"); |
| pw.println(" Complete stop the given application package."); |
| pw.println(" kill [--user <USER_ID> | all | current] <PACKAGE>"); |
| pw.println(" Kill all processes associated with the given application."); |
| pw.println(" kill-all"); |
| pw.println(" Kill all processes that are safe to kill (cached, etc)"); |
| pw.println(" write"); |
| pw.println(" Write all pending state to storage."); |
| pw.println(" track-associations"); |
| pw.println(" Enable association tracking."); |
| pw.println(" untrack-associations"); |
| pw.println(" Disable and clear association tracking."); |
| pw.println(" is-user-stopped <USER_ID>"); |
| pw.println(" returns whether <USER_ID> has been stopped or not"); |
| pw.println(" lenient-background-check [<true|false>]"); |
| pw.println(" optionally controls lenient background check mode, returns current mode."); |
| } |
| } |
| } |