Home | History | Annotate | Download | only in restrictions
      1 /*
      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 
     17 package com.android.server.restrictions;
     18 
     19 import android.app.AppGlobals;
     20 import android.app.admin.IDevicePolicyManager;
     21 import android.content.ComponentName;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IRestrictionsManager;
     25 import android.content.RestrictionsManager;
     26 import android.content.pm.ResolveInfo;
     27 import android.os.Binder;
     28 import android.os.Bundle;
     29 import android.os.IUserManager;
     30 import android.os.PersistableBundle;
     31 import android.os.RemoteException;
     32 import android.os.UserHandle;
     33 import android.util.Log;
     34 
     35 import com.android.internal.util.ArrayUtils;
     36 import com.android.server.SystemService;
     37 
     38 /**
     39  * SystemService wrapper for the RestrictionsManager implementation. Publishes the
     40  * Context.RESTRICTIONS_SERVICE.
     41  */
     42 public final class RestrictionsManagerService extends SystemService {
     43 
     44     static final String LOG_TAG = "RestrictionsManagerService";
     45     static final boolean DEBUG = false;
     46 
     47     private final RestrictionsManagerImpl mRestrictionsManagerImpl;
     48 
     49     public RestrictionsManagerService(Context context) {
     50         super(context);
     51         mRestrictionsManagerImpl = new RestrictionsManagerImpl(context);
     52     }
     53 
     54     @Override
     55     public void onStart() {
     56         publishBinderService(Context.RESTRICTIONS_SERVICE, mRestrictionsManagerImpl);
     57     }
     58 
     59     class RestrictionsManagerImpl extends IRestrictionsManager.Stub {
     60         final Context mContext;
     61         private final IUserManager mUm;
     62         private final IDevicePolicyManager mDpm;
     63 
     64         public RestrictionsManagerImpl(Context context) {
     65             mContext = context;
     66             mUm = (IUserManager) getBinderService(Context.USER_SERVICE);
     67             mDpm = (IDevicePolicyManager) getBinderService(Context.DEVICE_POLICY_SERVICE);
     68         }
     69 
     70         @Override
     71         public Bundle getApplicationRestrictions(String packageName) throws RemoteException {
     72             return mUm.getApplicationRestrictions(packageName);
     73         }
     74 
     75         @Override
     76         public boolean hasRestrictionsProvider() throws RemoteException {
     77             int userHandle = UserHandle.getCallingUserId();
     78             if (mDpm != null) {
     79                 long ident = Binder.clearCallingIdentity();
     80                 try {
     81                     return mDpm.getRestrictionsProvider(userHandle) != null;
     82                 } finally {
     83                     Binder.restoreCallingIdentity(ident);
     84                 }
     85             } else {
     86                 return false;
     87             }
     88         }
     89 
     90         @Override
     91         public void requestPermission(final String packageName, final String requestType,
     92                 final String requestId,
     93                 final PersistableBundle requestData) throws RemoteException {
     94             if (DEBUG) {
     95                 Log.i(LOG_TAG, "requestPermission");
     96             }
     97             int callingUid = Binder.getCallingUid();
     98             int userHandle = UserHandle.getUserId(callingUid);
     99             if (mDpm != null) {
    100                 long ident = Binder.clearCallingIdentity();
    101                 try {
    102                     ComponentName restrictionsProvider =
    103                             mDpm.getRestrictionsProvider(userHandle);
    104                     // Check if there is a restrictions provider
    105                     if (restrictionsProvider == null) {
    106                         throw new IllegalStateException(
    107                             "Cannot request permission without a restrictions provider registered");
    108                     }
    109                     // Check that the packageName matches the caller.
    110                     enforceCallerMatchesPackage(callingUid, packageName, "Package name does not" +
    111                             " match caller ");
    112                     // Prepare and broadcast the intent to the provider
    113                     Intent intent = new Intent(RestrictionsManager.ACTION_REQUEST_PERMISSION);
    114                     intent.setComponent(restrictionsProvider);
    115                     intent.putExtra(RestrictionsManager.EXTRA_PACKAGE_NAME, packageName);
    116                     intent.putExtra(RestrictionsManager.EXTRA_REQUEST_TYPE, requestType);
    117                     intent.putExtra(RestrictionsManager.EXTRA_REQUEST_ID, requestId);
    118                     intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, requestData);
    119                     mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
    120                 } finally {
    121                     Binder.restoreCallingIdentity(ident);
    122                 }
    123             }
    124         }
    125 
    126         @Override
    127         public Intent createLocalApprovalIntent() throws RemoteException {
    128             if (DEBUG) {
    129                 Log.i(LOG_TAG, "requestPermission");
    130             }
    131             final int userHandle = UserHandle.getCallingUserId();
    132             if (mDpm != null) {
    133                 long ident = Binder.clearCallingIdentity();
    134                 try {
    135                     ComponentName restrictionsProvider =
    136                             mDpm.getRestrictionsProvider(userHandle);
    137                     // Check if there is a restrictions provider
    138                     if (restrictionsProvider == null) {
    139                         throw new IllegalStateException(
    140                             "Cannot request permission without a restrictions provider registered");
    141                     }
    142                     String providerPackageName = restrictionsProvider.getPackageName();
    143                     Intent intent = new Intent(RestrictionsManager.ACTION_REQUEST_LOCAL_APPROVAL);
    144                     intent.setPackage(providerPackageName);
    145                     ResolveInfo ri = AppGlobals.getPackageManager().resolveIntent(intent,
    146                             null /* resolvedType */, 0 /* flags */, userHandle);
    147                     if (ri != null && ri.activityInfo != null && ri.activityInfo.exported) {
    148                         intent.setComponent(new ComponentName(ri.activityInfo.packageName,
    149                                 ri.activityInfo.name));
    150                         return intent;
    151                     }
    152                 } finally {
    153                     Binder.restoreCallingIdentity(ident);
    154                 }
    155             }
    156             return null;
    157         }
    158 
    159         @Override
    160         public void notifyPermissionResponse(String packageName, PersistableBundle response)
    161                 throws RemoteException {
    162             // Check caller
    163             int callingUid = Binder.getCallingUid();
    164             int userHandle = UserHandle.getUserId(callingUid);
    165             if (mDpm != null) {
    166                 long ident = Binder.clearCallingIdentity();
    167                 try {
    168                     ComponentName permProvider = mDpm.getRestrictionsProvider(userHandle);
    169                     if (permProvider == null) {
    170                         throw new SecurityException("No restrictions provider registered for user");
    171                     }
    172                     enforceCallerMatchesPackage(callingUid, permProvider.getPackageName(),
    173                             "Restrictions provider does not match caller ");
    174 
    175                     // Post the response to target package
    176                     Intent responseIntent = new Intent(
    177                             RestrictionsManager.ACTION_PERMISSION_RESPONSE_RECEIVED);
    178                     responseIntent.setPackage(packageName);
    179                     responseIntent.putExtra(RestrictionsManager.EXTRA_RESPONSE_BUNDLE, response);
    180                     mContext.sendBroadcastAsUser(responseIntent, new UserHandle(userHandle));
    181                 } finally {
    182                     Binder.restoreCallingIdentity(ident);
    183                 }
    184             }
    185         }
    186 
    187         private void enforceCallerMatchesPackage(int callingUid, String packageName,
    188                 String message) {
    189             try {
    190                 String[] pkgs = AppGlobals.getPackageManager().getPackagesForUid(callingUid);
    191                 if (pkgs != null) {
    192                     if (!ArrayUtils.contains(pkgs, packageName)) {
    193                         throw new SecurityException(message + callingUid);
    194                     }
    195                 }
    196             } catch (RemoteException re) {
    197                 // Shouldn't happen
    198             }
    199         }
    200     }
    201 }
    202