1/* 2** Copyright 2014, 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.commands.appops; 18 19import android.app.ActivityManager; 20import android.app.ActivityThread; 21import android.app.AppOpsManager; 22import android.content.Context; 23import android.content.pm.IPackageManager; 24import android.os.ServiceManager; 25import android.os.UserHandle; 26 27import android.util.TimeUtils; 28import com.android.internal.app.IAppOpsService; 29import com.android.internal.os.BaseCommand; 30 31import java.io.PrintStream; 32import java.util.List; 33 34/** 35 * This class is a command line utility for manipulating AppOps permissions. 36 */ 37public class AppOpsCommand extends BaseCommand { 38 39 public static void main(String[] args) { 40 new AppOpsCommand().run(args); 41 } 42 43 @Override 44 public void onShowUsage(PrintStream out) { 45 out.println("usage: appops set [--user <USER_ID>] <PACKAGE> <OP> <MODE>\n" 46 + " appops get [--user <USER_ID>] <PACKAGE> [<OP>]\n" 47 + " appops reset [--user <USER_ID>] [<PACKAGE>]\n" 48 + " <PACKAGE> an Android package name.\n" 49 + " <OP> an AppOps operation.\n" 50 + " <MODE> one of allow, ignore, deny, or default\n" 51 + " <USER_ID> the user id under which the package is installed. If --user is not\n" 52 + " specified, the current user is assumed.\n"); 53 } 54 55 private static final String COMMAND_SET = "set"; 56 private static final String COMMAND_GET = "get"; 57 private static final String COMMAND_RESET = "reset"; 58 59 @Override 60 public void onRun() throws Exception { 61 String command = nextArgRequired(); 62 switch (command) { 63 case COMMAND_SET: 64 runSet(); 65 break; 66 67 case COMMAND_GET: 68 runGet(); 69 break; 70 71 case COMMAND_RESET: 72 runReset(); 73 break; 74 75 default: 76 System.err.println("Error: Unknown command: '" + command + "'."); 77 break; 78 } 79 } 80 81 private static final String ARGUMENT_USER = "--user"; 82 83 // Modes 84 private static final String MODE_ALLOW = "allow"; 85 private static final String MODE_DENY = "deny"; 86 private static final String MODE_IGNORE = "ignore"; 87 private static final String MODE_DEFAULT = "default"; 88 89 private int strOpToOp(String op) { 90 try { 91 return AppOpsManager.strOpToOp(op); 92 } catch (IllegalArgumentException e) { 93 } 94 try { 95 return Integer.parseInt(op); 96 } catch (NumberFormatException e) { 97 } 98 try { 99 return AppOpsManager.strDebugOpToOp(op); 100 } catch (IllegalArgumentException e) { 101 System.err.println("Error: " + e.getMessage()); 102 return -1; 103 } 104 } 105 106 private void runSet() throws Exception { 107 String packageName = null; 108 String op = null; 109 String mode = null; 110 int userId = UserHandle.USER_CURRENT; 111 for (String argument; (argument = nextArg()) != null;) { 112 if (ARGUMENT_USER.equals(argument)) { 113 userId = Integer.parseInt(nextArgRequired()); 114 } else { 115 if (packageName == null) { 116 packageName = argument; 117 } else if (op == null) { 118 op = argument; 119 } else if (mode == null) { 120 mode = argument; 121 } else { 122 System.err.println("Error: Unsupported argument: " + argument); 123 return; 124 } 125 } 126 } 127 128 if (packageName == null) { 129 System.err.println("Error: Package name not specified."); 130 return; 131 } else if (op == null) { 132 System.err.println("Error: Operation not specified."); 133 return; 134 } else if (mode == null) { 135 System.err.println("Error: Mode not specified."); 136 return; 137 } 138 139 final int opInt = strOpToOp(op); 140 if (opInt < 0) { 141 return; 142 } 143 final int modeInt; 144 switch (mode) { 145 case MODE_ALLOW: 146 modeInt = AppOpsManager.MODE_ALLOWED; 147 break; 148 case MODE_DENY: 149 modeInt = AppOpsManager.MODE_ERRORED; 150 break; 151 case MODE_IGNORE: 152 modeInt = AppOpsManager.MODE_IGNORED; 153 break; 154 case MODE_DEFAULT: 155 modeInt = AppOpsManager.MODE_DEFAULT; 156 break; 157 default: 158 System.err.println("Error: Mode " + mode + " is not valid,"); 159 return; 160 } 161 162 // Parsing complete, let's execute the command. 163 164 if (userId == UserHandle.USER_CURRENT) { 165 userId = ActivityManager.getCurrentUser(); 166 } 167 168 final IPackageManager pm = ActivityThread.getPackageManager(); 169 final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( 170 ServiceManager.getService(Context.APP_OPS_SERVICE)); 171 final int uid = pm.getPackageUid(packageName, userId); 172 if (uid < 0) { 173 System.err.println("Error: No UID for " + packageName + " in user " + userId); 174 return; 175 } 176 appOpsService.setMode(opInt, uid, packageName, modeInt); 177 } 178 179 private void runGet() throws Exception { 180 String packageName = null; 181 String op = null; 182 int userId = UserHandle.USER_CURRENT; 183 for (String argument; (argument = nextArg()) != null;) { 184 if (ARGUMENT_USER.equals(argument)) { 185 userId = Integer.parseInt(nextArgRequired()); 186 } else { 187 if (packageName == null) { 188 packageName = argument; 189 } else if (op == null) { 190 op = argument; 191 } else { 192 System.err.println("Error: Unsupported argument: " + argument); 193 return; 194 } 195 } 196 } 197 198 if (packageName == null) { 199 System.err.println("Error: Package name not specified."); 200 return; 201 } 202 203 final int opInt = op != null ? strOpToOp(op) : 0; 204 205 // Parsing complete, let's execute the command. 206 207 if (userId == UserHandle.USER_CURRENT) { 208 userId = ActivityManager.getCurrentUser(); 209 } 210 211 final IPackageManager pm = ActivityThread.getPackageManager(); 212 final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( 213 ServiceManager.getService(Context.APP_OPS_SERVICE)); 214 final int uid = pm.getPackageUid(packageName, userId); 215 if (uid < 0) { 216 System.err.println("Error: No UID for " + packageName + " in user " + userId); 217 return; 218 } 219 List<AppOpsManager.PackageOps> ops = appOpsService.getOpsForPackage(uid, packageName, 220 op != null ? new int[] {opInt} : null); 221 if (ops == null || ops.size() <= 0) { 222 System.out.println("No operations."); 223 return; 224 } 225 final long now = System.currentTimeMillis(); 226 for (int i=0; i<ops.size(); i++) { 227 List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 228 for (int j=0; j<entries.size(); j++) { 229 AppOpsManager.OpEntry ent = entries.get(j); 230 System.out.print(AppOpsManager.opToName(ent.getOp())); 231 System.out.print(": "); 232 switch (ent.getMode()) { 233 case AppOpsManager.MODE_ALLOWED: 234 System.out.print("allow"); 235 break; 236 case AppOpsManager.MODE_IGNORED: 237 System.out.print("ignore"); 238 break; 239 case AppOpsManager.MODE_ERRORED: 240 System.out.print("deny"); 241 break; 242 case AppOpsManager.MODE_DEFAULT: 243 System.out.print("default"); 244 break; 245 default: 246 System.out.print("mode="); 247 System.out.print(ent.getMode()); 248 break; 249 } 250 if (ent.getTime() != 0) { 251 System.out.print("; time="); 252 StringBuilder sb = new StringBuilder(); 253 TimeUtils.formatDuration(now - ent.getTime(), sb); 254 System.out.print(sb); 255 System.out.print(" ago"); 256 } 257 if (ent.getRejectTime() != 0) { 258 System.out.print("; rejectTime="); 259 StringBuilder sb = new StringBuilder(); 260 TimeUtils.formatDuration(now - ent.getRejectTime(), sb); 261 System.out.print(sb); 262 System.out.print(" ago"); 263 } 264 if (ent.getDuration() == -1) { 265 System.out.print(" (running)"); 266 } else if (ent.getDuration() != 0) { 267 System.out.print("; duration="); 268 StringBuilder sb = new StringBuilder(); 269 TimeUtils.formatDuration(ent.getDuration(), sb); 270 System.out.print(sb); 271 } 272 System.out.println(); 273 } 274 } 275 } 276 277 private void runReset() throws Exception { 278 String packageName = null; 279 int userId = UserHandle.USER_CURRENT; 280 for (String argument; (argument = nextArg()) != null;) { 281 if (ARGUMENT_USER.equals(argument)) { 282 String userStr = nextArgRequired(); 283 if ("all".equals(userStr)) { 284 userId = UserHandle.USER_ALL; 285 } else if ("current".equals(userStr)) { 286 userId = UserHandle.USER_CURRENT; 287 } else if ("owner".equals(userStr)) { 288 userId = UserHandle.USER_OWNER; 289 } else { 290 userId = Integer.parseInt(nextArgRequired()); 291 } 292 } else { 293 if (packageName == null) { 294 packageName = argument; 295 } else { 296 System.err.println("Error: Unsupported argument: " + argument); 297 return; 298 } 299 } 300 } 301 302 // Parsing complete, let's execute the command. 303 304 if (userId == UserHandle.USER_CURRENT) { 305 userId = ActivityManager.getCurrentUser(); 306 } 307 308 final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( 309 ServiceManager.getService(Context.APP_OPS_SERVICE)); 310 appOpsService.resetAllModes(userId, packageName); 311 System.out.print("Reset all modes for: "); 312 if (userId == UserHandle.USER_ALL) { 313 System.out.print("all users"); 314 } else { 315 System.out.print("user "); System.out.print(userId); 316 } 317 System.out.print(", "); 318 if (packageName == null) { 319 System.out.println("all packages"); 320 } else { 321 System.out.print("package "); System.out.println(packageName); 322 } 323 } 324} 325