Improve handling of crashing a11y services.
We were confusing handling of services that were unbound with those that had crashed. We would lose track of services that has crashed, start new ones, and then when the system restarted a killed services we would have multiple instances running. It was possible for this to get very out of hand. Bug: 30306689 Change-Id: I4e63d25b6d2fec3ec68f450a4602898c43a2b2ad
This commit is contained in:
@@ -1111,9 +1111,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
|
|
||||||
private void addServiceLocked(Service service, UserState userState) {
|
private void addServiceLocked(Service service, UserState userState) {
|
||||||
try {
|
try {
|
||||||
|
if (!userState.mBoundServices.contains(service)) {
|
||||||
service.onAdded();
|
service.onAdded();
|
||||||
userState.mBoundServices.add(service);
|
userState.mBoundServices.add(service);
|
||||||
userState.mComponentNameToServiceMap.put(service.mComponentName, service);
|
userState.mComponentNameToServiceMap.put(service.mComponentName, service);
|
||||||
|
}
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
}
|
}
|
||||||
@@ -1126,8 +1128,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
*/
|
*/
|
||||||
private void removeServiceLocked(Service service, UserState userState) {
|
private void removeServiceLocked(Service service, UserState userState) {
|
||||||
userState.mBoundServices.remove(service);
|
userState.mBoundServices.remove(service);
|
||||||
userState.mComponentNameToServiceMap.remove(service.mComponentName);
|
|
||||||
service.onRemoved();
|
service.onRemoved();
|
||||||
|
// It may be possible to bind a service twice, which confuses the map. Rebuild the map
|
||||||
|
// to make sure we can still reach a service
|
||||||
|
userState.mComponentNameToServiceMap.clear();
|
||||||
|
for (int i = 0; i < userState.mBoundServices.size(); i++) {
|
||||||
|
Service boundService = userState.mBoundServices.get(i);
|
||||||
|
userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2324,15 +2332,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unbinds form the accessibility service and removes it from the data
|
* Unbinds from the accessibility service and removes it from the data
|
||||||
* structures for service management.
|
* structures for service management.
|
||||||
*
|
*
|
||||||
* @return True if unbinding is successful.
|
* @return True if unbinding is successful.
|
||||||
*/
|
*/
|
||||||
public boolean unbindLocked() {
|
public boolean unbindLocked() {
|
||||||
if (mService == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
UserState userState = getUserStateLocked(mUserId);
|
UserState userState = getUserStateLocked(mUserId);
|
||||||
getKeyEventDispatcher().flush(this);
|
getKeyEventDispatcher().flush(this);
|
||||||
if (!mIsAutomation) {
|
if (!mIsAutomation) {
|
||||||
@@ -3033,7 +3038,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName componentName) {
|
public void onServiceDisconnected(ComponentName componentName) {
|
||||||
/* do nothing - #binderDied takes care */
|
binderDied();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAdded() throws RemoteException {
|
public void onAdded() throws RemoteException {
|
||||||
@@ -3062,14 +3067,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void unlinkToOwnDeathLocked() {
|
public void unlinkToOwnDeathLocked() {
|
||||||
|
if (mService != null) {
|
||||||
mService.unlinkToDeath(this, 0);
|
mService.unlinkToDeath(this, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void resetLocked() {
|
public void resetLocked() {
|
||||||
try {
|
try {
|
||||||
// Clear the proxy in the other process so this
|
// Clear the proxy in the other process so this
|
||||||
// IAccessibilityServiceConnection can be garbage collected.
|
// IAccessibilityServiceConnection can be garbage collected.
|
||||||
|
if (mServiceInterface != null) {
|
||||||
mServiceInterface.init(null, mId, null);
|
mServiceInterface.init(null, mId, null);
|
||||||
|
}
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
@@ -3093,10 +3102,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
|||||||
mWasConnectedAndDied = true;
|
mWasConnectedAndDied = true;
|
||||||
getKeyEventDispatcher().flush(this);
|
getKeyEventDispatcher().flush(this);
|
||||||
UserState userState = getUserStateLocked(mUserId);
|
UserState userState = getUserStateLocked(mUserId);
|
||||||
// The death recipient is unregistered in removeServiceLocked
|
|
||||||
removeServiceLocked(this, userState);
|
|
||||||
resetLocked();
|
resetLocked();
|
||||||
if (mIsAutomation) {
|
if (mIsAutomation) {
|
||||||
|
// This is typically done when unbinding, but UiAutomation isn't bound.
|
||||||
|
removeServiceLocked(this, userState);
|
||||||
// We no longer have an automation service, so restore
|
// We no longer have an automation service, so restore
|
||||||
// the state based on values in the settings database.
|
// the state based on values in the settings database.
|
||||||
userState.mInstalledServices.remove(mAccessibilityServiceInfo);
|
userState.mInstalledServices.remove(mAccessibilityServiceInfo);
|
||||||
|
|||||||
Reference in New Issue
Block a user