/* * Copyright (C) 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 android.content; import android.app.admin.DevicePolicyManager; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import java.util.Collections; import java.util.List; /** * Provides a mechanism for apps to query restrictions imposed by an entity that * manages the user. Apps can also send permission requests to a local or remote * device administrator to override default app-specific restrictions or any other * operation that needs explicit authorization from the administrator. *
* Apps can expose a set of restrictions via a runtime receiver mechanism or via * static meta data in the manifest. *
* If the user has an active restrictions provider, dynamic requests can be made in * addition to the statically imposed restrictions. Dynamic requests are app-specific * and can be expressed via a predefined set of templates. *
* The RestrictionsManager forwards the dynamic requests to the active * restrictions provider. The restrictions provider can respond back to requests by calling * {@link #notifyPermissionResponse(String, Bundle)}, when * a response is received from the administrator of the device or user * The response is relayed back to the application via a protected broadcast, * {@link #ACTION_PERMISSION_RESPONSE_RECEIVED}. *
* Static restrictions are specified by an XML file referenced by a meta-data attribute * in the manifest. This enables applications as well as any web administration consoles * to be able to read the template from the apk. *
* The syntax of the XML format is as follows: *
* <restrictions> * <restriction * android:key="<key>" * android:restrictionType="boolean|string|integer|multi-select|null" * ... /> * <restriction ... /> * </restrictions> **
* The attributes for each restriction depend on the restriction type. * * @see RestrictionEntry */ public class RestrictionsManager { /** * Broadcast intent delivered when a response is received for a permission * request. The response is not available for later query, so the receiver * must persist and/or immediately act upon the response. The application * should not interrupt the user by coming to the foreground if it isn't * currently in the foreground. It can post a notification instead, informing * the user of a change in state. *
* For instance, if the user requested permission to make an in-app purchase, * the app can post a notification that the request had been granted or denied, * and allow the purchase to go through. *
* The broadcast Intent carries the following extra: * {@link #EXTRA_RESPONSE_BUNDLE}. */ public static final String ACTION_PERMISSION_RESPONSE_RECEIVED = "android.intent.action.PERMISSION_RESPONSE_RECEIVED"; /** * Protected broadcast intent sent to the active restrictions provider. The intent * contains the following extras:
*
* And depending on what the request template was, the bundle will contain the actual * result of the request. For {@link #REQUEST_TEMPLATE_QUESTION}, the result will be in * {@link #RESPONSE_KEY_BOOLEAN}, which is of type boolean; true if the administrator * approved the request, false otherwise. */ public static final String EXTRA_RESPONSE_BUNDLE = "response_bundle"; /** * Request template that presents a simple question, with a possible title and icon. *
* Required keys are * {@link #REQUEST_KEY_ID} and {@link #REQUEST_KEY_MESSAGE}. *
* Optional keys are * {@link #REQUEST_KEY_DATA}, {@link #REQUEST_KEY_ICON}, {@link #REQUEST_KEY_TITLE}, * {@link #REQUEST_KEY_APPROVE_LABEL} and {@link #REQUEST_KEY_DENY_LABEL}. */ public static final String REQUEST_TEMPLATE_QUESTION = "android.req_template.type.simple"; /** * Key for request ID contained in the request bundle. *
* App-generated request id to identify the specific request when receiving * a response. This value is returned in the {@link #EXTRA_RESPONSE_BUNDLE}. *
* Type: String */ public static final String REQUEST_KEY_ID = "android.req_template.req_id"; /** * Key for request data contained in the request bundle. *
* Optional, typically used to identify the specific data that is being referred to, * such as the unique identifier for a movie or book. This is not used for display * purposes and is more like a cookie. This value is returned in the * {@link #EXTRA_RESPONSE_BUNDLE}. *
* Type: String */ public static final String REQUEST_KEY_DATA = "android.req_template.data"; /** * Key for request title contained in the request bundle. *
* Optional, typically used as the title of any notification or dialog presented * to the administrator who approves the request. *
* Type: String */ public static final String REQUEST_KEY_TITLE = "android.req_template.title"; /** * Key for request message contained in the request bundle. *
* Required, shown as the actual message in a notification or dialog presented * to the administrator who approves the request. *
* Type: String */ public static final String REQUEST_KEY_MESSAGE = "android.req_template.mesg"; /** * Key for request icon contained in the request bundle. *
* Optional, shown alongside the request message presented to the administrator * who approves the request. *
* Type: Bitmap */ public static final String REQUEST_KEY_ICON = "android.req_template.icon"; /** * Key for request approval button label contained in the request bundle. *
* Optional, may be shown as a label on the positive button in a dialog or * notification presented to the administrator who approves the request. *
* Type: String */ public static final String REQUEST_KEY_APPROVE_LABEL = "android.req_template.accept"; /** * Key for request rejection button label contained in the request bundle. *
* Optional, may be shown as a label on the negative button in a dialog or * notification presented to the administrator who approves the request. *
* Type: String */ public static final String REQUEST_KEY_DENY_LABEL = "android.req_template.reject"; /** * Key for requestor's name contained in the request bundle. This value is not specified by * the application. It is automatically inserted into the Bundle by the Restrictions Provider * before it is sent to the administrator. *
* Type: String */ public static final String REQUEST_KEY_REQUESTOR_NAME = "android.req_template.requestor"; /** * Key for requestor's device name contained in the request bundle. This value is not specified * by the application. It is automatically inserted into the Bundle by the Restrictions Provider * before it is sent to the administrator. *
* Type: String */ public static final String REQUEST_KEY_DEVICE_NAME = "android.req_template.device"; /** * Key for the response in the response bundle sent to the application, for a permission * request. *
* Type: boolean
*/
public static final String RESPONSE_KEY_BOOLEAN = "android.req_template.response";
private static final String TAG = "RestrictionsManager";
private final Context mContext;
private final IRestrictionsManager mService;
/**
* @hide
*/
public RestrictionsManager(Context context, IRestrictionsManager service) {
mContext = context;
mService = service;
}
/**
* Returns any available set of application-specific restrictions applicable
* to this application.
* @return
*/
public Bundle getApplicationRestrictions() {
try {
if (mService != null) {
return mService.getApplicationRestrictions(mContext.getPackageName());
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
}
return null;
}
/**
* Called by an application to check if permission requests can be made. If false,
* there is no need to request permission for an operation, unless a static
* restriction applies to that operation.
* @return
*/
public boolean hasRestrictionsProvider() {
try {
if (mService != null) {
return mService.hasRestrictionsProvider();
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
}
return false;
}
/**
* Called by an application to request permission for an operation. The contents of the
* request are passed in a Bundle that contains several pieces of data depending on the
* chosen request template.
*
* @param requestTemplate The request template to use. The template could be one of the
* predefined templates specified in this class or a custom template that the specific
* Restrictions Provider might understand. For custom templates, the template name should be
* namespaced to avoid collisions with predefined templates and templates specified by
* other Restrictions Provider vendors.
* @param requestData A Bundle containing the data corresponding to the specified request
* template. The keys for the data in the bundle depend on the kind of template chosen.
*/
public void requestPermission(String requestTemplate, Bundle requestData) {
try {
if (mService != null) {
mService.requestPermission(mContext.getPackageName(), requestTemplate, requestData);
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
}
}
/**
* Called by the Restrictions Provider when a response is available to be
* delivered to an application.
* @param packageName
* @param response
*/
public void notifyPermissionResponse(String packageName, Bundle response) {
try {
if (mService != null) {
mService.notifyPermissionResponse(packageName, response);
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
}
}
/**
* Parse and return the list of restrictions defined in the manifest for the specified
* package, if any.
* @param packageName The application for which to fetch the restrictions list.
* @return The list of RestrictionEntry objects created from the XML file specified
* in the manifest, or null if none was specified.
*/
public List