1 /* 2 ** Copyright 2017, 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.accessibility; 18 19 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; 20 21 import android.accessibilityservice.AccessibilityServiceInfo; 22 import android.accessibilityservice.IAccessibilityServiceClient; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.ParceledListSlice; 27 import android.os.Binder; 28 import android.os.Handler; 29 import android.os.IBinder; 30 import android.os.RemoteException; 31 import android.os.UserHandle; 32 import android.provider.Settings; 33 import android.util.Slog; 34 35 import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy; 36 import com.android.server.accessibility.AccessibilityManagerService.UserState; 37 import com.android.server.wm.ActivityTaskManagerInternal; 38 import com.android.server.wm.WindowManagerInternal; 39 40 import java.lang.ref.WeakReference; 41 import java.util.Set; 42 43 /** 44 * This class represents an accessibility service. It stores all per service 45 * data required for the service management, provides API for starting/stopping the 46 * service and is responsible for adding/removing the service in the data structures 47 * for service management. The class also exposes configuration interface that is 48 * passed to the service it represents as soon it is bound. It also serves as the 49 * connection for the service. 50 */ 51 class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection { 52 private static final String LOG_TAG = "AccessibilityServiceConnection"; 53 /* 54 Holding a weak reference so there isn't a loop of references. UserState keeps lists of bound 55 and binding services. These are freed on user changes, but just in case it somehow gets lost 56 the weak reference will let the memory get GCed. 57 58 Having the reference be null when being called is a very bad sign, but we check the condition. 59 */ 60 final WeakReference<UserState> mUserStateWeakReference; 61 final Intent mIntent; 62 final ActivityTaskManagerInternal mActivityTaskManagerService; 63 64 private final Handler mMainHandler; 65 66 private boolean mWasConnectedAndDied; 67 68 AccessibilityServiceConnection(UserState userState, Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, GlobalActionPerformer globalActionPerfomer, ActivityTaskManagerInternal activityTaskManagerService)69 public AccessibilityServiceConnection(UserState userState, Context context, 70 ComponentName componentName, 71 AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, 72 Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport, 73 WindowManagerInternal windowManagerInternal, 74 GlobalActionPerformer globalActionPerfomer, 75 ActivityTaskManagerInternal activityTaskManagerService) { 76 super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock, 77 securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer); 78 mUserStateWeakReference = new WeakReference<UserState>(userState); 79 mIntent = new Intent().setComponent(mComponentName); 80 mMainHandler = mainHandler; 81 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, 82 com.android.internal.R.string.accessibility_binding_label); 83 mActivityTaskManagerService = activityTaskManagerService; 84 final long identity = Binder.clearCallingIdentity(); 85 try { 86 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, mSystemSupport.getPendingIntentActivity( 87 mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); 88 } finally { 89 Binder.restoreCallingIdentity(identity); 90 } 91 } 92 bindLocked()93 public void bindLocked() { 94 UserState userState = mUserStateWeakReference.get(); 95 if (userState == null) return; 96 final long identity = Binder.clearCallingIdentity(); 97 try { 98 int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE 99 | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS; 100 if (userState.getBindInstantServiceAllowed()) { 101 flags |= Context.BIND_ALLOW_INSTANT; 102 } 103 if (mService == null && mContext.bindServiceAsUser( 104 mIntent, this, flags, new UserHandle(userState.mUserId))) { 105 userState.getBindingServicesLocked().add(mComponentName); 106 } 107 } finally { 108 Binder.restoreCallingIdentity(identity); 109 } 110 mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), 111 mAccessibilityServiceInfo.getResolveInfo().serviceInfo.applicationInfo.uid, 112 userState.mUserId); 113 } 114 unbindLocked()115 public void unbindLocked() { 116 mContext.unbindService(this); 117 UserState userState = mUserStateWeakReference.get(); 118 if (userState == null) return; 119 userState.removeServiceLocked(this); 120 mSystemSupport.getMagnificationController().resetAllIfNeeded(mId); 121 // Set uid to -1 to clear allowing app switches. 122 mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), 123 /* uid= */ -1, userState.mUserId); 124 resetLocked(); 125 } 126 canRetrieveInteractiveWindowsLocked()127 public boolean canRetrieveInteractiveWindowsLocked() { 128 return mSecurityPolicy.canRetrieveWindowContentLocked(this) && mRetrieveInteractiveWindows; 129 } 130 131 @Override disableSelf()132 public void disableSelf() { 133 synchronized (mLock) { 134 UserState userState = mUserStateWeakReference.get(); 135 if (userState == null) return; 136 if (userState.getEnabledServicesLocked().remove(mComponentName)) { 137 final long identity = Binder.clearCallingIdentity(); 138 try { 139 mSystemSupport.persistComponentNamesToSettingLocked( 140 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, 141 userState.getEnabledServicesLocked(), userState.mUserId); 142 } finally { 143 Binder.restoreCallingIdentity(identity); 144 } 145 mSystemSupport.onClientChangeLocked(false); 146 } 147 } 148 } 149 150 @Override onServiceConnected(ComponentName componentName, IBinder service)151 public void onServiceConnected(ComponentName componentName, IBinder service) { 152 synchronized (mLock) { 153 if (mService != service) { 154 if (mService != null) { 155 mService.unlinkToDeath(this, 0); 156 } 157 mService = service; 158 try { 159 mService.linkToDeath(this, 0); 160 } catch (RemoteException re) { 161 Slog.e(LOG_TAG, "Failed registering death link"); 162 binderDied(); 163 return; 164 } 165 } 166 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); 167 UserState userState = mUserStateWeakReference.get(); 168 if (userState == null) return; 169 userState.addServiceLocked(this); 170 mSystemSupport.onClientChangeLocked(false); 171 // Initialize the service on the main handler after we're done setting up for 172 // the new configuration (for example, initializing the input filter). 173 mMainHandler.sendMessage(obtainMessage( 174 AccessibilityServiceConnection::initializeService, this)); 175 } 176 } 177 178 @Override getServiceInfo()179 public AccessibilityServiceInfo getServiceInfo() { 180 // Update crashed data 181 mAccessibilityServiceInfo.crashed = mWasConnectedAndDied; 182 return mAccessibilityServiceInfo; 183 } 184 initializeService()185 private void initializeService() { 186 IAccessibilityServiceClient serviceInterface = null; 187 synchronized (mLock) { 188 UserState userState = mUserStateWeakReference.get(); 189 if (userState == null) return; 190 Set<ComponentName> bindingServices = userState.getBindingServicesLocked(); 191 if (bindingServices.contains(mComponentName) || mWasConnectedAndDied) { 192 bindingServices.remove(mComponentName); 193 mWasConnectedAndDied = false; 194 serviceInterface = mServiceInterface; 195 } 196 // There's a chance that service is removed from enabled_accessibility_services setting 197 // key, but skip unbinding because of it's in binding state. Unbinds it if it's 198 // not in enabled service list. 199 if (serviceInterface != null 200 && !userState.getEnabledServicesLocked().contains(mComponentName)) { 201 mSystemSupport.onClientChangeLocked(false); 202 return; 203 } 204 } 205 if (serviceInterface == null) { 206 binderDied(); 207 return; 208 } 209 try { 210 serviceInterface.init(this, mId, mOverlayWindowToken); 211 } catch (RemoteException re) { 212 Slog.w(LOG_TAG, "Error while setting connection for service: " 213 + serviceInterface, re); 214 binderDied(); 215 } 216 } 217 218 @Override onServiceDisconnected(ComponentName componentName)219 public void onServiceDisconnected(ComponentName componentName) { 220 binderDied(); 221 UserState userState = mUserStateWeakReference.get(); 222 if (userState != null) { 223 // Set uid to -1 to clear allowing app switches. 224 mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), 225 /* uid= */ -1, userState.mUserId); 226 } 227 } 228 229 @Override isCalledForCurrentUserLocked()230 protected boolean isCalledForCurrentUserLocked() { 231 // We treat calls from a profile as if made by its parent as profiles 232 // share the accessibility state of the parent. The call below 233 // performs the current profile parent resolution. 234 final int resolvedUserId = mSecurityPolicy 235 .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT); 236 return resolvedUserId == mSystemSupport.getCurrentUserIdLocked(); 237 } 238 239 @Override setSoftKeyboardShowMode(int showMode)240 public boolean setSoftKeyboardShowMode(int showMode) { 241 synchronized (mLock) { 242 if (!isCalledForCurrentUserLocked()) { 243 return false; 244 } 245 final UserState userState = mUserStateWeakReference.get(); 246 if (userState == null) return false; 247 return userState.setSoftKeyboardModeLocked(showMode, mComponentName); 248 } 249 } 250 251 @Override getSoftKeyboardShowMode()252 public int getSoftKeyboardShowMode() { 253 final UserState userState = mUserStateWeakReference.get(); 254 return (userState != null) ? userState.getSoftKeyboardShowMode() : 0; 255 } 256 257 258 @Override isAccessibilityButtonAvailable()259 public boolean isAccessibilityButtonAvailable() { 260 synchronized (mLock) { 261 if (!isCalledForCurrentUserLocked()) { 262 return false; 263 } 264 UserState userState = mUserStateWeakReference.get(); 265 return (userState != null) && isAccessibilityButtonAvailableLocked(userState); 266 } 267 } 268 binderDied()269 public void binderDied() { 270 synchronized (mLock) { 271 // It is possible that this service's package was force stopped during 272 // whose handling the death recipient is unlinked and still get a call 273 // on binderDied since the call was made before we unlink but was 274 // waiting on the lock we held during the force stop handling. 275 if (!isConnectedLocked()) { 276 return; 277 } 278 mWasConnectedAndDied = true; 279 UserState userState = mUserStateWeakReference.get(); 280 if (userState != null) { 281 userState.serviceDisconnectedLocked(this); 282 } 283 resetLocked(); 284 mSystemSupport.getMagnificationController().resetAllIfNeeded(mId); 285 mSystemSupport.onClientChangeLocked(false); 286 } 287 } 288 isAccessibilityButtonAvailableLocked(UserState userState)289 public boolean isAccessibilityButtonAvailableLocked(UserState userState) { 290 // If the service does not request the accessibility button, it isn't available 291 if (!mRequestAccessibilityButton) { 292 return false; 293 } 294 295 // If the accessibility button isn't currently shown, it cannot be available to services 296 if (!mSystemSupport.isAccessibilityButtonShown()) { 297 return false; 298 } 299 300 // If magnification is on and assigned to the accessibility button, services cannot be 301 if (userState.mIsNavBarMagnificationEnabled 302 && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { 303 return false; 304 } 305 306 int requestingServices = 0; 307 for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { 308 final AccessibilityServiceConnection service = userState.mBoundServices.get(i); 309 if (service.mRequestAccessibilityButton) { 310 requestingServices++; 311 } 312 } 313 314 if (requestingServices == 1) { 315 // If only a single service is requesting, it must be this service, and the 316 // accessibility button is available to it 317 return true; 318 } else { 319 // With more than one active service, we derive the target from the user's settings 320 if (userState.mServiceAssignedToAccessibilityButton == null) { 321 // If the user has not made an assignment, we treat the button as available to 322 // all services until the user interacts with the button to make an assignment 323 return true; 324 } else { 325 // If an assignment was made, it defines availability 326 return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton); 327 } 328 } 329 } 330 331 @Override isCapturingFingerprintGestures()332 public boolean isCapturingFingerprintGestures() { 333 return (mServiceInterface != null) 334 && mSecurityPolicy.canCaptureFingerprintGestures(this) 335 && mCaptureFingerprintGestures; 336 } 337 338 @Override onFingerprintGestureDetectionActiveChanged(boolean active)339 public void onFingerprintGestureDetectionActiveChanged(boolean active) { 340 if (!isCapturingFingerprintGestures()) { 341 return; 342 } 343 IAccessibilityServiceClient serviceInterface; 344 synchronized (mLock) { 345 serviceInterface = mServiceInterface; 346 } 347 if (serviceInterface != null) { 348 try { 349 mServiceInterface.onFingerprintCapturingGesturesChanged(active); 350 } catch (RemoteException e) { 351 } 352 } 353 } 354 355 @Override onFingerprintGesture(int gesture)356 public void onFingerprintGesture(int gesture) { 357 if (!isCapturingFingerprintGestures()) { 358 return; 359 } 360 IAccessibilityServiceClient serviceInterface; 361 synchronized (mLock) { 362 serviceInterface = mServiceInterface; 363 } 364 if (serviceInterface != null) { 365 try { 366 mServiceInterface.onFingerprintGesture(gesture); 367 } catch (RemoteException e) { 368 } 369 } 370 } 371 372 @Override sendGesture(int sequence, ParceledListSlice gestureSteps)373 public void sendGesture(int sequence, ParceledListSlice gestureSteps) { 374 synchronized (mLock) { 375 if (mSecurityPolicy.canPerformGestures(this)) { 376 MotionEventInjector motionEventInjector = 377 mSystemSupport.getMotionEventInjectorLocked(); 378 if (motionEventInjector != null) { 379 motionEventInjector.injectEvents( 380 gestureSteps.getList(), mServiceInterface, sequence); 381 } else { 382 try { 383 mServiceInterface.onPerformGestureResult(sequence, false); 384 } catch (RemoteException re) { 385 Slog.e(LOG_TAG, "Error sending motion event injection failure to " 386 + mServiceInterface, re); 387 } 388 } 389 } 390 } 391 } 392 } 393