summaryrefslogtreecommitdiffstats
path: root/services/restrictions
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2014-07-10 13:41:55 -0700
committerAmith Yamasani <yamasani@google.com>2014-07-13 07:17:56 -0700
commitf6e2fcc2eaf5e650237d3c6d79a2de49d2d4111e (patch)
treefc4d32ee496c1021901cb5b50e463459908d7ae7 /services/restrictions
parent7ab9d759f5b5238b4ee6013f57454ed5d5f4927f (diff)
downloadframeworks_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.java171
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;
+ }
+ }
}
}