blob: ec23407915557046c12c922873bc9072d100265c [file] [log] [blame]
/*
* Copyright (C) 2016 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.job;
import android.app.AppGlobals;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
public class JobSchedulerShellCommand extends ShellCommand {
public static final int CMD_ERR_NO_PACKAGE = -1000;
public static final int CMD_ERR_NO_JOB = -1001;
public static final int CMD_ERR_CONSTRAINTS = -1002;
JobSchedulerService mInternal;
IPackageManager mPM;
JobSchedulerShellCommand(JobSchedulerService service) {
mInternal = service;
mPM = AppGlobals.getPackageManager();
}
@Override
public int onCommand(String cmd) {
final PrintWriter pw = getOutPrintWriter();
try {
switch (cmd != null ? cmd : "") {
case "run":
return runJob(pw);
case "monitor-battery":
return runMonitorBattery(pw);
case "get-battery-seq":
return runGetBatterySeq(pw);
case "get-battery-charging":
return runGetBatteryCharging(pw);
case "get-battery-not-low":
return runGetBatteryNotLow(pw);
default:
return handleDefaultCommands(cmd);
}
} catch (Exception e) {
pw.println("Exception: " + e);
}
return -1;
}
private void checkPermission(String operation) throws Exception {
final int uid = Binder.getCallingUid();
if (uid == 0) {
// Root can do anything.
return;
}
final int perm = mPM.checkUidPermission(
"android.permission.CHANGE_APP_IDLE_STATE", uid);
if (perm != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Uid " + uid
+ " not permitted to " + operation);
}
}
private int runJob(PrintWriter pw) throws Exception {
checkPermission("force scheduled jobs");
boolean force = false;
int userId = UserHandle.USER_SYSTEM;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "-f":
case "--force":
force = true;
break;
case "-u":
case "--user":
userId = Integer.parseInt(getNextArgRequired());
break;
default:
pw.println("Error: unknown option '" + opt + "'");
return -1;
}
}
final String pkgName = getNextArgRequired();
final int jobId = Integer.parseInt(getNextArgRequired());
int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
switch (ret) {
case CMD_ERR_NO_PACKAGE:
pw.print("Package not found: ");
pw.print(pkgName);
pw.print(" / user ");
pw.println(userId);
break;
case CMD_ERR_NO_JOB:
pw.print("Could not find job ");
pw.print(jobId);
pw.print(" in package ");
pw.print(pkgName);
pw.print(" / user ");
pw.println(userId);
break;
case CMD_ERR_CONSTRAINTS:
pw.print("Job ");
pw.print(jobId);
pw.print(" in package ");
pw.print(pkgName);
pw.print(" / user ");
pw.print(userId);
pw.println(" has functional constraints but --force not specified");
break;
default:
// success!
pw.print("Running job");
if (force) {
pw.print(" [FORCED]");
}
pw.println();
break;
}
return ret;
}
private int runMonitorBattery(PrintWriter pw) throws Exception {
checkPermission("change battery monitoring");
String opt = getNextArgRequired();
boolean enabled;
if ("on".equals(opt)) {
enabled = true;
} else if ("off".equals(opt)) {
enabled = false;
} else {
getErrPrintWriter().println("Error: unknown option " + opt);
return 1;
}
mInternal.setMonitorBattery(enabled);
if (enabled) pw.println("Battery monitoring enabled");
else pw.println("Battery monitoring disabled");
return 0;
}
private int runGetBatterySeq(PrintWriter pw) {
int seq = mInternal.getBatterySeq();
pw.println(seq);
return 0;
}
private int runGetBatteryCharging(PrintWriter pw) {
boolean val = mInternal.getBatteryCharging();
pw.println(val);
return 0;
}
private int runGetBatteryNotLow(PrintWriter pw) {
boolean val = mInternal.getBatteryNotLow();
pw.println(val);
return 0;
}
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
pw.println("Job scheduler (jobscheduler) commands:");
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
pw.println(" Trigger immediate execution of a specific scheduled job.");
pw.println(" Options:");
pw.println(" -f or --force: run the job even if technical constraints such as");
pw.println(" connectivity are not currently met");
pw.println(" -u or --user: specify which user's job is to be run; the default is");
pw.println(" the primary or system user");
pw.println(" monitor-battery [on|off]");
pw.println(" Control monitoring of all battery changes. Off by default. Turning");
pw.println(" on makes get-battery-seq useful.");
pw.println(" get-battery-seq");
pw.println(" Return the last battery update sequence number that was received.");
pw.println(" get-battery-charging");
pw.println(" Return whether the battery is currently considered to be charging.");
pw.println(" get-battery-not-low");
pw.println(" Return whether the battery is currently considered to not be low.");
pw.println();
}
}