Revert some new APIs for restrictions provider

Simplify back to being a broadcast receiver and add an extra to
indicate that a new request is desired vs. returning a pending
response from before.

Change-Id: Iafd16ed98293a2cc09006d2cce097fc3d590bbe2
This commit is contained in:
Amith Yamasani
2014-07-14 17:38:27 -07:00
parent a4ab780877
commit 5470bc184a
8 changed files with 115 additions and 348 deletions

View File

@@ -118,9 +118,7 @@ LOCAL_SRC_FILES += \
core/java/android/content/IIntentReceiver.aidl \
core/java/android/content/IIntentSender.aidl \
core/java/android/content/IOnPrimaryClipChangedListener.aidl \
core/java/android/content/IPermissionResponseCallback.aidl \
core/java/android/content/IRestrictionsManager.aidl \
core/java/android/content/IRestrictionsProvider.aidl \
core/java/android/content/ISyncAdapter.aidl \
core/java/android/content/ISyncContext.aidl \
core/java/android/content/ISyncServiceAdapter.aidl \

View File

@@ -6571,11 +6571,10 @@ package android.bluetooth.le {
package android.content {
public abstract class AbstractRestrictionsProvider extends android.app.Service {
public abstract class AbstractRestrictionsProvider extends android.content.BroadcastReceiver {
ctor public AbstractRestrictionsProvider();
method public abstract android.os.Bundle getPermissionResponse(java.lang.String, java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void requestPermission(java.lang.String, java.lang.String, android.os.Bundle);
method public void onReceive(android.content.Context, android.content.Intent);
method public abstract void requestPermission(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle);
}
public abstract class AbstractThreadedSyncAdapter {
@@ -7957,24 +7956,25 @@ package android.content {
public class RestrictionsManager {
method public android.os.Bundle getApplicationRestrictions();
method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
method public void getPermissionResponse(java.lang.String, android.content.RestrictionsManager.PermissionResponseCallback);
method public boolean hasRestrictionsProvider();
method public void notifyPermissionResponse(java.lang.String, android.os.Bundle);
method public void requestPermission(java.lang.String, android.os.Bundle);
field public static final java.lang.String ACTION_PERMISSION_RESPONSE_RECEIVED = "android.intent.action.PERMISSION_RESPONSE_RECEIVED";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "package_name";
field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "response";
field public static final java.lang.String ACTION_REQUEST_PERMISSION = "android.content.action.REQUEST_PERMISSION";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_REQUEST_BUNDLE = "android.content.extra.REQUEST_BUNDLE";
field public static final java.lang.String EXTRA_REQUEST_TYPE = "android.content.extra.REQUEST_TYPE";
field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "android.content.extra.RESPONSE_BUNDLE";
field public static final java.lang.String REQUEST_KEY_APPROVE_LABEL = "android.request.approve_label";
field public static final java.lang.String REQUEST_KEY_DATA = "android.request.data";
field public static final java.lang.String REQUEST_KEY_DENY_LABEL = "android.request.deny_label";
field public static final java.lang.String REQUEST_KEY_DEVICE_NAME = "android.request.device";
field public static final java.lang.String REQUEST_KEY_ICON = "android.request.icon";
field public static final java.lang.String REQUEST_KEY_ID = "android.request.id";
field public static final java.lang.String REQUEST_KEY_MESSAGE = "android.request.mesg";
field public static final java.lang.String REQUEST_KEY_REQUESTOR_NAME = "android.request.requestor";
field public static final java.lang.String REQUEST_KEY_NEW_REQUEST = "android.request.new_request";
field public static final java.lang.String REQUEST_KEY_TITLE = "android.request.title";
field public static final java.lang.String REQUEST_TYPE_APPROVAL = "android.request.type.approval";
field public static final java.lang.String REQUEST_TYPE_LOCAL_APPROVAL = "android.request.type.local_approval";
field public static final java.lang.String REQUEST_TYPE_QUESTION = "android.request.type.question";
field public static final java.lang.String RESPONSE_KEY_ERROR_CODE = "android.response.errorcode";
field public static final java.lang.String RESPONSE_KEY_ERROR_MESSAGE = "android.response.errormsg";
field public static final java.lang.String RESPONSE_KEY_RESPONSE_TIMESTAMP = "android.response.timestamp";
@@ -7989,11 +7989,6 @@ package android.content {
field public static final int RESULT_UNKNOWN_REQUEST = 4; // 0x4
}
public static abstract class RestrictionsManager.PermissionResponseCallback {
ctor public RestrictionsManager.PermissionResponseCallback();
method public abstract void onResponse(android.os.Bundle);
}
public class SearchRecentSuggestionsProvider extends android.content.ContentProvider {
ctor public SearchRecentSuggestionsProvider();
method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);

View File

@@ -16,78 +16,65 @@
package android.content;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.os.Bundle;
import android.os.IBinder;
/**
* Abstract implementation of a Restrictions Provider Service. To implement a Restrictions Provider,
* extend from this class and implement the abstract methods. Export this service in the
* manifest. A profile owner device admin can then register this component as a Restrictions
* Provider using {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
* Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
* Restrictions Provider, extend from this class and implement the abstract methods.
* Export this receiver in the manifest. A profile owner device admin can then register this
* component as a Restrictions Provider using
* {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
* <p>
* The function of a Restrictions Provider is to transport permission requests from apps on this
* device to an administrator (most likely on a remote device or computer) and deliver back
* responses. The response should be sent back to the app via
* {@link RestrictionsManager#notifyPermissionResponse(String, Bundle)}.
* <p>
* Apps can also query previously received responses using
* {@link #getPermissionResponse(String, String)}. The period for which previously received
* responses are available is left to the implementation of the Restrictions Provider.
*
* @see RestrictionsManager
*/
public abstract class AbstractRestrictionsProvider extends Service {
public abstract class AbstractRestrictionsProvider extends BroadcastReceiver {
private static final String TAG = "AbstractRestrictionsProvider";
@Override
public final IBinder onBind(Intent intent) {
return new RestrictionsProviderWrapper().asBinder();
}
/**
* Checks to see if there is a response for a prior request and returns the response bundle if
* it exists. If there is no response yet or if the request is not known, the returned bundle
* should contain the response code in {@link RestrictionsManager#RESPONSE_KEY_RESULT}.
*
* @param packageName the application that is requesting a permission response.
* @param requestId the id of the request for which the response is needed.
* @return a bundle containing at a minimum the result of the request. It could contain other
* optional information such as error codes and cookies.
*
* @see RestrictionsManager#RESPONSE_KEY_RESULT
*/
public abstract Bundle getPermissionResponse(String packageName, String requestId);
/**
* An asynchronous permission request made by an application for an operation that requires
* authorization by a local or remote administrator other than the user. The Restrictions
* Provider must transfer the request to the administrator and deliver back a response, when
* Provider should transfer the request to the administrator and deliver back a response, when
* available. The calling application is aware that the response could take an indefinite
* amount of time.
* <p>
* If the request bundle contains the key {@link RestrictionsManager#REQUEST_KEY_NEW_REQUEST},
* then a new request must be sent. Otherwise the provider can look up any previous response
* to the same requestId and return the cached response.
*
* @param packageName the application requesting permission.
* @param requestType the type of request, which determines the content and presentation of
* the request data.
* @param request the request data bundle containing at a minimum a request id.
*
* @see RestrictionsManager#REQUEST_TYPE_QUESTION
* @see RestrictionsManager#REQUEST_TYPE_APPROVAL
* @see RestrictionsManager#REQUEST_TYPE_LOCAL_APPROVAL
* @see RestrictionsManager#REQUEST_KEY_ID
*/
public abstract void requestPermission(String packageName, String requestType, Bundle request);
public abstract void requestPermission(Context context,
String packageName, String requestType, Bundle request);
private class RestrictionsProviderWrapper extends IRestrictionsProvider.Stub {
/**
* Intercept standard Restrictions Provider broadcasts. Implementations
* should not override this method; it is better to implement the
* convenience callbacks for each action.
*/
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@Override
public Bundle getPermissionResponse(String packageName, String requestId) {
return AbstractRestrictionsProvider.this
.getPermissionResponse(packageName, requestId);
}
@Override
public void requestPermission(String packageName, String templateId, Bundle request) {
AbstractRestrictionsProvider.this.requestPermission(packageName, templateId, request);
if (RestrictionsManager.ACTION_REQUEST_PERMISSION.equals(action)) {
String packageName = intent.getStringExtra(RestrictionsManager.EXTRA_PACKAGE_NAME);
String requestType = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_TYPE);
Bundle request = intent.getBundleExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE);
requestPermission(context, packageName, requestType, request);
}
}
}

View File

@@ -1,30 +0,0 @@
/*
** Copyright 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.os.Bundle;
/**
* Callback for permission response queries.
*
* @hide
*/
interface IPermissionResponseCallback {
void onResponse(in Bundle response);
}

View File

@@ -17,7 +17,6 @@
package android.content;
import android.os.Bundle;
import android.content.IPermissionResponseCallback;
/**
* Interface used by the RestrictionsManager
@@ -28,6 +27,4 @@ interface IRestrictionsManager {
boolean hasRestrictionsProvider();
void requestPermission(in String packageName, in String requestTemplate, in Bundle requestData);
void notifyPermissionResponse(in String packageName, in Bundle response);
void getPermissionResponse(in String packageName, in String requestId,
in IPermissionResponseCallback callback);
}

View File

@@ -1,31 +0,0 @@
/*
** Copyright 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.os.Bundle;
/**
* Interface to a restrictions provider service component.
*
* @hide
*/
interface IRestrictionsProvider {
void requestPermission(in String packageName, in String requestType, in Bundle requestBundle);
Bundle getPermissionResponse(in String packageName, in String requestId);
}

View File

@@ -32,21 +32,17 @@ import java.util.List;
* <p>
* Apps can expose a set of restrictions via an XML file specified in the manifest.
* <p>
* If the user has an active restrictions provider, dynamic requests can be made in
* 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 request types.
* <p>
* The RestrictionsManager forwards the dynamic requests to the active
* restrictions provider. The restrictions provider can respond back to requests by calling
* 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}.
* <p>
* Prior responses to requests can also be queried through calls to
* {@link #getPermissionResponse(String, PermissionResponseCallback)}, if the provider
* saves old responses.
* <p>
* 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 list of available restrictions from the apk.
@@ -72,10 +68,8 @@ public class RestrictionsManager {
private static final String TAG = "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
* Broadcast intent delivered when a response is received for a permission request. The
* application should not interrupt the user by coming to the foreground if it isn't
* currently in the foreground. It can either post a notification informing
* the user of the response or wait until the next time the user launches the app.
* <p>
@@ -88,10 +82,33 @@ public class RestrictionsManager {
public static final String ACTION_PERMISSION_RESPONSE_RECEIVED =
"android.intent.action.PERMISSION_RESPONSE_RECEIVED";
/**
* Broadcast intent sent to the Restrictions Provider to handle a permission request from
* an app. It will have the following extras: {@link #EXTRA_PACKAGE_NAME},
* {@link #EXTRA_REQUEST_TYPE} and {@link #EXTRA_REQUEST_BUNDLE}. The Restrictions Provider
* will handle the request and respond back to the RestrictionsManager, when a response is
* available, by calling {@link #notifyPermissionResponse}.
* <p>
* The BroadcastReceiver must require the {@link android.Manifest.permission#BIND_DEVICE_ADMIN}
* permission to ensure that only the system can send the broadcast.
*/
public static final String ACTION_REQUEST_PERMISSION =
"android.content.action.REQUEST_PERMISSION";
/**
* The package name of the application making the request.
*/
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
/**
* The request type passed in the {@link #ACTION_REQUEST_PERMISSION} broadcast.
*/
public static final String EXTRA_REQUEST_TYPE = "android.content.extra.REQUEST_TYPE";
/**
* The request bundle passed in the {@link #ACTION_REQUEST_PERMISSION} broadcast.
*/
public static final String EXTRA_REQUEST_BUNDLE = "android.content.extra.REQUEST_BUNDLE";
/**
* Contains a response from the administrator for specific request.
@@ -101,7 +118,7 @@ public class RestrictionsManager {
* <li>{@link #RESPONSE_KEY_RESULT}: The response result.</li>
* </ul>
*/
public static final String EXTRA_RESPONSE_BUNDLE = "response";
public static final String EXTRA_RESPONSE_BUNDLE = "android.content.extra.RESPONSE_BUNDLE";
/**
* Request type for a simple question, with a possible title and icon.
@@ -113,7 +130,7 @@ public class RestrictionsManager {
* {@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_TYPE_QUESTION = "android.request.type.question";
public static final String REQUEST_TYPE_APPROVAL = "android.request.type.approval";
/**
* Request type for a local password challenge. This is a way for an app to ask
@@ -204,22 +221,14 @@ public class RestrictionsManager {
public static final String REQUEST_KEY_DENY_LABEL = "android.request.deny_label";
/**
* 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.
* Key for issuing a new request, contained in the request bundle. If this is set to true,
* the Restrictions Provider must make a new request. If it is false or not specified, then
* the Restrictions Provider can return a cached response that has the same requestId, if
* available. If there's no cached response, it will issue a new one to the administrator.
* <p>
* Type: String
* Type: boolean
*/
public static final String REQUEST_KEY_REQUESTOR_NAME = "android.request.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.
* <p>
* Type: String
*/
public static final String REQUEST_KEY_DEVICE_NAME = "android.request.device";
public static final String REQUEST_KEY_NEW_REQUEST = "android.request.new_request";
/**
* Key for the response in the response bundle sent to the application, for a permission
@@ -249,8 +258,8 @@ public class RestrictionsManager {
public static final int RESULT_NO_RESPONSE = 3;
/**
* Response result value indicating that the request is unknown, when returned through a
* call to #getPendingResponse
* Response result value indicating that the request is unknown, when it's not a new
* request.
*/
public static final int RESULT_UNKNOWN_REQUEST = 4;
@@ -311,19 +320,6 @@ public class RestrictionsManager {
private final Context mContext;
private final IRestrictionsManager mService;
/**
* Callback object for returning a response for a request.
*
* @see #getPermissionResponse
*/
public static abstract class PermissionResponseCallback {
/**
* Contains the response
* @param response
*/
public abstract void onResponse(Bundle response);
}
/**
* @hide
*/
@@ -350,11 +346,10 @@ public class RestrictionsManager {
}
/**
* Called by an application to check if there is an active restrictions provider. If
* there isn't, {@link #getPermissionResponse(String, PermissionResponseCallback)}
* and {@link #requestPermission(String, Bundle)} are not available.
* Called by an application to check if there is an active Restrictions Provider. If
* there isn't, {@link #requestPermission(String, Bundle)} is not available.
*
* @return whether there is an active restrictions provider.
* @return whether there is an active Restrictions Provider.
*/
public boolean hasRestrictionsProvider() {
try {
@@ -374,13 +369,24 @@ public class RestrictionsManager {
*
* @param requestType The type of request. The type could be one of the
* predefined types specified here or a custom type that the specific
* restrictions provider might understand. For custom types, the type name should be
* Restrictions Provider might understand. For custom types, the type name should be
* namespaced to avoid collisions with predefined types and types specified by
* other restrictions providers.
* other Restrictions Providers.
* @param request A Bundle containing the data corresponding to the specified request
* type. The keys for the data in the bundle depend on the request type.
*
* @throws IllegalArgumentException if any of the required parameters are missing.
*/
public void requestPermission(String requestType, Bundle request) {
if (requestType == null) {
throw new NullPointerException("requestType cannot be null");
}
if (request == null) {
throw new NullPointerException("request cannot be null");
}
if (!request.containsKey(REQUEST_KEY_ID)) {
throw new IllegalArgumentException("REQUEST_KEY_ID must be specified");
}
try {
if (mService != null) {
mService.requestPermission(mContext.getPackageName(), requestType, request);
@@ -391,41 +397,27 @@ public class RestrictionsManager {
}
/**
* Called by an application to query for any available response from the restrictions provider
* for the given requestId. The call returns immediately and the response will be returned
* via the provided callback. This does not initiate a new request and does not wait
* for a response to be received. It merely returns any previously received response
* or indicates if there was no available response. If there are multiple responses
* available for the same request ID, the most recent one is returned.
* Called by the Restrictions Provider to deliver a response to an application.
*
* @param requestId The ID of the original request made via
* {@link #requestPermission(String, Bundle)}. It's possible to also query for responses
* to requests made on a different device with the same requestId, if the Restrictions
* Provider happens to sync responses across devices with the same account managed by the
* restrictions provider.
* @param callback The response is returned via the callback object. Cannot be null.
*/
public void getPermissionResponse(String requestId, PermissionResponseCallback callback) {
if (requestId == null || callback == null) {
throw new NullPointerException("requestId or callback cannot be null");
}
try {
if (mService != null) {
mService.getPermissionResponse(mContext.getPackageName(), requestId,
new PermissionResponseCallbackWrapper(callback));
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
}
}
/**
* Called by the restrictions provider to deliver a response to an application.
*
* @param packageName the application to deliver the response to.
* @param packageName the application to deliver the response to. Cannot be null.
* @param response the Bundle containing the response status, request ID and other information.
* Cannot be null.
*
* @throws IllegalArgumentException if any of the required parameters are missing.
*/
public void notifyPermissionResponse(String packageName, Bundle response) {
if (packageName == null) {
throw new NullPointerException("packageName cannot be null");
}
if (response == null) {
throw new NullPointerException("request cannot be null");
}
if (!response.containsKey(REQUEST_KEY_ID)) {
throw new IllegalArgumentException("REQUEST_KEY_ID must be specified");
}
if (!response.containsKey(RESPONSE_KEY_RESULT)) {
throw new IllegalArgumentException("RESPONSE_KEY_RESULT must be specified");
}
try {
if (mService != null) {
mService.notifyPermissionResponse(packageName, response);
@@ -447,19 +439,4 @@ public class RestrictionsManager {
// TODO:
return null;
}
private static class PermissionResponseCallbackWrapper
extends IPermissionResponseCallback.Stub {
private PermissionResponseCallback mCallback;
PermissionResponseCallbackWrapper(PermissionResponseCallback callback) {
mCallback = callback;
}
@Override
public void onResponse(Bundle response) {
mCallback.onResponse(response);
}
}
}

View File

@@ -23,17 +23,13 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.IDevicePolicyManager;
import android.content.AbstractRestrictionsProvider;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IPermissionResponseCallback;
import android.content.IRestrictionsProvider;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -127,58 +123,12 @@ public final class RestrictionsManagerService extends SystemService {
enforceCallerMatchesPackage(callingUid, packageName, "Package name does not" +
" match caller ");
// Prepare and broadcast the intent to the provider
Intent intent = new Intent();
Intent intent = new Intent(RestrictionsManager.ACTION_REQUEST_PERMISSION);
intent.setComponent(restrictionsProvider);
new ProviderServiceConnection(intent, null, userHandle) {
@Override
public void run() throws RemoteException {
if (DEBUG) {
Log.i(LOG_TAG, "calling requestPermission for " + packageName
+ ", type=" + requestType + ", data=" + requestData);
}
mRestrictionsProvider.requestPermission(packageName,
requestType, requestData);
}
}.bind();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
@Override
public void getPermissionResponse(final String packageName, final String requestId,
final IPermissionResponseCallback callback) throws RemoteException {
int callingUid = Binder.getCallingUid();
int userHandle = UserHandle.getUserId(callingUid);
if (mDpm != null) {
long ident = Binder.clearCallingIdentity();
try {
ComponentName restrictionsProvider =
mDpm.getRestrictionsProvider(userHandle);
// Check if there is a restrictions provider
if (restrictionsProvider == null) {
throw new IllegalStateException(
"Cannot fetch permission without a restrictions provider registered");
}
// Check that the packageName matches the caller.
enforceCallerMatchesPackage(callingUid, packageName, "Package name does not" +
" match caller ");
// Prepare and broadcast the intent to the provider
Intent intent = new Intent();
intent.setComponent(restrictionsProvider);
new ProviderServiceConnection(intent, callback.asBinder(), userHandle) {
@Override
public void run() throws RemoteException {
if (DEBUG) {
Log.i(LOG_TAG, "calling getPermissionResponse for " + packageName
+ ", id=" + requestId);
}
Bundle response = mRestrictionsProvider.getPermissionResponse(
packageName, requestId);
callback.onResponse(response);
}
}.bind();
intent.putExtra(RestrictionsManager.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RestrictionsManager.EXTRA_REQUEST_TYPE, requestType);
intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, requestData);
mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -226,81 +176,5 @@ public final class RestrictionsManagerService extends SystemService {
// Shouldn't happen
}
}
abstract class ProviderServiceConnection
implements IBinder.DeathRecipient, ServiceConnection {
protected IRestrictionsProvider mRestrictionsProvider;
private Intent mIntent;
protected int mUserHandle;
protected IBinder mResponse;
private boolean mAbort;
public ProviderServiceConnection(Intent intent, IBinder response, int userHandle) {
mIntent = intent;
mResponse = response;
mUserHandle = userHandle;
if (mResponse != null) {
try {
mResponse.linkToDeath(this, 0 /* flags */);
} catch (RemoteException re) {
close();
}
}
}
/** Bind to the RestrictionsProvider process */
public void bind() {
if (DEBUG) {
Log.i(LOG_TAG, "binding to service: " + mIntent);
}
mContext.bindServiceAsUser(mIntent, this, Context.BIND_AUTO_CREATE,
new UserHandle(mUserHandle));
}
private void close() {
mAbort = true;
unbind();
}
private void unbind() {
if (DEBUG) {
Log.i(LOG_TAG, "unbinding from service");
}
mContext.unbindService(this);
}
/** Implement this to call the appropriate method on the service */
public abstract void run() throws RemoteException;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) {
Log.i(LOG_TAG, "connected to " + name);
}
mRestrictionsProvider = IRestrictionsProvider.Stub.asInterface(service);
if (!mAbort) {
try {
run();
} catch (RemoteException re) {
Log.w("RestrictionsProvider", "Remote exception: " + re);
}
}
close();
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) {
Log.i(LOG_TAG, "disconnected from " + name);
}
mRestrictionsProvider = null;
}
@Override
public void binderDied() {
mAbort = true;
}
}
}
}