diff options
author | Amith Yamasani <yamasani@google.com> | 2014-07-10 13:41:55 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2014-07-13 07:17:56 -0700 |
commit | f6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e (patch) | |
tree | fc4d32ee496c1021901cb5b50e463459908d7ae7 /services/restrictions | |
parent | 7ab9d759f5b5238b4ee6013f57454ed5d5f4927f (diff) | |
download | frameworks_base-f6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e.zip frameworks_base-f6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e.tar.gz frameworks_base-f6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e.tar.bz2 |
Improvements to Restrictions API
Convert restrictions provider to a service instead of a receiver.
Add a way to get pending responses from restrictions provider.
Add AbstractRestrictionsProvider.
Add a callback API for responses.
Removed some constants in RestrictionsManager.
Added new constants for errors and error codes.
Much improved javadocs.
Bug: 16176009
Change-Id: I838a50fabc80b94b632294b3a55cd5d8092acf55
Diffstat (limited to 'services/restrictions')
-rw-r--r-- | services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java | 171 |
1 files changed, 153 insertions, 18 deletions
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java index e1f77b3..1db3c5e 100644 --- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java +++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java @@ -17,18 +17,23 @@ package com.android.server.restrictions; import android.Manifest; +import android.accounts.IAccountAuthenticator; import android.app.AppGlobals; 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; @@ -37,11 +42,13 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import android.os.IUserManager; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.util.Log; import com.android.internal.util.ArrayUtils; import com.android.server.SystemService; @@ -50,8 +57,11 @@ import com.android.server.SystemService; * SystemService wrapper for the RestrictionsManager implementation. Publishes the * Context.RESTRICTIONS_SERVICE. */ - public final class RestrictionsManagerService extends SystemService { + + static final String LOG_TAG = "RestrictionsManagerService"; + static final boolean DEBUG = false; + private final RestrictionsManagerImpl mRestrictionsManagerImpl; public RestrictionsManagerService(Context context) { @@ -65,7 +75,7 @@ public final class RestrictionsManagerService extends SystemService { } class RestrictionsManagerImpl extends IRestrictionsManager.Stub { - private final Context mContext; + final Context mContext; private final IUserManager mUm; private final IDevicePolicyManager mDpm; @@ -96,8 +106,11 @@ public final class RestrictionsManagerService extends SystemService { } @Override - public void requestPermission(String packageName, String requestTemplate, - Bundle requestData) throws RemoteException { + public void requestPermission(final String packageName, final String requestType, + final Bundle requestData) throws RemoteException { + if (DEBUG) { + Log.i(LOG_TAG, "requestPermission"); + } int callingUid = Binder.getCallingUid(); int userHandle = UserHandle.getUserId(callingUid); if (mDpm != null) { @@ -114,29 +127,61 @@ 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(RestrictionsManager.ACTION_REQUEST_PERMISSION); + Intent intent = new Intent(); intent.setComponent(restrictionsProvider); - intent.putExtra(RestrictionsManager.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(RestrictionsManager.EXTRA_TEMPLATE_ID, requestTemplate); - intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, requestData); - mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle)); + 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); } } } - private void enforceCallerMatchesPackage(int callingUid, String packageName, - String message) { - try { - String[] pkgs = AppGlobals.getPackageManager().getPackagesForUid(callingUid); - if (pkgs != null) { - if (!ArrayUtils.contains(pkgs, packageName)) { - throw new SecurityException(message + callingUid); + @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(); + } finally { + Binder.restoreCallingIdentity(ident); } - } catch (RemoteException re) { - // Shouldn't happen } } @@ -167,5 +212,95 @@ public final class RestrictionsManagerService extends SystemService { } } } + + private void enforceCallerMatchesPackage(int callingUid, String packageName, + String message) { + try { + String[] pkgs = AppGlobals.getPackageManager().getPackagesForUid(callingUid); + if (pkgs != null) { + if (!ArrayUtils.contains(pkgs, packageName)) { + throw new SecurityException(message + callingUid); + } + } + } catch (RemoteException re) { + // 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; + } + } } } |