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 17 package com.android.commands.appwidget; 18 19 import android.content.Context; 20 import android.os.IBinder; 21 import android.os.RemoteException; 22 import android.os.ServiceManager; 23 import android.os.UserHandle; 24 import android.text.TextUtils; 25 26 import com.android.internal.appwidget.IAppWidgetService; 27 28 /** 29 * This class is a command line utility for manipulating app widgets. A client 30 * can grant or revoke the permission for a given package to bind app widgets. 31 */ 32 public class AppWidget { 33 34 private static final String USAGE = 35 "usage: adb shell appwidget [subcommand] [options]\n" 36 + "\n" 37 + "usage: adb shell appwidget grantbind --package <PACKAGE> " 38 + " [--user <USER_ID> | current]\n" 39 + " <PACKAGE> an Android package name.\n" 40 + " <USER_ID> The user id under which the package is installed.\n" 41 + " Example:\n" 42 + " # Grant the \"foo.bar.baz\" package to bind app widgets for the current user.\n" 43 + " adb shell grantbind --package foo.bar.baz --user current\n" 44 + "\n" 45 + "usage: adb shell appwidget revokebind --package <PACKAGE> " 46 + "[--user <USER_ID> | current]\n" 47 + " <PACKAGE> an Android package name.\n" 48 + " <USER_ID> The user id under which the package is installed.\n" 49 + " Example:\n" 50 + " # Revoke the permisison to bind app widgets from the \"foo.bar.baz\" package.\n" 51 + " adb shell revokebind --package foo.bar.baz --user current\n" 52 + "\n"; 53 54 private static class Parser { 55 private static final String ARGUMENT_GRANT_BIND = "grantbind"; 56 private static final String ARGUMENT_REVOKE_BIND = "revokebind"; 57 private static final String ARGUMENT_PACKAGE = "--package"; 58 private static final String ARGUMENT_USER = "--user"; 59 private static final String ARGUMENT_PREFIX = "--"; 60 private static final String VALUE_USER_CURRENT = "current"; 61 62 private final Tokenizer mTokenizer; 63 Parser(String[] args)64 public Parser(String[] args) { 65 mTokenizer = new Tokenizer(args); 66 } 67 parseCommand()68 public Runnable parseCommand() { 69 try { 70 String operation = mTokenizer.nextArg(); 71 if (ARGUMENT_GRANT_BIND.equals(operation)) { 72 return parseSetGrantBindAppWidgetPermissionCommand(true); 73 } else if (ARGUMENT_REVOKE_BIND.equals(operation)) { 74 return parseSetGrantBindAppWidgetPermissionCommand(false); 75 } else { 76 throw new IllegalArgumentException("Unsupported operation: " + operation); 77 } 78 } catch (IllegalArgumentException iae) { 79 System.out.println(USAGE); 80 System.out.println("[ERROR] " + iae.getMessage()); 81 return null; 82 } 83 } 84 parseSetGrantBindAppWidgetPermissionCommand( boolean granted)85 private SetBindAppWidgetPermissionCommand parseSetGrantBindAppWidgetPermissionCommand( 86 boolean granted) { 87 String packageName = null; 88 int userId = UserHandle.USER_SYSTEM; 89 for (String argument; (argument = mTokenizer.nextArg()) != null;) { 90 if (ARGUMENT_PACKAGE.equals(argument)) { 91 packageName = argumentValueRequired(argument); 92 } else if (ARGUMENT_USER.equals(argument)) { 93 String user = argumentValueRequired(argument); 94 if (VALUE_USER_CURRENT.equals(user)) { 95 userId = UserHandle.USER_CURRENT; 96 } else { 97 userId = Integer.parseInt(user); 98 } 99 } else { 100 throw new IllegalArgumentException("Unsupported argument: " + argument); 101 } 102 } 103 if (packageName == null) { 104 throw new IllegalArgumentException("Package name not specified." 105 + " Did you specify --package argument?"); 106 } 107 return new SetBindAppWidgetPermissionCommand(packageName, granted, userId); 108 } 109 argumentValueRequired(String argument)110 private String argumentValueRequired(String argument) { 111 String value = mTokenizer.nextArg(); 112 if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) { 113 throw new IllegalArgumentException("No value for argument: " + argument); 114 } 115 return value; 116 } 117 } 118 119 private static class Tokenizer { 120 private final String[] mArgs; 121 private int mNextArg; 122 Tokenizer(String[] args)123 public Tokenizer(String[] args) { 124 mArgs = args; 125 } 126 nextArg()127 private String nextArg() { 128 if (mNextArg < mArgs.length) { 129 return mArgs[mNextArg++]; 130 } else { 131 return null; 132 } 133 } 134 } 135 136 private static class SetBindAppWidgetPermissionCommand implements Runnable { 137 final String mPackageName; 138 final boolean mGranted; 139 final int mUserId; 140 SetBindAppWidgetPermissionCommand(String packageName, boolean granted, int userId)141 public SetBindAppWidgetPermissionCommand(String packageName, boolean granted, 142 int userId) { 143 mPackageName = packageName; 144 mGranted = granted; 145 mUserId = userId; 146 } 147 148 @Override run()149 public void run() { 150 IBinder binder = ServiceManager.getService(Context.APPWIDGET_SERVICE); 151 IAppWidgetService appWidgetService = IAppWidgetService.Stub.asInterface(binder); 152 try { 153 appWidgetService.setBindAppWidgetPermission(mPackageName, mUserId, mGranted); 154 } catch (RemoteException re) { 155 re.printStackTrace(); 156 } 157 } 158 } 159 main(String[] args)160 public static void main(String[] args) { 161 Parser parser = new Parser(args); 162 Runnable command = parser.parseCommand(); 163 if (command != null) { 164 command.run(); 165 } 166 } 167 } 168