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