1/*
2 * Copyright (C) 2015 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
17package com.android.server.am;
18
19import android.app.ActivityManager;
20import android.app.IActivityManager;
21import android.os.RemoteException;
22import android.os.ShellCommand;
23import android.os.UserHandle;
24import android.util.DebugUtils;
25
26import java.io.PrintWriter;
27
28class ActivityManagerShellCommand extends ShellCommand {
29    // IPC interface to activity manager -- don't need to do additional security checks.
30    final IActivityManager mInterface;
31
32    // Internal service impl -- must perform security checks before touching.
33    final ActivityManagerService mInternal;
34
35    final boolean mDumping;
36
37    ActivityManagerShellCommand(ActivityManagerService service, boolean dumping) {
38        mInterface = service;
39        mInternal = service;
40        mDumping = dumping;
41    }
42
43    @Override
44    public int onCommand(String cmd) {
45        if (cmd == null) {
46            return handleDefaultCommands(cmd);
47        }
48        PrintWriter pw = getOutPrintWriter();
49        try {
50            switch (cmd) {
51                case "force-stop":
52                    return runForceStop(pw);
53                case "kill":
54                    return runKill(pw);
55                case "kill-all":
56                    return runKillAll(pw);
57                case "write":
58                    return runWrite(pw);
59                case "track-associations":
60                    return runTrackAssociations(pw);
61                case "untrack-associations":
62                    return runUntrackAssociations(pw);
63                case "is-user-stopped":
64                    return runIsUserStopped(pw);
65                case "lenient-background-check":
66                    return runLenientBackgroundCheck(pw);
67                case "get-uid-state":
68                    return getUidState(pw);
69                default:
70                    return handleDefaultCommands(cmd);
71            }
72        } catch (RemoteException e) {
73            pw.println("Remote exception: " + e);
74        }
75        return -1;
76    }
77
78    int runIsUserStopped(PrintWriter pw) {
79        int userId = UserHandle.parseUserArg(getNextArgRequired());
80        boolean stopped = mInternal.isUserStopped(userId);
81        pw.println(stopped);
82        return 0;
83    }
84
85    int runForceStop(PrintWriter pw) throws RemoteException {
86        int userId = UserHandle.USER_ALL;
87
88        String opt;
89        while ((opt = getNextOption()) != null) {
90            if (opt.equals("--user")) {
91                userId = UserHandle.parseUserArg(getNextArgRequired());
92            } else {
93                pw.println("Error: Unknown option: " + opt);
94                return -1;
95            }
96        }
97        mInterface.forceStopPackage(getNextArgRequired(), userId);
98        return 0;
99    }
100
101    int runKill(PrintWriter pw) throws RemoteException {
102        int userId = UserHandle.USER_ALL;
103
104        String opt;
105        while ((opt=getNextOption()) != null) {
106            if (opt.equals("--user")) {
107                userId = UserHandle.parseUserArg(getNextArgRequired());
108            } else {
109                pw.println("Error: Unknown option: " + opt);
110                return -1;
111            }
112        }
113        mInterface.killBackgroundProcesses(getNextArgRequired(), userId);
114        return 0;
115    }
116
117    int runKillAll(PrintWriter pw) throws RemoteException {
118        mInterface.killAllBackgroundProcesses();
119        return 0;
120    }
121
122    int runWrite(PrintWriter pw) {
123        mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
124                "registerUidObserver()");
125        mInternal.mRecentTasks.flush();
126        pw.println("All tasks persisted.");
127        return 0;
128    }
129
130    int runTrackAssociations(PrintWriter pw) {
131        mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
132                "registerUidObserver()");
133        synchronized (mInternal) {
134            if (!mInternal.mTrackingAssociations) {
135                mInternal.mTrackingAssociations = true;
136                pw.println("Association tracking started.");
137            } else {
138                pw.println("Association tracking already enabled.");
139            }
140        }
141        return 0;
142    }
143
144    int runUntrackAssociations(PrintWriter pw) {
145        mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
146                "registerUidObserver()");
147        synchronized (mInternal) {
148            if (mInternal.mTrackingAssociations) {
149                mInternal.mTrackingAssociations = false;
150                mInternal.mAssociations.clear();
151                pw.println("Association tracking stopped.");
152            } else {
153                pw.println("Association tracking not running.");
154            }
155        }
156        return 0;
157    }
158
159    int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException {
160        String arg = getNextArg();
161        if (arg != null) {
162            boolean state = Boolean.valueOf(arg) || "1".equals(arg);
163            mInterface.setLenientBackgroundCheck(state);
164        }
165        synchronized (mInternal) {
166            if (mInternal.mLenientBackgroundCheck) {
167                pw.println("Lenient background check enabled");
168            } else {
169                pw.println("Lenient background check disabled");
170            }
171        }
172        return 0;
173    }
174
175    int getUidState(PrintWriter pw) throws RemoteException {
176        mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
177                "getUidState()");
178        int state = mInternal.getUidState(Integer.parseInt(getNextArgRequired()));
179        pw.print(state);
180        pw.print(" (");
181        pw.printf(DebugUtils.valueToString(ActivityManager.class, "PROCESS_STATE_", state));
182        pw.println(")");
183        return 0;
184    }
185
186    @Override
187    public void onHelp() {
188        PrintWriter pw = getOutPrintWriter();
189        dumpHelp(pw, mDumping);
190    }
191
192    static void dumpHelp(PrintWriter pw, boolean dumping) {
193        if (dumping) {
194            pw.println("Activity manager dump options:");
195            pw.println("  [-a] [-c] [-p PACKAGE] [-h] [WHAT] ...");
196            pw.println("  WHAT may be one of:");
197            pw.println("    a[ctivities]: activity stack state");
198            pw.println("    r[recents]: recent activities state");
199            pw.println("    b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
200            pw.println("    broadcast-stats [PACKAGE_NAME]: aggregated broadcast statistics");
201            pw.println("    i[ntents] [PACKAGE_NAME]: pending intent state");
202            pw.println("    p[rocesses] [PACKAGE_NAME]: process state");
203            pw.println("    o[om]: out of memory management");
204            pw.println("    perm[issions]: URI permission grant state");
205            pw.println("    prov[iders] [COMP_SPEC ...]: content provider state");
206            pw.println("    provider [COMP_SPEC]: provider client-side state");
207            pw.println("    s[ervices] [COMP_SPEC ...]: service state");
208            pw.println("    as[sociations]: tracked app associations");
209            pw.println("    service [COMP_SPEC]: service client-side state");
210            pw.println("    package [PACKAGE_NAME]: all state related to given package");
211            pw.println("    all: dump all activities");
212            pw.println("    top: dump the top activity");
213            pw.println("  WHAT may also be a COMP_SPEC to dump activities.");
214            pw.println("  COMP_SPEC may be a component name (com.foo/.myApp),");
215            pw.println("    a partial substring in a component name, a");
216            pw.println("    hex object identifier.");
217            pw.println("  -a: include all available server state.");
218            pw.println("  -c: include client state.");
219            pw.println("  -p: limit output to given package.");
220            pw.println("  --checkin: output checkin format, resetting data.");
221            pw.println("  --C: output checkin format, not resetting data.");
222        } else {
223            pw.println("Activity manager (activity) commands:");
224            pw.println("  help");
225            pw.println("    Print this help text.");
226            pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
227            pw.println("    Completely stop the given application package.");
228            pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
229            pw.println("    Kill all processes associated with the given application.");
230            pw.println("  kill-all");
231            pw.println("    Kill all processes that are safe to kill (cached, etc).");
232            pw.println("  write");
233            pw.println("    Write all pending state to storage.");
234            pw.println("  track-associations");
235            pw.println("    Enable association tracking.");
236            pw.println("  untrack-associations");
237            pw.println("    Disable and clear association tracking.");
238            pw.println("  is-user-stopped <USER_ID>");
239            pw.println("    Returns whether <USER_ID> has been stopped or not.");
240            pw.println("  lenient-background-check [<true|false>]");
241            pw.println("    Optionally controls lenient background check mode, returns current mode.");
242            pw.println("  get-uid-state <UID>");
243            pw.println("    Gets the process state of an app given its <UID>.");
244        }
245    }
246}
247