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 RestrictionsManagerService(Context context)49 public RestrictionsManagerService(Context context) { 50 super(context); 51 mRestrictionsManagerImpl = new RestrictionsManagerImpl(context); 52 } 53 54 @Override onStart()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 RestrictionsManagerImpl(Context context)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 getApplicationRestrictions(String packageName)71 public Bundle getApplicationRestrictions(String packageName) throws RemoteException { 72 return mUm.getApplicationRestrictions(packageName); 73 } 74 75 @Override hasRestrictionsProvider()76 public boolean hasRestrictionsProvider() throws RemoteException { 77 int userHandle = UserHandle.getCallingUserId(); 78 if (mDpm != null) { 79 final 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 requestPermission(final String packageName, final String requestType, final String requestId, final PersistableBundle requestData)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 final 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 createLocalApprovalIntent()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 final 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 notifyPermissionResponse(String packageName, PersistableBundle response)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 final 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 enforceCallerMatchesPackage(int callingUid, String packageName, String message)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