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