1 /* 2 * Copyright (C) 2016 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 17 package com.android.server.job; 18 19 import android.app.AppGlobals; 20 import android.content.pm.IPackageManager; 21 import android.content.pm.PackageManager; 22 import android.os.Binder; 23 import android.os.RemoteException; 24 import android.os.ShellCommand; 25 import android.os.UserHandle; 26 27 import java.io.PrintWriter; 28 29 public class JobSchedulerShellCommand extends ShellCommand { 30 public static final int CMD_ERR_NO_PACKAGE = -1000; 31 public static final int CMD_ERR_NO_JOB = -1001; 32 public static final int CMD_ERR_CONSTRAINTS = -1002; 33 34 JobSchedulerService mInternal; 35 IPackageManager mPM; 36 37 JobSchedulerShellCommand(JobSchedulerService service) { 38 mInternal = service; 39 mPM = AppGlobals.getPackageManager(); 40 } 41 42 @Override 43 public int onCommand(String cmd) { 44 final PrintWriter pw = getOutPrintWriter(); 45 try { 46 if ("run".equals(cmd)) { 47 return runJob(); 48 } else { 49 return handleDefaultCommands(cmd); 50 } 51 } catch (Exception e) { 52 pw.println("Exception: " + e); 53 } 54 return -1; 55 } 56 57 private int runJob() { 58 try { 59 final int uid = Binder.getCallingUid(); 60 final int perm = mPM.checkUidPermission( 61 "android.permission.CHANGE_APP_IDLE_STATE", uid); 62 if (perm != PackageManager.PERMISSION_GRANTED) { 63 throw new SecurityException("Uid " + uid 64 + " not permitted to force scheduled jobs"); 65 } 66 } catch (RemoteException e) { 67 // Can't happen 68 } 69 70 final PrintWriter pw = getOutPrintWriter(); 71 boolean force = false; 72 int userId = UserHandle.USER_SYSTEM; 73 74 String opt; 75 while ((opt = getNextOption()) != null) { 76 switch (opt) { 77 case "-f": 78 case "--force": 79 force = true; 80 break; 81 82 case "-u": 83 case "--user": 84 userId = Integer.parseInt(getNextArgRequired()); 85 break; 86 87 default: 88 pw.println("Error: unknown option '" + opt + "'"); 89 return -1; 90 } 91 } 92 93 final String pkgName = getNextArgRequired(); 94 final int jobId = Integer.parseInt(getNextArgRequired()); 95 96 int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force); 97 switch (ret) { 98 case CMD_ERR_NO_PACKAGE: 99 pw.print("Package not found: "); 100 pw.print(pkgName); 101 pw.print(" / user "); 102 pw.println(userId); 103 break; 104 105 case CMD_ERR_NO_JOB: 106 pw.print("Could not find job "); 107 pw.print(jobId); 108 pw.print(" in package "); 109 pw.print(pkgName); 110 pw.print(" / user "); 111 pw.println(userId); 112 break; 113 114 case CMD_ERR_CONSTRAINTS: 115 pw.print("Job "); 116 pw.print(jobId); 117 pw.print(" in package "); 118 pw.print(pkgName); 119 pw.print(" / user "); 120 pw.print(userId); 121 pw.println(" has functional constraints but --force not specified"); 122 break; 123 124 default: 125 // success! 126 pw.print("Running job"); 127 if (force) { 128 pw.print(" [FORCED]"); 129 } 130 pw.println(); 131 break; 132 } 133 return ret; 134 } 135 136 @Override 137 public void onHelp() { 138 final PrintWriter pw = getOutPrintWriter(); 139 140 pw.println("Job scheduler (jobscheduler) commands:"); 141 pw.println(" help"); 142 pw.println(" Print this help text."); 143 pw.println(); 144 pw.println(" run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID"); 145 pw.println(" Trigger immediate execution of a specific scheduled job."); 146 pw.println(" Options:"); 147 pw.println(" -f or --force: run the job even if technical constraints such as"); 148 pw.println(" connectivity are not currently met"); 149 pw.println(" -u or --user: specify which user's job is to be run; the default is"); 150 pw.println(" the primary or system user"); 151 pw.println(); 152 } 153 154 } 155