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