/* ** Copyright 2014, 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.commands.appops; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.IPackageManager; import android.os.ServiceManager; import android.os.UserHandle; import android.util.TimeUtils; import com.android.internal.app.IAppOpsService; import com.android.internal.os.BaseCommand; import java.io.PrintStream; import java.util.List; /** * This class is a command line utility for manipulating AppOps permissions. */ public class AppOpsCommand extends BaseCommand { public static void main(String[] args) { new AppOpsCommand().run(args); } @Override public void onShowUsage(PrintStream out) { out.println("usage: appops set [--user ] \n" + " appops get [--user ] []\n" + " appops reset [--user ] []\n" + " an Android package name.\n" + " an AppOps operation.\n" + " one of allow, ignore, deny, or default\n" + " the user id under which the package is installed. If --user is not\n" + " specified, the current user is assumed.\n"); } private static final String COMMAND_SET = "set"; private static final String COMMAND_GET = "get"; private static final String COMMAND_RESET = "reset"; @Override public void onRun() throws Exception { String command = nextArgRequired(); switch (command) { case COMMAND_SET: runSet(); break; case COMMAND_GET: runGet(); break; case COMMAND_RESET: runReset(); break; default: System.err.println("Error: Unknown command: '" + command + "'."); break; } } private static final String ARGUMENT_USER = "--user"; // Modes private static final String MODE_ALLOW = "allow"; private static final String MODE_DENY = "deny"; private static final String MODE_IGNORE = "ignore"; private static final String MODE_DEFAULT = "default"; private int strOpToOp(String op) { try { return AppOpsManager.strOpToOp(op); } catch (IllegalArgumentException e) { } try { return Integer.parseInt(op); } catch (NumberFormatException e) { } try { return AppOpsManager.strDebugOpToOp(op); } catch (IllegalArgumentException e) { System.err.println("Error: " + e.getMessage()); return -1; } } private void runSet() throws Exception { String packageName = null; String op = null; String mode = null; int userId = UserHandle.USER_CURRENT; for (String argument; (argument = nextArg()) != null;) { if (ARGUMENT_USER.equals(argument)) { userId = Integer.parseInt(nextArgRequired()); } else { if (packageName == null) { packageName = argument; } else if (op == null) { op = argument; } else if (mode == null) { mode = argument; } else { System.err.println("Error: Unsupported argument: " + argument); return; } } } if (packageName == null) { System.err.println("Error: Package name not specified."); return; } else if (op == null) { System.err.println("Error: Operation not specified."); return; } else if (mode == null) { System.err.println("Error: Mode not specified."); return; } final int opInt = strOpToOp(op); if (opInt < 0) { return; } final int modeInt; switch (mode) { case MODE_ALLOW: modeInt = AppOpsManager.MODE_ALLOWED; break; case MODE_DENY: modeInt = AppOpsManager.MODE_ERRORED; break; case MODE_IGNORE: modeInt = AppOpsManager.MODE_IGNORED; break; case MODE_DEFAULT: modeInt = AppOpsManager.MODE_DEFAULT; break; default: System.err.println("Error: Mode " + mode + " is not valid,"); return; } // Parsing complete, let's execute the command. if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final IPackageManager pm = ActivityThread.getPackageManager(); final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); final int uid = pm.getPackageUid(packageName, userId); if (uid < 0) { System.err.println("Error: No UID for " + packageName + " in user " + userId); return; } appOpsService.setMode(opInt, uid, packageName, modeInt); } private void runGet() throws Exception { String packageName = null; String op = null; int userId = UserHandle.USER_CURRENT; for (String argument; (argument = nextArg()) != null;) { if (ARGUMENT_USER.equals(argument)) { userId = Integer.parseInt(nextArgRequired()); } else { if (packageName == null) { packageName = argument; } else if (op == null) { op = argument; } else { System.err.println("Error: Unsupported argument: " + argument); return; } } } if (packageName == null) { System.err.println("Error: Package name not specified."); return; } final int opInt = op != null ? strOpToOp(op) : 0; // Parsing complete, let's execute the command. if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final IPackageManager pm = ActivityThread.getPackageManager(); final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); final int uid = pm.getPackageUid(packageName, userId); if (uid < 0) { System.err.println("Error: No UID for " + packageName + " in user " + userId); return; } List ops = appOpsService.getOpsForPackage(uid, packageName, op != null ? new int[] {opInt} : null); if (ops == null || ops.size() <= 0) { System.out.println("No operations."); return; } final long now = System.currentTimeMillis(); for (int i=0; i entries = ops.get(i).getOps(); for (int j=0; j