blob: 0dd0edde12a5f5f0efdad123eeaa6e5090e0b50c [file] [log] [blame]
Amith Yamasanif20d6402014-05-24 15:34:37 -07001/*
2 * Copyright (C) 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 android.content;
18
19import android.app.admin.DevicePolicyManager;
20import android.os.Bundle;
21import android.os.RemoteException;
22import android.util.Log;
23
24import java.util.Collections;
25import java.util.List;
26
27/**
28 * Provides a mechanism for apps to query restrictions imposed by an entity that
29 * manages the user. Apps can also send permission requests to a local or remote
30 * device administrator to override default app-specific restrictions or any other
31 * operation that needs explicit authorization from the administrator.
32 * <p>
33 * Apps can expose a set of restrictions via a runtime receiver mechanism or via
34 * static meta data in the manifest.
35 * <p>
36 * If the user has an active restrictions provider, dynamic requests can be made in
37 * addition to the statically imposed restrictions. Dynamic requests are app-specific
38 * and can be expressed via a predefined set of templates.
39 * <p>
40 * The RestrictionsManager forwards the dynamic requests to the active
41 * restrictions provider. The restrictions provider can respond back to requests by calling
42 * {@link #notifyPermissionResponse(String, Bundle)}, when
43 * a response is received from the administrator of the device or user
44 * The response is relayed back to the application via a protected broadcast,
45 * {@link #ACTION_PERMISSION_RESPONSE_RECEIVED}.
46 * <p>
47 * Static restrictions are specified by an XML file referenced by a meta-data attribute
48 * in the manifest. This enables applications as well as any web administration consoles
49 * to be able to read the template from the apk.
50 * <p>
51 * The syntax of the XML format is as follows:
52 * <pre>
53 * &lt;restrictions&gt;
54 * &lt;restriction
55 * android:key="&lt;key&gt;"
56 * android:restrictionType="boolean|string|integer|multi-select|null"
57 * ... /&gt;
58 * &lt;restriction ... /&gt;
59 * &lt;/restrictions&gt;
60 * </pre>
61 * <p>
62 * The attributes for each restriction depend on the restriction type.
63 *
64 * @see RestrictionEntry
65 */
66public class RestrictionsManager {
67
68 /**
69 * Broadcast intent delivered when a response is received for a permission
70 * request. The response is not available for later query, so the receiver
71 * must persist and/or immediately act upon the response. The application
72 * should not interrupt the user by coming to the foreground if it isn't
73 * currently in the foreground. It can post a notification instead, informing
74 * the user of a change in state.
75 * <p>
76 * For instance, if the user requested permission to make an in-app purchase,
77 * the app can post a notification that the request had been granted or denied,
78 * and allow the purchase to go through.
79 * <p>
80 * The broadcast Intent carries the following extra:
81 * {@link #EXTRA_RESPONSE_BUNDLE}.
82 */
83 public static final String ACTION_PERMISSION_RESPONSE_RECEIVED =
84 "android.intent.action.PERMISSION_RESPONSE_RECEIVED";
85
86 /**
87 * Protected broadcast intent sent to the active restrictions provider. The intent
88 * contains the following extras:<p>
89 * <ul>
90 * <li>{@link #EXTRA_PACKAGE_NAME} : String; the package name of the application requesting
91 * permission.</li>
92 * <li>{@link #EXTRA_TEMPLATE_ID} : String; the template of the request.</li>
93 * <li>{@link #EXTRA_REQUEST_BUNDLE} : Bundle; contains the template-specific keys and values
94 * for the request.
95 * </ul>
96 * @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
97 * @see #requestPermission(String, String, Bundle)
98 */
99 public static final String ACTION_REQUEST_PERMISSION =
100 "android.intent.action.REQUEST_PERMISSION";
101
102 /**
103 * The package name of the application making the request.
104 */
105 public static final String EXTRA_PACKAGE_NAME = "package_name";
106
107 /**
108 * The template id that specifies what kind of a request it is and may indicate
109 * how the request is to be presented to the administrator. Must be either one of
110 * the predefined templates or a custom one specified by the application that the
111 * restrictions provider is familiar with.
112 */
113 public static final String EXTRA_TEMPLATE_ID = "template_id";
114
115 /**
116 * A bundle containing the details about the request. The contents depend on the
117 * template id.
118 * @see #EXTRA_TEMPLATE_ID
119 */
120 public static final String EXTRA_REQUEST_BUNDLE = "request_bundle";
121
122 /**
123 * Contains a response from the administrator for specific request.
124 * The bundle contains the following information, at least:
125 * <ul>
126 * <li>{@link #REQUEST_KEY_ID}: The request id.</li>
127 * <li>{@link #REQUEST_KEY_DATA}: The request reference data.</li>
128 * </ul>
129 * <p>
130 * And depending on what the request template was, the bundle will contain the actual
131 * result of the request. For {@link #REQUEST_TEMPLATE_QUESTION}, the result will be in
132 * {@link #RESPONSE_KEY_BOOLEAN}, which is of type boolean; true if the administrator
133 * approved the request, false otherwise.
134 */
135 public static final String EXTRA_RESPONSE_BUNDLE = "response_bundle";
136
137
138 /**
139 * Request template that presents a simple question, with a possible title and icon.
140 * <p>
141 * Required keys are
142 * {@link #REQUEST_KEY_ID} and {@link #REQUEST_KEY_MESSAGE}.
143 * <p>
144 * Optional keys are
145 * {@link #REQUEST_KEY_DATA}, {@link #REQUEST_KEY_ICON}, {@link #REQUEST_KEY_TITLE},
146 * {@link #REQUEST_KEY_APPROVE_LABEL} and {@link #REQUEST_KEY_DENY_LABEL}.
147 */
148 public static final String REQUEST_TEMPLATE_QUESTION = "android.req_template.type.simple";
149
150 /**
151 * Key for request ID contained in the request bundle.
152 * <p>
153 * App-generated request id to identify the specific request when receiving
154 * a response. This value is returned in the {@link #EXTRA_RESPONSE_BUNDLE}.
155 * <p>
156 * Type: String
157 */
158 public static final String REQUEST_KEY_ID = "android.req_template.req_id";
159
160 /**
161 * Key for request data contained in the request bundle.
162 * <p>
163 * Optional, typically used to identify the specific data that is being referred to,
164 * such as the unique identifier for a movie or book. This is not used for display
165 * purposes and is more like a cookie. This value is returned in the
166 * {@link #EXTRA_RESPONSE_BUNDLE}.
167 * <p>
168 * Type: String
169 */
170 public static final String REQUEST_KEY_DATA = "android.req_template.data";
171
172 /**
173 * Key for request title contained in the request bundle.
174 * <p>
175 * Optional, typically used as the title of any notification or dialog presented
176 * to the administrator who approves the request.
177 * <p>
178 * Type: String
179 */
180 public static final String REQUEST_KEY_TITLE = "android.req_template.title";
181
182 /**
183 * Key for request message contained in the request bundle.
184 * <p>
185 * Required, shown as the actual message in a notification or dialog presented
186 * to the administrator who approves the request.
187 * <p>
188 * Type: String
189 */
190 public static final String REQUEST_KEY_MESSAGE = "android.req_template.mesg";
191
192 /**
193 * Key for request icon contained in the request bundle.
194 * <p>
195 * Optional, shown alongside the request message presented to the administrator
196 * who approves the request.
197 * <p>
198 * Type: Bitmap
199 */
200 public static final String REQUEST_KEY_ICON = "android.req_template.icon";
201
202 /**
203 * Key for request approval button label contained in the request bundle.
204 * <p>
205 * Optional, may be shown as a label on the positive button in a dialog or
206 * notification presented to the administrator who approves the request.
207 * <p>
208 * Type: String
209 */
210 public static final String REQUEST_KEY_APPROVE_LABEL = "android.req_template.accept";
211
212 /**
213 * Key for request rejection button label contained in the request bundle.
214 * <p>
215 * Optional, may be shown as a label on the negative button in a dialog or
216 * notification presented to the administrator who approves the request.
217 * <p>
218 * Type: String
219 */
220 public static final String REQUEST_KEY_DENY_LABEL = "android.req_template.reject";
221
222 /**
223 * Key for requestor's name contained in the request bundle. This value is not specified by
224 * the application. It is automatically inserted into the Bundle by the Restrictions Provider
225 * before it is sent to the administrator.
226 * <p>
227 * Type: String
228 */
229 public static final String REQUEST_KEY_REQUESTOR_NAME = "android.req_template.requestor";
230
231 /**
232 * Key for requestor's device name contained in the request bundle. This value is not specified
233 * by the application. It is automatically inserted into the Bundle by the Restrictions Provider
234 * before it is sent to the administrator.
235 * <p>
236 * Type: String
237 */
238 public static final String REQUEST_KEY_DEVICE_NAME = "android.req_template.device";
239
240 /**
241 * Key for the response in the response bundle sent to the application, for a permission
242 * request.
243 * <p>
244 * Type: boolean
245 */
246 public static final String RESPONSE_KEY_BOOLEAN = "android.req_template.response";
247
248 private static final String TAG = "RestrictionsManager";
249
250 private final Context mContext;
251 private final IRestrictionsManager mService;
252
253 /**
254 * @hide
255 */
256 public RestrictionsManager(Context context, IRestrictionsManager service) {
257 mContext = context;
258 mService = service;
259 }
260
261 /**
262 * Returns any available set of application-specific restrictions applicable
263 * to this application.
264 * @return
265 */
266 public Bundle getApplicationRestrictions() {
267 try {
268 if (mService != null) {
269 return mService.getApplicationRestrictions(mContext.getPackageName());
270 }
271 } catch (RemoteException re) {
272 Log.w(TAG, "Couldn't reach service");
273 }
274 return null;
275 }
276
277 /**
278 * Called by an application to check if permission requests can be made. If false,
279 * there is no need to request permission for an operation, unless a static
280 * restriction applies to that operation.
281 * @return
282 */
283 public boolean hasRestrictionsProvider() {
284 try {
285 if (mService != null) {
286 return mService.hasRestrictionsProvider();
287 }
288 } catch (RemoteException re) {
289 Log.w(TAG, "Couldn't reach service");
290 }
291 return false;
292 }
293
294 /**
295 * Called by an application to request permission for an operation. The contents of the
296 * request are passed in a Bundle that contains several pieces of data depending on the
297 * chosen request template.
298 *
299 * @param requestTemplate The request template to use. The template could be one of the
300 * predefined templates specified in this class or a custom template that the specific
301 * Restrictions Provider might understand. For custom templates, the template name should be
302 * namespaced to avoid collisions with predefined templates and templates specified by
303 * other Restrictions Provider vendors.
304 * @param requestData A Bundle containing the data corresponding to the specified request
305 * template. The keys for the data in the bundle depend on the kind of template chosen.
306 */
307 public void requestPermission(String requestTemplate, Bundle requestData) {
308 try {
309 if (mService != null) {
310 mService.requestPermission(mContext.getPackageName(), requestTemplate, requestData);
311 }
312 } catch (RemoteException re) {
313 Log.w(TAG, "Couldn't reach service");
314 }
315 }
316
317 /**
318 * Called by the Restrictions Provider when a response is available to be
319 * delivered to an application.
320 * @param packageName
321 * @param response
322 */
323 public void notifyPermissionResponse(String packageName, Bundle response) {
324 try {
325 if (mService != null) {
326 mService.notifyPermissionResponse(packageName, response);
327 }
328 } catch (RemoteException re) {
329 Log.w(TAG, "Couldn't reach service");
330 }
331 }
332
333 /**
334 * Parse and return the list of restrictions defined in the manifest for the specified
335 * package, if any.
336 * @param packageName The application for which to fetch the restrictions list.
337 * @return The list of RestrictionEntry objects created from the XML file specified
338 * in the manifest, or null if none was specified.
339 */
340 public List<RestrictionEntry> getManifestRestrictions(String packageName) {
341 // TODO:
342 return null;
343 }
344}