15d346051bd6da471203fed94357f58491822a4ebChristopher Tate/*
25d346051bd6da471203fed94357f58491822a4ebChristopher Tate * Copyright (C) 2016 The Android Open Source Project
35d346051bd6da471203fed94357f58491822a4ebChristopher Tate *
45d346051bd6da471203fed94357f58491822a4ebChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
55d346051bd6da471203fed94357f58491822a4ebChristopher Tate * you may not use this file except in compliance with the License.
65d346051bd6da471203fed94357f58491822a4ebChristopher Tate * You may obtain a copy of the License at
75d346051bd6da471203fed94357f58491822a4ebChristopher Tate *
85d346051bd6da471203fed94357f58491822a4ebChristopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
95d346051bd6da471203fed94357f58491822a4ebChristopher Tate *
105d346051bd6da471203fed94357f58491822a4ebChristopher Tate * Unless required by applicable law or agreed to in writing, software
115d346051bd6da471203fed94357f58491822a4ebChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
125d346051bd6da471203fed94357f58491822a4ebChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d346051bd6da471203fed94357f58491822a4ebChristopher Tate * See the License for the specific language governing permissions and
145d346051bd6da471203fed94357f58491822a4ebChristopher Tate * limitations under the License
155d346051bd6da471203fed94357f58491822a4ebChristopher Tate */
165d346051bd6da471203fed94357f58491822a4ebChristopher Tate
175d346051bd6da471203fed94357f58491822a4ebChristopher Tatepackage com.android.server.job;
185d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackbornimport android.app.ActivityManager;
205d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.app.AppGlobals;
215d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.content.pm.IPackageManager;
225d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.content.pm.PackageManager;
235d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.os.Binder;
245d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.os.ShellCommand;
255d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport android.os.UserHandle;
265d346051bd6da471203fed94357f58491822a4ebChristopher Tate
275d346051bd6da471203fed94357f58491822a4ebChristopher Tateimport java.io.PrintWriter;
285d346051bd6da471203fed94357f58491822a4ebChristopher Tate
296466c1cc5efc4ff05fabdd670cf78a6a7ca45afbDianne Hackbornpublic final class JobSchedulerShellCommand extends ShellCommand {
305d346051bd6da471203fed94357f58491822a4ebChristopher Tate    public static final int CMD_ERR_NO_PACKAGE = -1000;
315d346051bd6da471203fed94357f58491822a4ebChristopher Tate    public static final int CMD_ERR_NO_JOB = -1001;
325d346051bd6da471203fed94357f58491822a4ebChristopher Tate    public static final int CMD_ERR_CONSTRAINTS = -1002;
335d346051bd6da471203fed94357f58491822a4ebChristopher Tate
345d346051bd6da471203fed94357f58491822a4ebChristopher Tate    JobSchedulerService mInternal;
355d346051bd6da471203fed94357f58491822a4ebChristopher Tate    IPackageManager mPM;
365d346051bd6da471203fed94357f58491822a4ebChristopher Tate
375d346051bd6da471203fed94357f58491822a4ebChristopher Tate    JobSchedulerShellCommand(JobSchedulerService service) {
385d346051bd6da471203fed94357f58491822a4ebChristopher Tate        mInternal = service;
395d346051bd6da471203fed94357f58491822a4ebChristopher Tate        mPM = AppGlobals.getPackageManager();
405d346051bd6da471203fed94357f58491822a4ebChristopher Tate    }
415d346051bd6da471203fed94357f58491822a4ebChristopher Tate
425d346051bd6da471203fed94357f58491822a4ebChristopher Tate    @Override
435d346051bd6da471203fed94357f58491822a4ebChristopher Tate    public int onCommand(String cmd) {
445d346051bd6da471203fed94357f58491822a4ebChristopher Tate        final PrintWriter pw = getOutPrintWriter();
455d346051bd6da471203fed94357f58491822a4ebChristopher Tate        try {
46a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            switch (cmd != null ? cmd : "") {
47a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                case "run":
48a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                    return runJob(pw);
4983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                case "timeout":
5083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return timeout(pw);
51a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                case "monitor-battery":
5283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return monitorBattery(pw);
53a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                case "get-battery-seq":
5483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return getBatterySeq(pw);
55a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                case "get-battery-charging":
5683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return getBatteryCharging(pw);
57a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                case "get-battery-not-low":
5883b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return getBatteryNotLow(pw);
59532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn                case "get-storage-seq":
6083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return getStorageSeq(pw);
61532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn                case "get-storage-not-low":
6283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return getStorageNotLow(pw);
636d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                case "get-job-state":
646d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                    return getJobState(pw);
65a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                default:
66a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                    return handleDefaultCommands(cmd);
675d346051bd6da471203fed94357f58491822a4ebChristopher Tate            }
685d346051bd6da471203fed94357f58491822a4ebChristopher Tate        } catch (Exception e) {
695d346051bd6da471203fed94357f58491822a4ebChristopher Tate            pw.println("Exception: " + e);
705d346051bd6da471203fed94357f58491822a4ebChristopher Tate        }
715d346051bd6da471203fed94357f58491822a4ebChristopher Tate        return -1;
725d346051bd6da471203fed94357f58491822a4ebChristopher Tate    }
735d346051bd6da471203fed94357f58491822a4ebChristopher Tate
74a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    private void checkPermission(String operation) throws Exception {
75a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        final int uid = Binder.getCallingUid();
76a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        if (uid == 0) {
77a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            // Root can do anything.
78a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            return;
795d346051bd6da471203fed94357f58491822a4ebChristopher Tate        }
80a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        final int perm = mPM.checkUidPermission(
81a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                "android.permission.CHANGE_APP_IDLE_STATE", uid);
82a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        if (perm != PackageManager.PERMISSION_GRANTED) {
83a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            throw new SecurityException("Uid " + uid
84a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn                    + " not permitted to " + operation);
85a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        }
86a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    }
87a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn
886d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn    private boolean printError(int errCode, String pkgName, int userId, int jobId) {
896d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        PrintWriter pw;
906d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        switch (errCode) {
916d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            case CMD_ERR_NO_PACKAGE:
926d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw = getErrPrintWriter();
936d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print("Package not found: ");
946d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(pkgName);
956d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" / user ");
966d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.println(userId);
976d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                return true;
986d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
996d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            case CMD_ERR_NO_JOB:
1006d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw = getErrPrintWriter();
1016d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print("Could not find job ");
1026d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(jobId);
1036d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" in package ");
1046d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(pkgName);
1056d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" / user ");
1066d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.println(userId);
1076d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                return true;
1086d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
1096d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            case CMD_ERR_CONSTRAINTS:
1106d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw = getErrPrintWriter();
1116d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print("Job ");
1126d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(jobId);
1136d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" in package ");
1146d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(pkgName);
1156d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" / user ");
1166d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(userId);
1176d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.println(" has functional constraints but --force not specified");
1186d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                return true;
1196d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
1206d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            default:
1216d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                return false;
1226d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        }
1236d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn    }
1246d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
125a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    private int runJob(PrintWriter pw) throws Exception {
126a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        checkPermission("force scheduled jobs");
1275d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1285d346051bd6da471203fed94357f58491822a4ebChristopher Tate        boolean force = false;
1295d346051bd6da471203fed94357f58491822a4ebChristopher Tate        int userId = UserHandle.USER_SYSTEM;
1305d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1315d346051bd6da471203fed94357f58491822a4ebChristopher Tate        String opt;
1325d346051bd6da471203fed94357f58491822a4ebChristopher Tate        while ((opt = getNextOption()) != null) {
1335d346051bd6da471203fed94357f58491822a4ebChristopher Tate            switch (opt) {
1345d346051bd6da471203fed94357f58491822a4ebChristopher Tate                case "-f":
1355d346051bd6da471203fed94357f58491822a4ebChristopher Tate                case "--force":
1365d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    force = true;
1375d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    break;
1385d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1395d346051bd6da471203fed94357f58491822a4ebChristopher Tate                case "-u":
1405d346051bd6da471203fed94357f58491822a4ebChristopher Tate                case "--user":
1415d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    userId = Integer.parseInt(getNextArgRequired());
1425d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    break;
1435d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1445d346051bd6da471203fed94357f58491822a4ebChristopher Tate                default:
1455d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    pw.println("Error: unknown option '" + opt + "'");
1465d346051bd6da471203fed94357f58491822a4ebChristopher Tate                    return -1;
1475d346051bd6da471203fed94357f58491822a4ebChristopher Tate            }
1485d346051bd6da471203fed94357f58491822a4ebChristopher Tate        }
1495d346051bd6da471203fed94357f58491822a4ebChristopher Tate
1505d346051bd6da471203fed94357f58491822a4ebChristopher Tate        final String pkgName = getNextArgRequired();
1515d346051bd6da471203fed94357f58491822a4ebChristopher Tate        final int jobId = Integer.parseInt(getNextArgRequired());
1525d346051bd6da471203fed94357f58491822a4ebChristopher Tate
153851a35abe856be6d33917be979628e64e3c019e5Christopher Tate        final long ident = Binder.clearCallingIdentity();
154851a35abe856be6d33917be979628e64e3c019e5Christopher Tate        try {
155851a35abe856be6d33917be979628e64e3c019e5Christopher Tate            int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
1566d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            if (printError(ret, pkgName, userId, jobId)) {
1576d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                return ret;
1586d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            }
159851a35abe856be6d33917be979628e64e3c019e5Christopher Tate
1606d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            // success!
1616d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            pw.print("Running job");
1626d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            if (force) {
1636d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                pw.print(" [FORCED]");
164851a35abe856be6d33917be979628e64e3c019e5Christopher Tate            }
1656d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            pw.println();
1666d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
167851a35abe856be6d33917be979628e64e3c019e5Christopher Tate            return ret;
168851a35abe856be6d33917be979628e64e3c019e5Christopher Tate        } finally {
169851a35abe856be6d33917be979628e64e3c019e5Christopher Tate            Binder.restoreCallingIdentity(ident);
1705d346051bd6da471203fed94357f58491822a4ebChristopher Tate        }
1715d346051bd6da471203fed94357f58491822a4ebChristopher Tate    }
1725d346051bd6da471203fed94357f58491822a4ebChristopher Tate
17383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int timeout(PrintWriter pw) throws Exception {
17483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        checkPermission("force timeout jobs");
17583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
17683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        int userId = UserHandle.USER_ALL;
17783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
17883b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        String opt;
17983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        while ((opt = getNextOption()) != null) {
18083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            switch (opt) {
18183b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                case "-u":
18283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                case "--user":
18383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    userId = UserHandle.parseUserArg(getNextArgRequired());
18483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    break;
18583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
18683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                default:
18783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    pw.println("Error: unknown option '" + opt + "'");
18883b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn                    return -1;
18983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            }
19083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        }
19183b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
19283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        if (userId == UserHandle.USER_CURRENT) {
19383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            userId = ActivityManager.getCurrentUser();
19483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        }
19583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
19683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        final String pkgName = getNextArg();
19783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        final String jobIdStr = getNextArg();
19883b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        final int jobId = jobIdStr != null ? Integer.parseInt(jobIdStr) : -1;
19983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
20083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
20183b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        try {
20283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            return mInternal.executeTimeoutCommand(pw, pkgName, userId, jobIdStr != null, jobId);
20383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        } finally {
20483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            Binder.restoreCallingIdentity(ident);
20583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        }
20683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    }
20783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn
20883b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int monitorBattery(PrintWriter pw) throws Exception {
209a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        checkPermission("change battery monitoring");
210a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        String opt = getNextArgRequired();
211a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        boolean enabled;
212a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        if ("on".equals(opt)) {
213a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            enabled = true;
214a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        } else if ("off".equals(opt)) {
215a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            enabled = false;
216a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        } else {
217a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            getErrPrintWriter().println("Error: unknown option " + opt);
218a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn            return 1;
219a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        }
22083b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
22183b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        try {
22283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            mInternal.setMonitorBattery(enabled);
22383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            if (enabled) pw.println("Battery monitoring enabled");
22483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            else pw.println("Battery monitoring disabled");
22583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        } finally {
22683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn            Binder.restoreCallingIdentity(ident);
22783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        }
228a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        return 0;
229a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    }
230a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn
23183b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int getBatterySeq(PrintWriter pw) {
232a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        int seq = mInternal.getBatterySeq();
233a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println(seq);
234a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        return 0;
235a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    }
236a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn
23783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int getBatteryCharging(PrintWriter pw) {
238a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        boolean val = mInternal.getBatteryCharging();
239a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println(val);
240a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        return 0;
241a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    }
242a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn
24383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int getBatteryNotLow(PrintWriter pw) {
244a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        boolean val = mInternal.getBatteryNotLow();
245a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println(val);
246a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        return 0;
247a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn    }
248a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn
24983b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int getStorageSeq(PrintWriter pw) {
250532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        int seq = mInternal.getStorageSeq();
251532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println(seq);
252532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        return 0;
253532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn    }
254532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn
25583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn    private int getStorageNotLow(PrintWriter pw) {
256532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        boolean val = mInternal.getStorageNotLow();
257532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println(val);
258532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        return 0;
259532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn    }
260532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn
2616d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn    private int getJobState(PrintWriter pw) throws Exception {
2626d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        checkPermission("force timeout jobs");
2636d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2646d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        int userId = UserHandle.USER_SYSTEM;
2656d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2666d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        String opt;
2676d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        while ((opt = getNextOption()) != null) {
2686d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            switch (opt) {
2696d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                case "-u":
2706d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                case "--user":
2716d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                    userId = UserHandle.parseUserArg(getNextArgRequired());
2726d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                    break;
2736d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2746d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                default:
2756d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                    pw.println("Error: unknown option '" + opt + "'");
2766d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn                    return -1;
2776d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            }
2786d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        }
2796d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2806d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        if (userId == UserHandle.USER_CURRENT) {
2816d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            userId = ActivityManager.getCurrentUser();
2826d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        }
2836d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2846d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        final String pkgName = getNextArgRequired();
2856d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        final String jobIdStr = getNextArgRequired();
2866d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        final int jobId = Integer.parseInt(jobIdStr);
2876d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2886d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
2896d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        try {
2906d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            int ret = mInternal.getJobState(pw, pkgName, userId, jobId);
2916d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            printError(ret, pkgName, userId, jobId);
2926d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            return ret;
2936d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        } finally {
2946d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn            Binder.restoreCallingIdentity(ident);
2956d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        }
2966d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn    }
2976d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn
2985d346051bd6da471203fed94357f58491822a4ebChristopher Tate    @Override
2995d346051bd6da471203fed94357f58491822a4ebChristopher Tate    public void onHelp() {
3005d346051bd6da471203fed94357f58491822a4ebChristopher Tate        final PrintWriter pw = getOutPrintWriter();
3015d346051bd6da471203fed94357f58491822a4ebChristopher Tate
3025d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("Job scheduler (jobscheduler) commands:");
3035d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("  help");
3045d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("    Print this help text.");
3055d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("  run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
3065d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("    Trigger immediate execution of a specific scheduled job.");
3075d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("    Options:");
3085d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("      -f or --force: run the job even if technical constraints such as");
3095d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("         connectivity are not currently met");
3105d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("      -u or --user: specify which user's job is to be run; the default is");
3115d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println("         the primary or system user");
31283b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("  timeout [-u | --user USER_ID] [PACKAGE] [JOB_ID]");
31383b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("    Trigger immediate timeout of currently executing jobs, as if their.");
31483b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("    execution timeout had expired.");
31583b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("    Options:");
31683b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("      -u or --user: specify which user's job is to be run; the default is");
31783b40f69bef4ba17bb63ac30d52f661a12d5b4f4Dianne Hackborn        pw.println("         all users");
318a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("  monitor-battery [on|off]");
319a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("    Control monitoring of all battery changes.  Off by default.  Turning");
320a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("    on makes get-battery-seq useful.");
321a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("  get-battery-seq");
322a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("    Return the last battery update sequence number that was received.");
323a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("  get-battery-charging");
324a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("    Return whether the battery is currently considered to be charging.");
325a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("  get-battery-not-low");
326a06ec6a9435f9555142e700f54cf20278bc1982fDianne Hackborn        pw.println("    Return whether the battery is currently considered to not be low.");
327532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println("  get-storage-seq");
328532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println("    Return the last storage update sequence number that was received.");
329532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println("  get-storage-not-low");
330532ea26c7b66180b09524f96da8bca1110f41197Dianne Hackborn        pw.println("    Return whether storage is currently considered to not be low.");
3316d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("  get-job-state [-u | --user USER_ID] PACKAGE JOB_ID");
3326d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("    Return the current state of a job, may be any combination of:");
3336d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      pending: currently on the pending list, waiting to be active");
3346d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      active: job is actively running");
3356d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      user-stopped: job can't run because its user is stopped");
3366d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      backing-up: job can't run because app is currently backing up its data");
3376d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      no-component: job can't run because its component is not available");
3386d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      ready: job is ready to run (all constraints satisfied or bypassed)");
3396d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      waiting: if nothing else above is printed, job not ready to run");
3406d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("    Options:");
3416d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("      -u or --user: specify which user's job is to be run; the default is");
3426d06826b2424f5d937bf97576d3b51169c576fc5Dianne Hackborn        pw.println("         the primary or system user");
3435d346051bd6da471203fed94357f58491822a4ebChristopher Tate        pw.println();
3445d346051bd6da471203fed94357f58491822a4ebChristopher Tate    }
3455d346051bd6da471203fed94357f58491822a4ebChristopher Tate
3465d346051bd6da471203fed94357f58491822a4ebChristopher Tate}
347