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