summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server')
-rw-r--r--services/java/com/android/server/AppWidgetService.java59
-rw-r--r--services/java/com/android/server/AppWidgetServiceImpl.java10
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java32
-rw-r--r--services/java/com/android/server/IntentResolver.java27
-rw-r--r--services/java/com/android/server/LocationManagerService.java111
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java7
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java1332
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java15
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java18
-rwxr-xr-xservices/java/com/android/server/am/ActivityStack.java10
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java6
-rw-r--r--services/java/com/android/server/display/LocalDisplayAdapter.java19
-rw-r--r--services/java/com/android/server/display/WifiDisplayController.java2
-rw-r--r--services/java/com/android/server/location/LocationFudger.java20
-rw-r--r--services/java/com/android/server/location/PassiveProvider.java2
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java160
-rw-r--r--services/java/com/android/server/pm/Settings.java39
17 files changed, 1113 insertions, 756 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 385681e..9be7045 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
@@ -27,6 +28,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -193,31 +195,44 @@ class AppWidgetService extends IAppWidgetService.Stub
}, UserHandle.ALL, userFilter, null, null);
}
+ private int getCallingOrCurrentUserId() {
+ int callingUid = Binder.getCallingUid();
+ if (callingUid == android.os.Process.myUid()) {
+ try {
+ return ActivityManagerNative.getDefault().getCurrentUser().id;
+ } catch (RemoteException re) {
+ return UserHandle.getUserId(callingUid);
+ }
+ } else {
+ return UserHandle.getUserId(callingUid);
+ }
+ }
+
@Override
public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).allocateAppWidgetId(
+ return getImplForUser(getCallingOrCurrentUserId()).allocateAppWidgetId(
packageName, hostId);
}
@Override
public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).deleteAppWidgetId(appWidgetId);
+ getImplForUser(getCallingOrCurrentUserId()).deleteAppWidgetId(appWidgetId);
}
@Override
public void deleteHost(int hostId) throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).deleteHost(hostId);
+ getImplForUser(getCallingOrCurrentUserId()).deleteHost(hostId);
}
@Override
public void deleteAllHosts() throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).deleteAllHosts();
+ getImplForUser(getCallingOrCurrentUserId()).deleteAllHosts();
}
@Override
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetId(appWidgetId, provider,
+ getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetId(appWidgetId, provider,
options);
}
@@ -225,34 +240,34 @@ class AppWidgetService extends IAppWidgetService.Stub
public boolean bindAppWidgetIdIfAllowed(
String packageName, int appWidgetId, ComponentName provider, Bundle options)
throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetIdIfAllowed(
+ return getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetIdIfAllowed(
packageName, appWidgetId, provider, options);
}
@Override
public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).hasBindAppWidgetPermission(
+ return getImplForUser(getCallingOrCurrentUserId()).hasBindAppWidgetPermission(
packageName);
}
@Override
public void setBindAppWidgetPermission(String packageName, boolean permission)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).setBindAppWidgetPermission(
+ getImplForUser(getCallingOrCurrentUserId()).setBindAppWidgetPermission(
packageName, permission);
}
@Override
public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).bindRemoteViewsService(
+ getImplForUser(getCallingOrCurrentUserId()).bindRemoteViewsService(
appWidgetId, intent, connection);
}
@Override
public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
List<RemoteViews> updatedViews) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).startListening(host,
+ return getImplForUser(getCallingOrCurrentUserId()).startListening(host,
packageName, hostId, updatedViews);
}
@@ -287,27 +302,27 @@ class AppWidgetService extends IAppWidgetService.Stub
@Override
public int[] getAppWidgetIds(ComponentName provider) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetIds(provider);
+ return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIds(provider);
}
@Override
public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetInfo(appWidgetId);
+ return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetInfo(appWidgetId);
}
@Override
public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetViews(appWidgetId);
+ return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetViews(appWidgetId);
}
@Override
public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
- getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetOptions(appWidgetId, options);
+ getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetOptions(appWidgetId, options);
}
@Override
public Bundle getAppWidgetOptions(int appWidgetId) {
- return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetOptions(appWidgetId);
+ return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetOptions(appWidgetId);
}
static int[] getAppWidgetIds(Provider p) {
@@ -321,43 +336,43 @@ class AppWidgetService extends IAppWidgetService.Stub
@Override
public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
- return getImplForUser(UserHandle.getCallingUserId()).getInstalledProviders();
+ return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders();
}
@Override
public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).notifyAppWidgetViewDataChanged(
+ getImplForUser(getCallingOrCurrentUserId()).notifyAppWidgetViewDataChanged(
appWidgetIds, viewId);
}
@Override
public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).partiallyUpdateAppWidgetIds(
+ getImplForUser(getCallingOrCurrentUserId()).partiallyUpdateAppWidgetIds(
appWidgetIds, views);
}
@Override
public void stopListening(int hostId) throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).stopListening(hostId);
+ getImplForUser(getCallingOrCurrentUserId()).stopListening(hostId);
}
@Override
public void unbindRemoteViewsService(int appWidgetId, Intent intent) throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).unbindRemoteViewsService(
+ getImplForUser(getCallingOrCurrentUserId()).unbindRemoteViewsService(
appWidgetId, intent);
}
@Override
public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetIds(appWidgetIds, views);
+ getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetIds(appWidgetIds, views);
}
@Override
public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
throws RemoteException {
- getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetProvider(provider, views);
+ getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetProvider(provider, views);
}
@Override
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 815ee24..fcc8a06 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -1627,22 +1627,22 @@ class AppWidgetServiceImpl {
Integer.parseInt(minWidthString, 16));
}
String minHeightString = parser.getAttributeValue(null, "min_height");
- if (minWidthString != null) {
+ if (minHeightString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
Integer.parseInt(minHeightString, 16));
}
- String maxWidthString = parser.getAttributeValue(null, "max_height");
- if (minWidthString != null) {
+ String maxWidthString = parser.getAttributeValue(null, "max_width");
+ if (maxWidthString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
Integer.parseInt(maxWidthString, 16));
}
String maxHeightString = parser.getAttributeValue(null, "max_height");
- if (minWidthString != null) {
+ if (maxHeightString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
Integer.parseInt(maxHeightString, 16));
}
String categoryString = parser.getAttributeValue(null, "host_category");
- if (minWidthString != null) {
+ if (categoryString != null) {
options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
Integer.parseInt(categoryString, 16));
}
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index aec5d6e..83fa55b 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -212,8 +212,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
- static final int DEF_KEYGUARD_WIDGET_DISABLED = 0; // none
- int disableKeyguardWidgets = DEF_KEYGUARD_WIDGET_DISABLED;
+ static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+ int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
boolean encryptionRequested = false;
boolean disableCamera = false;
@@ -328,10 +328,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, "value", Boolean.toString(disableCamera));
out.endTag(null, "disable-camera");
}
- if (disableKeyguardWidgets != DEF_KEYGUARD_WIDGET_DISABLED) {
- out.startTag(null, "disable-keyguard-widgets");
- out.attribute(null, "value", Integer.toString(disableKeyguardWidgets));
- out.endTag(null, "disable-keyguard-widgets");
+ if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
+ out.startTag(null, "disable-keyguard-features");
+ out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures));
+ out.endTag(null, "disable-keyguard-features");
}
}
@@ -2300,18 +2300,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
- * Selectively disable keyguard widgets.
+ * Selectively disable keyguard features.
*/
- public void setKeyguardWidgetsDisabled(ComponentName who, int which, int userHandle) {
+ public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS);
- if ((ap.disableKeyguardWidgets & which) != which) {
- ap.disableKeyguardWidgets |= which;
+ DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+ if (ap.disabledKeyguardFeatures != which) {
+ ap.disabledKeyguardFeatures = which;
saveSettingsLocked(userHandle);
}
syncDeviceCapabilitiesLocked(getUserData(userHandle));
@@ -2319,24 +2319,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
- * Gets the disabled state for widgets in keyguard for the given admin,
+ * Gets the disabled state for features in keyguard for the given admin,
* or the aggregate of all active admins if who is null.
*/
- public int getKeyguardWidgetsDisabled(ComponentName who, int userHandle) {
+ public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
- return (admin != null) ? admin.disableKeyguardWidgets : 0;
+ return (admin != null) ? admin.disabledKeyguardFeatures : 0;
}
- // Determine whether or not keyguard widgets are disabled for any active admins.
+ // Determine which keyguard features are disabled for any active admins.
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
int which = 0;
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
- which |= admin.disableKeyguardWidgets;
+ which |= admin.disabledKeyguardFeatures;
}
return which;
}
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index d4769e8..9b19008 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -46,6 +46,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
final private static String TAG = "IntentResolver";
final private static boolean DEBUG = false;
final private static boolean localLOGV = DEBUG || false;
+ final private static boolean VALIDATE = false;
public void addFilter(F f) {
if (localLOGV) {
@@ -67,16 +68,20 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
mTypedActionToFilter, " TypedAction: ");
}
- mOldResolver.addFilter(f);
- verifyDataStructures(f);
+ if (VALIDATE) {
+ mOldResolver.addFilter(f);
+ verifyDataStructures(f);
+ }
}
public void removeFilter(F f) {
removeFilterInternal(f);
mFilters.remove(f);
- mOldResolver.removeFilter(f);
- verifyDataStructures(f);
+ if (VALIDATE) {
+ mOldResolver.removeFilter(f);
+ verifyDataStructures(f);
+ }
}
void removeFilterInternal(F f) {
@@ -314,12 +319,14 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
}
sortResults(finalList);
- List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId);
- if (oldList.size() != finalList.size()) {
- ValidationFailure here = new ValidationFailure();
- here.fillInStackTrace();
- Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size()
- + "; old implementation is " + oldList.size(), here);
+ if (VALIDATE) {
+ List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId);
+ if (oldList.size() != finalList.size()) {
+ ValidationFailure here = new ValidationFailure();
+ here.fillInStackTrace();
+ Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size()
+ + "; old implementation is " + oldList.size(), here);
+ }
}
if (debug) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 197f6ab..840d432 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -900,25 +900,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
return receiver;
}
+ private boolean isProviderAllowedByCoarsePermission(String provider) {
+ if (LocationManager.FUSED_PROVIDER.equals(provider)) {
+ return true;
+ }
+ if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+ return true;
+ }
+ if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
+ return true;
+ }
+ return false;
+ }
+
private String checkPermissionAndRequest(LocationRequest request) {
String perm = checkPermission();
if (ACCESS_COARSE_LOCATION.equals(perm)) {
- switch (request.getQuality()) {
- case LocationRequest.ACCURACY_FINE:
- request.setQuality(LocationRequest.ACCURACY_BLOCK);
- break;
- case LocationRequest.POWER_HIGH:
- request.setQuality(LocationRequest.POWER_LOW);
- break;
- }
- // throttle
- if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
- request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
- }
- if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
- request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
- }
+ if (!isProviderAllowedByCoarsePermission(request.getProvider())) {
+ throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
+ }
+ switch (request.getQuality()) {
+ case LocationRequest.ACCURACY_FINE:
+ request.setQuality(LocationRequest.ACCURACY_BLOCK);
+ break;
+ case LocationRequest.POWER_HIGH:
+ request.setQuality(LocationRequest.POWER_LOW);
+ break;
+ }
+ // throttle
+ if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ }
+ if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+ request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
+ }
}
// make getFastestInterval() the minimum of interval and fastest interval
if (request.getFastestInterval() > request.getInterval()) {
@@ -990,7 +1006,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// use the fused provider
if (request == null) request = DEFAULT_LOCATION_REQUEST;
String name = request.getProvider();
- if (name == null) name = LocationManager.FUSED_PROVIDER;
+ if (name == null) {
+ throw new IllegalArgumentException("provider name must not be null");
+ }
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) {
throw new IllegalArgumentException("provider doesn't exisit: " + provider);
@@ -1094,12 +1112,19 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (!isAllowedBySettingsLocked(name)) return null;
Location location = mLastLocation.get(name);
+ if (location == null) {
+ return null;
+ }
if (ACCESS_FINE_LOCATION.equals(perm)) {
return location;
} else {
- return mLocationFudger.getOrCreate(location);
+ Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ if (noGPSLocation != null) {
+ return mLocationFudger.getOrCreate(noGPSLocation);
+ }
}
}
+ return null;
}
@Override
@@ -1329,17 +1354,29 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) return;
- // Add the coarse location as an extra
- Location coarse = mLocationFudger.getOrCreate(location);
-
// Update last known locations
+ Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ Location lastNoGPSLocation = null;
Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) {
lastLocation = new Location(provider);
mLastLocation.put(provider, lastLocation);
+ } else {
+ lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+ if (noGPSLocation == null && lastNoGPSLocation != null) {
+ // New location has no no-GPS location: adopt last no-GPS location. This is set
+ // directly into location because we do not want to notify COARSE clients.
+ location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
+ }
}
lastLocation.set(location);
+ // Fetch coarse location
+ Location coarseLocation = null;
+ if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
+ coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
+ }
+
// Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime();
@@ -1361,29 +1398,31 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
continue;
}
+ Location notifyLocation = null;
if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
- location = lastLocation; // use fine location
+ notifyLocation = lastLocation; // use fine location
} else {
- location = coarse; // use coarse location
- }
-
- Location lastLoc = r.mLastFixBroadcast;
- if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
- if (lastLoc == null) {
- lastLoc = new Location(location);
- r.mLastFixBroadcast = lastLoc;
- } else {
- lastLoc.set(location);
- }
- if (!receiver.callLocationChangedLocked(location)) {
- Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
- receiverDead = true;
+ notifyLocation = coarseLocation; // use coarse location if available
+ }
+ if (notifyLocation != null) {
+ Location lastLoc = r.mLastFixBroadcast;
+ if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r)) {
+ if (lastLoc == null) {
+ lastLoc = new Location(notifyLocation);
+ r.mLastFixBroadcast = lastLoc;
+ } else {
+ lastLoc.set(notifyLocation);
+ }
+ if (!receiver.callLocationChangedLocked(notifyLocation)) {
+ Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
+ receiverDead = true;
+ }
}
}
long prevStatusUpdateTime = r.mLastStatusBroadcast;
if ((newStatusUpdateTime > prevStatusUpdateTime) &&
- (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
+ (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
r.mLastStatusBroadcast = newStatusUpdateTime;
if (!receiver.callStatusChangedLocked(provider, status, extras)) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 3caba1f..71e6e66 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -63,6 +63,7 @@ import android.util.Slog;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
import android.widget.Toast;
import com.android.internal.statusbar.StatusBarNotification;
@@ -877,7 +878,6 @@ public class NotificationManagerService extends INotificationManager.Stub
return (x < low) ? low : ((x > high) ? high : x);
}
-
// Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
// uid/pid of another application)
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
@@ -992,8 +992,9 @@ public class NotificationManagerService extends INotificationManager.Stub
}
if (notification.icon != 0) {
- StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
- r.uid, r.initialPid, score, notification);
+ final UserHandle user = new UserHandle(userId);
+ final StatusBarNotification n = new StatusBarNotification(
+ pkg, id, tag, r.uid, r.initialPid, score, notification, user);
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e7f3599..20c89ad 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -50,9 +50,12 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
@@ -76,6 +79,7 @@ import android.view.accessibility.IAccessibilityManagerClient;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBarService;
import org.xmlpull.v1.XmlPullParserException;
@@ -89,6 +93,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* This class is instantiated by the system as a system level service and can be
@@ -111,69 +116,62 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private static final int OWN_PROCESS_ID = android.os.Process.myPid();
- private static final int MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG = 1;
-
- private static final int MSG_TOGGLE_TOUCH_EXPLORATION = 2;
-
- private static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 3;
-
- private static final int MSG_SEND_UPDATE_INPUT_FILTER = 4;
-
private static int sIdCounter = 0;
private static int sNextWindowId;
- final Context mContext;
-
- final Object mLock = new Object();
-
- final List<Service> mServices = new ArrayList<Service>();
+ private final Context mContext;
- final List<IAccessibilityManagerClient> mClients =
- new ArrayList<IAccessibilityManagerClient>();
+ private final Object mLock = new Object();
- final Map<ComponentName, Service> mComponentNameToServiceMap = new HashMap<ComponentName, Service>();
+ private final SimpleStringSplitter mStringColonSplitter =
+ new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
- private final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<AccessibilityServiceInfo>();
+ private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
+ new ArrayList<AccessibilityServiceInfo>();
- private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+ private final PackageManager mPackageManager;
- private final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<ComponentName>();
+ private final IWindowManager mWindowManagerService;
- private final SparseArray<AccessibilityConnectionWrapper> mWindowIdToInteractionConnectionWrapperMap =
- new SparseArray<AccessibilityConnectionWrapper>();
-
- private final SparseArray<IBinder> mWindowIdToWindowTokenMap = new SparseArray<IBinder>();
+ private final SecurityPolicy mSecurityPolicy;
- private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
+ private final MainHandler mMainHandler;
- private PackageManager mPackageManager;
+ private Service mUiAutomationService;
- private int mHandledFeedbackTypes = 0;
+ private Service mQueryBridge;
- private boolean mIsAccessibilityEnabled;
+ private AlertDialog mEnableTouchExplorationDialog;
private AccessibilityInputFilter mInputFilter;
private boolean mHasInputFilter;
- private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
-
- private boolean mIsTouchExplorationEnabled;
+ private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
+ new RemoteCallbackList<IAccessibilityManagerClient>();
- private boolean mIsScreenMagnificationEnabled;
+ private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
+ new SparseArray<AccessibilityConnectionWrapper>();
- private final IWindowManager mWindowManager;
+ private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<IBinder>();
- private final SecurityPolicy mSecurityPolicy;
-
- private final MainHandler mMainHandler;
+ private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
- private Service mUiAutomationService;
+ private int mCurrentUserId = UserHandle.USER_NULL;
- private Service mQueryBridge;
+ private UserState getCurrentUserStateLocked() {
+ return getUserStateLocked(mCurrentUserId);
+ }
- private AlertDialog mEnableTouchExplorationDialog;
+ private UserState getUserStateLocked(int userId) {
+ UserState state = mUserStates.get(userId);
+ if (state == null) {
+ state = new UserState(userId);
+ mUserStates.put(userId, state);
+ }
+ return state;
+ }
/**
* Creates a new instance.
@@ -183,28 +181,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public AccessibilityManagerService(Context context) {
mContext = context;
mPackageManager = mContext.getPackageManager();
- mWindowManager = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
+ mWindowManagerService = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
mSecurityPolicy = new SecurityPolicy();
mMainHandler = new MainHandler(mContext.getMainLooper());
- registerPackageChangeAndBootCompletedBroadcastReceiver();
- registerSettingsContentObservers();
+ registerBroadcastReceivers();
+ new AccessibilityContentObserver(mMainHandler).register(
+ context.getContentResolver());
}
- /**
- * Registers a {@link BroadcastReceiver} for the events of
- * adding/changing/removing/restarting a package and boot completion.
- */
- private void registerPackageChangeAndBootCompletedBroadcastReceiver() {
- Context context = mContext;
-
+ private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
@Override
public void onSomePackagesChanged() {
synchronized (mLock) {
+ if (getChangingUserId() != mCurrentUserId) {
+ return;
+ }
// We will update when the automation service dies.
if (mUiAutomationService == null) {
- populateInstalledAccessibilityServiceLocked();
- manageServicesLocked();
+ UserState userState = getCurrentUserStateLocked();
+ populateInstalledAccessibilityServiceLocked(userState);
+ manageServicesLocked(userState);
}
}
}
@@ -212,7 +209,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public void onPackageRemoved(String packageName, int uid) {
synchronized (mLock) {
- Iterator<ComponentName> it = mEnabledServices.iterator();
+ final int userId = getChangingUserId();
+ if (userId != mCurrentUserId) {
+ return;
+ }
+ UserState state = getUserStateLocked(userId);
+ Iterator<ComponentName> it = state.mEnabledServices.iterator();
while (it.hasNext()) {
ComponentName comp = it.next();
String compPkg = comp.getPackageName();
@@ -221,13 +223,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// Update the enabled services setting.
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- mEnabledServices);
+ state.mEnabledServices, userId);
// Update the touch exploration granted services setting.
- mTouchExplorationGrantedServices.remove(comp);
+ state.mTouchExplorationGrantedServices.remove(comp);
persistComponentNamesToSettingLocked(
Settings.Secure.
TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- mEnabledServices);
+ state.mEnabledServices, userId);
return;
}
}
@@ -238,7 +240,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public boolean onHandleForceStop(Intent intent, String[] packages,
int uid, boolean doit) {
synchronized (mLock) {
- Iterator<ComponentName> it = mEnabledServices.iterator();
+ final int userId = getChangingUserId();
+ if (userId != mCurrentUserId) {
+ return false;
+ }
+ UserState state = getUserStateLocked(userId);
+ Iterator<ComponentName> it = state.mEnabledServices.iterator();
while (it.hasNext()) {
ComponentName comp = it.next();
String compPkg = comp.getPackageName();
@@ -250,179 +257,97 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
it.remove();
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- mEnabledServices);
+ state.mEnabledServices, userId);
}
}
}
return false;
}
}
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- updateInternalStateLocked();
- }
- }
- return;
- }
- super.onReceive(context, intent);
- }
};
// package changes
- monitor.register(context, null, true);
+ monitor.register(mContext, null, UserHandle.ALL, true);
- // boot completed
- IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- mContext.registerReceiver(monitor, bootFiler, null, monitor.getRegisteredHandler());
- }
-
- /**
- * {@link ContentObserver}s for {@link Settings.Secure#ACCESSIBILITY_ENABLED}
- * and {@link Settings.Secure#ENABLED_ACCESSIBILITY_SERVICES} settings.
- */
- private void registerSettingsContentObservers() {
- ContentResolver contentResolver = mContext.getContentResolver();
-
- Uri accessibilityEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_ENABLED);
- contentResolver.registerContentObserver(accessibilityEnabledUri, false,
- new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- handleAccessibilityEnabledSettingChangedLocked();
- updateInputFilterLocked();
- sendStateToClientsLocked();
- }
- }
- }
- });
+ // user change
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
- Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
- Settings.Secure.TOUCH_EXPLORATION_ENABLED);
- contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
- new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- handleTouchExplorationEnabledSettingChangedLocked();
- updateInputFilterLocked();
- sendStateToClientsLocked();
- }
- }
- }
- });
-
- Uri accessibilityScreenMagnificationEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
- contentResolver.registerContentObserver(accessibilityScreenMagnificationEnabledUri, false,
- new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- handleScreenMagnificationEnabledSettingChangedLocked();
- updateInputFilterLocked();
- sendStateToClientsLocked();
- }
- }
- }
- });
-
- Uri accessibilityServicesUri =
- Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
- contentResolver.registerContentObserver(accessibilityServicesUri, false,
- new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- populateEnabledAccessibilityServicesLocked();
- manageServicesLocked();
- }
- }
- }
- });
-
- Uri touchExplorationGrantedServicesUri = Settings.Secure.getUriFor(
- Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
- contentResolver.registerContentObserver(touchExplorationGrantedServicesUri, false,
- new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- populateTouchExplorationGrantedAccessibilityServicesLocked();
- handleTouchExplorationGrantedAccessibilityServicesChangedLocked();
- }
- }
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
}
- });
+ }
+ }, userFilter);
}
- public int addClient(IAccessibilityManagerClient client) throws RemoteException {
+ public int addClient(IAccessibilityManagerClient client, int userId) {
synchronized (mLock) {
- final IAccessibilityManagerClient addedClient = client;
- mClients.add(addedClient);
- // Clients are registered all the time until their process is
- // killed, therefore we do not have a corresponding unlinkToDeath.
- client.asBinder().linkToDeath(new DeathRecipient() {
- public void binderDied() {
- synchronized (mLock) {
- addedClient.asBinder().unlinkToDeath(this, 0);
- mClients.remove(addedClient);
- }
- }
- }, 0);
- return getState();
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ // If the client is from a process that runs across users such as
+ // the system UI or the system we add it to the global state that
+ // is shared across users.
+ UserState userState = getUserStateLocked(resolvedUserId);
+ if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
+ mGlobalClients.register(client);
+ return getClientState(userState);
+ } else {
+ userState.mClients.register(client);
+ // If this client is not for the current user we do not
+ // return a state since it is not for the foreground user.
+ // We will send the state to the client on a user switch.
+ return (resolvedUserId == mCurrentUserId) ? getClientState(userState) : 0;
+ }
}
}
- public boolean sendAccessibilityEvent(AccessibilityEvent event) {
+ public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ // This method does nothing for a background user.
+ if (resolvedUserId != mCurrentUserId) {
+ return true; // yes, recycle the event
+ }
if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
mSecurityPolicy.updateActiveWindowAndEventSourceLocked(event);
notifyAccessibilityServicesDelayedLocked(event, false);
notifyAccessibilityServicesDelayedLocked(event, true);
}
if (mHasInputFilter && mInputFilter != null) {
- mMainHandler.obtainMessage(MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
+ mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
AccessibilityEvent.obtain(event)).sendToTarget();
}
event.recycle();
- mHandledFeedbackTypes = 0;
+ getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
}
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
- public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+ public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
synchronized (mLock) {
- return mInstalledServices;
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ return getUserStateLocked(resolvedUserId).mInstalledServices;
}
}
- public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
- List<AccessibilityServiceInfo> result = mEnabledServicesForFeedbackTempList;
- result.clear();
- List<Service> services = mServices;
+ public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
+ int userId) {
+ List<AccessibilityServiceInfo> result = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ result = mEnabledServicesForFeedbackTempList;
+ result.clear();
+ List<Service> services = getUserStateLocked(resolvedUserId).mServices;
while (feedbackType != 0) {
final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
feedbackType &= ~feedbackTypeBit;
@@ -438,30 +363,51 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return result;
}
- public void interrupt() {
+ public void interrupt(int userId) {
+ CopyOnWriteArrayList<Service> services;
synchronized (mLock) {
- for (int i = 0, count = mServices.size(); i < count; i++) {
- Service service = mServices.get(i);
- try {
- service.mServiceInterface.onInterrupt();
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error during sending interrupt request to "
- + service.mService, re);
- }
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ // This method does nothing for a background user.
+ if (resolvedUserId != mCurrentUserId) {
+ return;
+ }
+ services = getUserStateLocked(resolvedUserId).mServices;
+ }
+ for (int i = 0, count = services.size(); i < count; i++) {
+ Service service = services.get(i);
+ try {
+ service.mServiceInterface.onInterrupt();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error during sending interrupt request to "
+ + service.mService, re);
}
}
}
public int addAccessibilityInteractionConnection(IWindow windowToken,
- IAccessibilityInteractionConnection connection) throws RemoteException {
+ IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
synchronized (mLock) {
- final IWindow addedWindowToken = windowToken;
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
final int windowId = sNextWindowId++;
- AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(windowId,
- connection);
- wrapper.linkToDeath();
- mWindowIdToWindowTokenMap.put(windowId, addedWindowToken.asBinder());
- mWindowIdToInteractionConnectionWrapperMap.put(windowId, wrapper);
+ // If the window is from a process that runs across users such as
+ // the system UI or the system we add it to the global state that
+ // is shared across users.
+ if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
+ AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+ windowId, connection, UserHandle.USER_ALL);
+ wrapper.linkToDeath();
+ mGlobalInteractionConnections.put(windowId, wrapper);
+ mGlobalWindowTokens.put(windowId, windowToken.asBinder());
+ } else {
+ AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+ windowId, connection, resolvedUserId);
+ wrapper.linkToDeath();
+ UserState userState = getUserStateLocked(resolvedUserId);
+ userState.mInteractionConnections.put(windowId, wrapper);
+ userState.mWindowTokens.put(windowId, windowToken.asBinder());
+ }
if (DEBUG) {
Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
}
@@ -469,22 +415,47 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
- public void removeAccessibilityInteractionConnection(IWindow windowToken) {
+ public void removeAccessibilityInteractionConnection(IWindow window) {
synchronized (mLock) {
- final int count = mWindowIdToWindowTokenMap.size();
- for (int i = 0; i < count; i++) {
- if (mWindowIdToWindowTokenMap.valueAt(i) == windowToken.asBinder()) {
- final int windowId = mWindowIdToWindowTokenMap.keyAt(i);
- AccessibilityConnectionWrapper wrapper =
- mWindowIdToInteractionConnectionWrapperMap.get(windowId);
- wrapper.unlinkToDeath();
- removeAccessibilityInteractionConnectionLocked(windowId);
+ mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ IBinder token = window.asBinder();
+ final boolean removedGlobal =
+ removeAccessibilityInteractionConnectionInternalLocked(
+ token, mGlobalWindowTokens, mGlobalInteractionConnections);
+ if (removedGlobal) {
+ return;
+ }
+ final int userCount = mUserStates.size();
+ for (int i = 0; i < userCount; i++) {
+ UserState userState = mUserStates.valueAt(i);
+ final boolean removedForUser =
+ removeAccessibilityInteractionConnectionInternalLocked(
+ token, userState.mWindowTokens, userState.mInteractionConnections);
+ if (removedForUser) {
return;
}
}
}
}
+ private boolean removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
+ SparseArray<IBinder> windowTokens,
+ SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
+ final int count = windowTokens.size();
+ for (int i = 0; i < count; i++) {
+ if (windowTokens.valueAt(i) == windowToken) {
+ final int windowId = windowTokens.keyAt(i);
+ windowTokens.removeAt(i);
+ AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
+ wrapper.unlinkToDeath();
+ interactionConnections.remove(windowId);
+ return true;
+ }
+ }
+ return false;
+ }
+
public void registerUiTestAutomationService(IAccessibilityServiceClient serviceClient,
AccessibilityServiceInfo accessibilityServiceInfo) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
@@ -495,21 +466,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// If an automation services is connected to the system all services are stopped
// so the automation one is the only one running. Settings are not changed so when
// the automation service goes away the state is restored from the settings.
+ UserState userState = getCurrentUserStateLocked();
+ unbindAllServicesLocked(userState);
- // Disable all services.
- final int runningServiceCount = mServices.size();
- for (int i = 0; i < runningServiceCount; i++) {
- Service runningService = mServices.get(i);
- runningService.unbind();
- }
// If necessary enable accessibility and announce that.
- if (!mIsAccessibilityEnabled) {
- mIsAccessibilityEnabled = true;
- sendStateToClientsLocked();
+ if (!userState.mIsAccessibilityEnabled) {
+ userState.mIsAccessibilityEnabled = true;
+ scheduleSendStateToClientsLocked(userState);
}
}
// Hook the automation service up.
- mUiAutomationService = new Service(componentName, accessibilityServiceInfo, true);
+ mUiAutomationService = new Service(mCurrentUserId, componentName,
+ accessibilityServiceInfo, true);
mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
}
@@ -572,30 +540,80 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
* @param outBounds The output to which to write the bounds.
*/
boolean getActiveWindowBounds(Rect outBounds) {
+ IBinder token;
synchronized (mLock) {
final int windowId = mSecurityPolicy.mActiveWindowId;
- IBinder token = mWindowIdToWindowTokenMap.get(windowId);
- try {
- WindowInfo info = mWindowManager.getWindowInfo(token);
- if (info != null) {
- outBounds.set(info.frame);
- return true;
- }
- } catch (RemoteException re) {
- /* ignore */
+ token = mGlobalWindowTokens.get(windowId);
+ if (token == null) {
+ token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ }
+ }
+ WindowInfo info = null;
+ try {
+ info = mWindowManagerService.getWindowInfo(token);
+ if (info != null) {
+ outBounds.set(info.frame);
+ return true;
+ }
+ } catch (RemoteException re) {
+ /* ignore */
+ } finally {
+ if (info != null) {
+ info.recycle();
}
- return false;
}
+ return false;
}
- public int getActiveWindowId() {
+ int getActiveWindowId() {
return mSecurityPolicy.mActiveWindowId;
}
+ private void switchUser(int userId) {
+ synchronized (mLock) {
+ if (userId == mCurrentUserId) {
+ return;
+ }
+
+ // Disconnect from services for the old user.
+ UserState oldUserState = getUserStateLocked(mCurrentUserId);
+ unbindAllServicesLocked(oldUserState);
+
+ // Disable the local managers for the old user.
+ if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
+ mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
+ oldUserState.mUserId, 0).sendToTarget();
+ }
+
+ // The user changed.
+ mCurrentUserId = userId;
+
+ // Recreate the internal state for the new user.
+ mMainHandler.obtainMessage(MainHandler.MSG_SEND_RECREATE_INTERNAL_STATE,
+ mCurrentUserId, 0).sendToTarget();
+
+ // Re-register the test automation service after the new state is recreated.
+ if (mUiAutomationService != null) {
+ unregisterUiTestAutomationService(mUiAutomationService.mServiceInterface);
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = mUiAutomationService.mServiceInterface;
+ args.arg2 = mUiAutomationService.mAccessibilityServiceInfo;
+ mMainHandler.obtainMessage(MainHandler.MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE,
+ args).sendToTarget();
+ }
+ }
+ }
+
+ private void removeUser(int userId) {
+ synchronized (mLock) {
+ mUserStates.remove(userId);
+ }
+ }
+
private Service getQueryBridge() {
if (mQueryBridge == null) {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
- mQueryBridge = new Service(null, info, true);
+ mQueryBridge = new Service(UserHandle.USER_NULL, null, info, true);
}
return mQueryBridge;
}
@@ -610,8 +628,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// gestures to avoid user frustration when different
// behavior is observed from different combinations of
// enabled accessibility services.
- for (int i = mServices.size() - 1; i >= 0; i--) {
- Service service = mServices.get(i);
+ UserState state = getCurrentUserStateLocked();
+ for (int i = state.mServices.size() - 1; i >= 0; i--) {
+ Service service = state.mServices.get(i);
if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
service.notifyGesture(gestureId);
return true;
@@ -624,29 +643,36 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
* Removes an AccessibilityInteractionConnection.
*
* @param windowId The id of the window to which the connection is targeted.
+ * @param userId The id of the user owning the connection. UserHandle.USER_ALL
+ * if global.
*/
- private void removeAccessibilityInteractionConnectionLocked(int windowId) {
- mWindowIdToWindowTokenMap.remove(windowId);
- mWindowIdToInteractionConnectionWrapperMap.remove(windowId);
+ private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ mGlobalWindowTokens.remove(windowId);
+ mGlobalInteractionConnections.remove(windowId);
+ } else {
+ UserState userState = getCurrentUserStateLocked();
+ userState.mWindowTokens.remove(windowId);
+ userState.mInteractionConnections.remove(windowId);
+ }
if (DEBUG) {
Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
}
}
- /**
- * Populates the cached list of installed {@link AccessibilityService}s.
- */
- private void populateInstalledAccessibilityServiceLocked() {
- mInstalledServices.clear();
+ private void populateInstalledAccessibilityServiceLocked(UserState userState) {
+ userState.mInstalledServices.clear();
- List<ResolveInfo> installedServices = mPackageManager.queryIntentServices(
+ List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
new Intent(AccessibilityService.SERVICE_INTERFACE),
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ mCurrentUserId);
for (int i = 0, count = installedServices.size(); i < count; i++) {
ResolveInfo resolveInfo = installedServices.get(i);
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(serviceInfo.permission)) {
+ if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
+ serviceInfo.permission)) {
Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
serviceInfo.packageName, serviceInfo.name).flattenToShortString()
+ ": it does not require the permission "
@@ -656,7 +682,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityServiceInfo accessibilityServiceInfo;
try {
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
- mInstalledServices.add(accessibilityServiceInfo);
+ userState.mInstalledServices.add(accessibilityServiceInfo);
} catch (XmlPullParserException xppe) {
Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
} catch (IOException ioe) {
@@ -665,16 +691,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
- private void populateEnabledAccessibilityServicesLocked() {
+ private void populateEnabledAccessibilityServicesLocked(UserState userState) {
populateComponentNamesFromSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- mEnabledServices);
+ userState.mUserId,
+ userState.mEnabledServices);
}
- private void populateTouchExplorationGrantedAccessibilityServicesLocked() {
+ private void populateTouchExplorationGrantedAccessibilityServicesLocked(
+ UserState userState) {
populateComponentNamesFromSettingLocked(
Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- mTouchExplorationGrantedServices);
+ userState.mUserId,
+ userState.mTouchExplorationGrantedServices);
}
/**
@@ -687,12 +716,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
boolean isDefault) {
try {
- for (int i = 0, count = mServices.size(); i < count; i++) {
- Service service = mServices.get(i);
+ UserState state = getCurrentUserStateLocked();
+ for (int i = 0, count = state.mServices.size(); i < count; i++) {
+ Service service = state.mServices.get(i);
if (service.mIsDefault == isDefault) {
- if (canDispathEventLocked(service, event, mHandledFeedbackTypes)) {
- mHandledFeedbackTypes |= service.mFeedbackType;
+ if (canDispathEventLocked(service, event, state.mHandledFeedbackTypes)) {
+ state.mHandledFeedbackTypes |= service.mFeedbackType;
service.notifyAccessibilityEvent(event);
}
}
@@ -706,19 +736,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
/**
- * Adds a service.
+ * Adds a service for a user.
*
* @param service The service to add.
+ * @param userId The user id.
*/
- private void tryAddServiceLocked(Service service) {
+ private void tryAddServiceLocked(Service service, int userId) {
try {
- if (mServices.contains(service) || !service.isConfigured()) {
+ UserState userState = getUserStateLocked(userId);
+ if (userState.mServices.contains(service) || !service.isConfigured()) {
return;
}
service.linkToOwnDeath();
- mServices.add(service);
- mComponentNameToServiceMap.put(service.mComponentName, service);
- updateInputFilterLocked();
+ userState.mServices.add(service);
+ userState.mComponentNameToServiceMap.put(service.mComponentName, service);
+ updateInputFilterLocked(userState);
tryEnableTouchExplorationLocked(service);
} catch (RemoteException e) {
/* do nothing */
@@ -732,14 +764,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
* @return True if the service was removed, false otherwise.
*/
private boolean tryRemoveServiceLocked(Service service) {
- final boolean removed = mServices.remove(service);
+ UserState userState = getUserStateLocked(service.mUserId);
+ final boolean removed = userState.mServices.remove(service);
if (!removed) {
return false;
}
- mComponentNameToServiceMap.remove(service.mComponentName);
+ userState.mComponentNameToServiceMap.remove(service.mComponentName);
service.unlinkToOwnDeath();
service.dispose();
- updateInputFilterLocked();
+ updateInputFilterLocked(userState);
tryDisableTouchExplorationLocked(service);
return removed;
}
@@ -791,23 +824,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
/**
* Manages services by starting enabled ones and stopping disabled ones.
*/
- private void manageServicesLocked() {
- final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices,
- mEnabledServices);
+ private void manageServicesLocked(UserState userState) {
+ final int enabledInstalledServicesCount = updateServicesStateLocked(userState);
// No enabled installed services => disable accessibility to avoid
// sending accessibility events with no recipient across processes.
- if (mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0);
+ if (userState.mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
}
}
/**
- * Unbinds all bound services.
+ * Unbinds all bound services for a user.
+ *
+ * @param userState The user state.
*/
- private void unbindAllServicesLocked() {
- List<Service> services = mServices;
-
+ private void unbindAllServicesLocked(UserState userState) {
+ List<Service> services = userState.mServices;
for (int i = 0, count = services.size(); i < count; i++) {
Service service = services.get(i);
if (service.unbind()) {
@@ -819,17 +852,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
/**
* Populates a set with the {@link ComponentName}s stored in a colon
- * separated value setting.
+ * separated value setting for a given user.
*
* @param settingName The setting to parse.
+ * @param userId The user id.
* @param outComponentNames The output component names.
*/
- private void populateComponentNamesFromSettingLocked(String settingName,
+ private void populateComponentNamesFromSettingLocked(String settingName, int userId,
Set<ComponentName> outComponentNames) {
+ String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ settingName, userId);
outComponentNames.clear();
-
- String settingValue = Settings.Secure.getString(mContext.getContentResolver(), settingName);
-
if (settingValue != null) {
TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
splitter.setString(settingValue);
@@ -854,7 +887,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
* @param componentNames The component names.
*/
private void persistComponentNamesToSettingLocked(String settingName,
- Set<ComponentName> componentNames) {
+ Set<ComponentName> componentNames, int userId) {
StringBuilder builder = new StringBuilder();
for (ComponentName componentName : componentNames) {
if (builder.length() > 0) {
@@ -862,34 +895,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
builder.append(componentName.flattenToShortString());
}
- Settings.Secure.putString(mContext.getContentResolver(), settingName, builder.toString());
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ settingName, builder.toString(), userId);
}
/**
* Updates the state of each service by starting (or keeping running) enabled ones and
* stopping the rest.
*
- * @param installedServices All installed {@link AccessibilityService}s.
- * @param enabledServices The {@link ComponentName}s of the enabled services.
+ * @param userState The user state for which to do that.
* @return The number of enabled installed services.
*/
- private int updateServicesStateLocked(List<AccessibilityServiceInfo> installedServices,
- Set<ComponentName> enabledServices) {
-
- Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
- boolean isEnabled = mIsAccessibilityEnabled;
+ private int updateServicesStateLocked(UserState userState) {
+ Map<ComponentName, Service> componentNameToServiceMap =
+ userState.mComponentNameToServiceMap;
+ boolean isEnabled = userState.mIsAccessibilityEnabled;
int enabledInstalledServices = 0;
- for (int i = 0, count = installedServices.size(); i < count; i++) {
- AccessibilityServiceInfo installedService = installedServices.get(i);
+ for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
+ AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
ComponentName componentName = ComponentName.unflattenFromString(
installedService.getId());
Service service = componentNameToServiceMap.get(componentName);
if (isEnabled) {
- if (enabledServices.contains(componentName)) {
+ if (userState.mEnabledServices.contains(componentName)) {
if (service == null) {
- service = new Service(componentName, installedService, false);
+ service = new Service(userState.mUserId, componentName,
+ installedService, false);
}
service.bind();
enabledInstalledServices++;
@@ -908,145 +941,206 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return enabledInstalledServices;
}
- /**
- * Sends the state to the clients.
- */
- private void sendStateToClientsLocked() {
- final int state = getState();
- for (int i = 0, count = mClients.size(); i < count; i++) {
+ private void scheduleSendStateToClientsLocked(UserState userState) {
+ if (mGlobalClients.getRegisteredCallbackCount() > 0
+ || userState.mClients.getRegisteredCallbackCount() > 0) {
+ final int clientState = getClientState(userState);
+ mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
+ clientState, userState.mUserId) .sendToTarget();
+ }
+ }
+
+ private void updateInputFilterLocked(UserState userState) {
+ boolean setInputFilter = false;
+ AccessibilityInputFilter inputFilter = null;
+ synchronized (mLock) {
+ if ((userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled)
+ || userState.mIsDisplayMagnificationEnabled) {
+ if (!mHasInputFilter) {
+ mHasInputFilter = true;
+ if (mInputFilter == null) {
+ mInputFilter = new AccessibilityInputFilter(mContext,
+ AccessibilityManagerService.this);
+ }
+ inputFilter = mInputFilter;
+ setInputFilter = true;
+ }
+ int flags = 0;
+ if (userState.mIsDisplayMagnificationEnabled) {
+ flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
+ }
+ if (userState.mIsTouchExplorationEnabled) {
+ flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
+ }
+ mInputFilter.setEnabledFeatures(flags);
+ } else {
+ if (mHasInputFilter) {
+ mHasInputFilter = false;
+ mInputFilter.setEnabledFeatures(0);
+ inputFilter = null;
+ setInputFilter = true;
+ }
+ }
+ }
+ if (setInputFilter) {
try {
- mClients.get(i).setState(state);
+ mWindowManagerService.setInputFilter(inputFilter);
} catch (RemoteException re) {
- mClients.remove(i);
- count--;
- i--;
+ /* ignore */
}
}
}
- /**
- * Gets the current state as a set of flags.
- *
- * @return The state.
- */
- private int getState() {
- int state = 0;
- if (mIsAccessibilityEnabled) {
- state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
- }
- // Touch exploration relies on enabled accessibility.
- if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
- state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+ private void showEnableTouchExplorationDialog(final Service service) {
+ String label = service.mResolveInfo.loadLabel(
+ mContext.getPackageManager()).toString();
+ synchronized (mLock) {
+ final UserState state = getCurrentUserStateLocked();
+ if (state.mIsTouchExplorationEnabled) {
+ return;
+ }
+ if (mEnableTouchExplorationDialog != null
+ && mEnableTouchExplorationDialog.isShowing()) {
+ return;
+ }
+ mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // The user allowed the service to toggle touch exploration.
+ state.mTouchExplorationGrantedServices.add(service.mComponentName);
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ state.mTouchExplorationGrantedServices, state.mUserId);
+ // Enable touch exploration.
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
+ service.mUserId);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ })
+ .setTitle(R.string.enable_explore_by_touch_warning_title)
+ .setMessage(mContext.getString(
+ R.string.enable_explore_by_touch_warning_message, label))
+ .create();
+ mEnableTouchExplorationDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
+ mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
+ mEnableTouchExplorationDialog.show();
}
- return state;
}
- /**
- * Updates the state of the input filter.
- */
- private void updateInputFilterLocked() {
- mMainHandler.obtainMessage(MSG_SEND_UPDATE_INPUT_FILTER).sendToTarget();
+ private int getClientState(UserState userState) {
+ int clientState = 0;
+ if (userState.mIsAccessibilityEnabled) {
+ clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+ }
+ // Touch exploration relies on enabled accessibility.
+ if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+ clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+ }
+ return clientState;
}
- /**
- * Updated the internal state of this service to match the current settings.
- */
- private void updateInternalStateLocked() {
- populateInstalledAccessibilityServiceLocked();
- populateEnabledAccessibilityServicesLocked();
- populateTouchExplorationGrantedAccessibilityServicesLocked();
+ private void recreateInternalStateLocked(UserState userState) {
+ populateInstalledAccessibilityServiceLocked(userState);
+ populateEnabledAccessibilityServicesLocked(userState);
+ populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
- handleTouchExplorationEnabledSettingChangedLocked();
- handleScreenMagnificationEnabledSettingChangedLocked();
- handleAccessibilityEnabledSettingChangedLocked();
+ handleTouchExplorationEnabledSettingChangedLocked(userState);
+ handleDisplayMagnificationEnabledSettingChangedLocked(userState);
+ handleAccessibilityEnabledSettingChangedLocked(userState);
- updateInputFilterLocked();
- sendStateToClientsLocked();
+ updateInputFilterLocked(userState);
+ scheduleSendStateToClientsLocked(userState);
}
- /**
- * Updated the state based on the accessibility enabled setting.
- */
- private void handleAccessibilityEnabledSettingChangedLocked() {
- mIsAccessibilityEnabled = Settings.Secure.getInt(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
- if (mIsAccessibilityEnabled) {
- manageServicesLocked();
+ private void handleAccessibilityEnabledSettingChangedLocked(UserState userState) {
+ userState.mIsAccessibilityEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
+ if (userState.mIsAccessibilityEnabled ) {
+ manageServicesLocked(userState);
} else {
- unbindAllServicesLocked();
+ unbindAllServicesLocked(userState);
}
}
- /**
- * Updates the state based on the touch exploration enabled setting.
- */
- private void handleTouchExplorationEnabledSettingChangedLocked() {
- mIsTouchExplorationEnabled = Settings.Secure.getInt(
+ private void handleTouchExplorationEnabledSettingChangedLocked(UserState userState) {
+ userState.mIsTouchExplorationEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
}
- /**
- * Updates the state based on the screen magnification enabled setting.
- */
- private void handleScreenMagnificationEnabledSettingChangedLocked() {
- mIsScreenMagnificationEnabled = Settings.Secure.getInt(
+ private void handleDisplayMagnificationEnabledSettingChangedLocked(UserState userState) {
+ userState.mIsDisplayMagnificationEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+ 0, userState.mUserId) == 1;
}
- private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked() {
- final int serviceCount = mServices.size();
+ private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked(
+ UserState userState) {
+ final int serviceCount = userState.mServices.size();
for (int i = 0; i < serviceCount; i++) {
- Service service = mServices.get(i);
+ Service service = userState.mServices.get(i);
if (service.mRequestTouchExplorationMode
- && mTouchExplorationGrantedServices.contains(service.mComponentName)) {
+ && userState.mTouchExplorationGrantedServices.contains(
+ service.mComponentName)) {
tryEnableTouchExplorationLocked(service);
return;
}
}
- if (mIsTouchExplorationEnabled) {
- mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0,
- 0).sendToTarget();
+ if (userState.mIsTouchExplorationEnabled) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
}
private void tryEnableTouchExplorationLocked(final Service service) {
- if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
- final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains(
- service.mComponentName);
+ UserState userState = getUserStateLocked(service.mUserId);
+ if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
+ final boolean canToggleTouchExploration =
+ userState.mTouchExplorationGrantedServices.contains(service.mComponentName);
if (!service.mIsAutomation && !canToggleTouchExploration) {
- mMainHandler.obtainMessage(MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG,
- service).sendToTarget();
+ showEnableTouchExplorationDialog(service);
} else {
- mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 1, 0).sendToTarget();
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId);
}
}
}
private void tryDisableTouchExplorationLocked(Service service) {
- if (mIsTouchExplorationEnabled) {
- synchronized (mLock) {
- final int serviceCount = mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service other = mServices.get(i);
- if (other != service && other.mRequestTouchExplorationMode) {
- return;
- }
+ UserState userState = getUserStateLocked(service.mUserId);
+ if (userState.mIsTouchExplorationEnabled) {
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service other = userState.mServices.get(i);
+ if (other != service && other.mRequestTouchExplorationMode) {
+ return;
}
- mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0, 0).sendToTarget();
}
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
}
private class AccessibilityConnectionWrapper implements DeathRecipient {
private final int mWindowId;
+ private final int mUserId;
private final IAccessibilityInteractionConnection mConnection;
public AccessibilityConnectionWrapper(int windowId,
- IAccessibilityInteractionConnection connection) {
+ IAccessibilityInteractionConnection connection, int userId) {
mWindowId = windowId;
+ mUserId = userId;
mConnection = connection;
}
@@ -1062,12 +1156,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public void binderDied() {
unlinkToDeath();
synchronized (mLock) {
- removeAccessibilityInteractionConnectionLocked(mWindowId);
+ removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
}
}
}
- private class MainHandler extends Handler {
+ private final class MainHandler extends Handler {
+ public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
+ public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
+ public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
+ public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4;
+ public static final int MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE = 5;
public MainHandler(Looper looper) {
super(looper);
@@ -1077,104 +1176,70 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public void handleMessage(Message msg) {
final int type = msg.what;
switch (type) {
- case MSG_TOGGLE_TOUCH_EXPLORATION: {
- final int value = msg.arg1;
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, value);
- } break;
- case MSG_SHOW_ENABLE_TOUCH_EXPLORATION_DIALOG: {
- final Service service = (Service) msg.obj;
- String label = service.mResolveInfo.loadLabel(
- mContext.getPackageManager()).toString();
- synchronized (mLock) {
- if (mIsTouchExplorationEnabled) {
- return;
- }
- if (mEnableTouchExplorationDialog != null
- && mEnableTouchExplorationDialog.isShowing()) {
- return;
- }
- mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // The user allowed the service to toggle touch exploration.
- mTouchExplorationGrantedServices.add(service.mComponentName);
- persistComponentNamesToSettingLocked(
- Settings.Secure.
- TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- mTouchExplorationGrantedServices);
- // Enable touch exploration.
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
- }
- })
- .setNegativeButton(android.R.string.cancel, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- })
- .setTitle(R.string.enable_explore_by_touch_warning_title)
- .setMessage(mContext.getString(
- R.string.enable_explore_by_touch_warning_message, label))
- .create();
- mEnableTouchExplorationDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
- mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
- mEnableTouchExplorationDialog.show();
- }
- } break;
case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
AccessibilityEvent event = (AccessibilityEvent) msg.obj;
- if (mHasInputFilter && mInputFilter != null) {
- mInputFilter.notifyAccessibilityEvent(event);
+ synchronized (mLock) {
+ if (mHasInputFilter && mInputFilter != null) {
+ mInputFilter.notifyAccessibilityEvent(event);
+ }
}
event.recycle();
} break;
- case MSG_SEND_UPDATE_INPUT_FILTER: {
- boolean setInputFilter = false;
- AccessibilityInputFilter inputFilter = null;
+ case MSG_SEND_STATE_TO_CLIENTS: {
+ final int clientState = msg.arg1;
+ final int userId = msg.arg2;
+ sendStateToClients(clientState, mGlobalClients);
+ sendStateToClientsForUser(clientState, userId);
+ } break;
+ case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
+ final int userId = msg.arg1;
+ sendStateToClientsForUser(0, userId);
+ } break;
+ case MSG_SEND_RECREATE_INTERNAL_STATE: {
+ final int userId = msg.arg1;
synchronized (mLock) {
- if ((mIsAccessibilityEnabled && mIsTouchExplorationEnabled)
- || mIsScreenMagnificationEnabled) {
- if (!mHasInputFilter) {
- mHasInputFilter = true;
- if (mInputFilter == null) {
- mInputFilter = new AccessibilityInputFilter(mContext,
- AccessibilityManagerService.this);
- }
- inputFilter = mInputFilter;
- setInputFilter = true;
- }
- int flags = 0;
- if (mIsScreenMagnificationEnabled) {
- flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
- }
- if (mIsTouchExplorationEnabled) {
- flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
- }
- mInputFilter.setEnabledFeatures(flags);
- } else {
- if (mHasInputFilter) {
- mHasInputFilter = false;
- mInputFilter.setEnabledFeatures(0);
- inputFilter = null;
- setInputFilter = true;
- }
- }
+ UserState userState = getUserStateLocked(userId);
+ recreateInternalStateLocked(userState);
}
- if (setInputFilter) {
- try {
- mWindowManager.setInputFilter(inputFilter);
- } catch (RemoteException re) {
- /* ignore */
- }
+ } break;
+ case MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ IAccessibilityServiceClient client =
+ (IAccessibilityServiceClient) args.arg1;
+ AccessibilityServiceInfo info = (AccessibilityServiceInfo) args.arg2;
+ registerUiTestAutomationService(client, info);
+ } finally {
+ args.recycle();
}
} break;
}
}
+
+ private void sendStateToClientsForUser(int clientState, int userId) {
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getUserStateLocked(userId);
+ }
+ sendStateToClients(clientState, userState.mClients);
+ }
+
+ private void sendStateToClients(int clientState,
+ RemoteCallbackList<IAccessibilityManagerClient> clients) {
+ try {
+ final int userClientCount = clients.beginBroadcast();
+ for (int i = 0; i < userClientCount; i++) {
+ IAccessibilityManagerClient client = clients.getBroadcastItem(i);
+ try {
+ client.setState(clientState);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+ } finally {
+ clients.finishBroadcast();
+ }
+ }
}
/**
@@ -1192,6 +1257,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// used as message types allowing us to remove messages per event type.
private static final int MSG_ON_GESTURE = 0x80000000;
+ final int mUserId;
+
int mId = 0;
AccessibilityServiceInfo mAccessibilityServiceInfo;
@@ -1250,8 +1317,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
};
- public Service(ComponentName componentName,
+ public Service(int userId, ComponentName componentName,
AccessibilityServiceInfo accessibilityServiceInfo, boolean isAutomation) {
+ mUserId = userId;
mResolveInfo = accessibilityServiceInfo.getResolveInfo();
mId = sIdCounter++;
mComponentName = componentName;
@@ -1312,7 +1380,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
*/
public boolean bind() {
if (!mIsAutomation && mService == null) {
- return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+ return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE, mUserId);
}
return false;
}
@@ -1355,17 +1423,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public void setServiceInfo(AccessibilityServiceInfo info) {
- synchronized (mLock) {
- // If the XML manifest had data to configure the service its info
- // should be already set. In such a case update only the dynamically
- // configurable properties.
- AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
- if (oldInfo != null) {
- oldInfo.updateDynamicallyConfigurableProperties(info);
- setDynamicallyConfigurableProperties(oldInfo);
- } else {
- setDynamicallyConfigurableProperties(info);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ // If the XML manifest had data to configure the service its info
+ // should be already set. In such a case update only the dynamically
+ // configurable properties.
+ AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
+ if (oldInfo != null) {
+ oldInfo.updateDynamicallyConfigurableProperties(info);
+ setDynamicallyConfigurableProperties(oldInfo);
+ } else {
+ setDynamicallyConfigurableProperties(info);
+ }
}
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -1376,7 +1449,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
try {
mServiceInterface.setConnection(this, mId);
synchronized (mLock) {
- tryAddServiceLocked(this);
+ tryAddServiceLocked(this, mUserId);
}
} catch (RemoteException re) {
Slog.w(LOG_TAG, "Error while setting Controller for service: " + service, re);
@@ -1388,14 +1461,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
long accessibilityNodeId, int viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return -1;
+ }
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
if (!permissionGranted) {
return 0;
} else {
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
return 0;
@@ -1425,10 +1505,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return -1;
+ }
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
@@ -1464,10 +1551,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
long interrogatingTid) throws RemoteException {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return -1;
+ }
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
@@ -1502,10 +1596,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return -1;
+ }
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
@@ -1540,10 +1641,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return -1;
+ }
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
@@ -1576,10 +1684,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public boolean performAccessibilityAction(int accessibilityWindowId,
long accessibilityNodeId, int action, Bundle arguments, int interactionId,
- IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) {
- final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+ IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+ throws RemoteException {
+ final int resolvedWindowId;
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return false;
+ }
+ mSecurityPolicy.enforceCanRetrieveWindowContent(this);
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
resolvedWindowId, action, arguments);
if (!permissionGranted) {
@@ -1608,22 +1725,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return true;
}
- public boolean performGlobalAction(int action) {
- switch (action) {
- case AccessibilityService.GLOBAL_ACTION_BACK: {
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
- } return true;
- case AccessibilityService.GLOBAL_ACTION_HOME: {
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
- } return true;
- case AccessibilityService.GLOBAL_ACTION_RECENTS: {
- openRecents();
- } return true;
- case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
- expandStatusBar();
- } return true;
+ public boolean performGlobalAction(int action) throws RemoteException {
+ synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return false;
+ }
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ switch (action) {
+ case AccessibilityService.GLOBAL_ACTION_BACK: {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
+ } return true;
+ case AccessibilityService.GLOBAL_ACTION_HOME: {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
+ } return true;
+ case AccessibilityService.GLOBAL_ACTION_RECENTS: {
+ openRecents();
+ } return true;
+ case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
+ expandStatusBar();
+ } return true;
+ }
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- return false;
}
public void onServiceDisconnected(ComponentName componentName) {
@@ -1658,7 +1788,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// the state based on values in the settings database.
if (mIsAutomation) {
mUiAutomationService = null;
- updateInternalStateLocked();
+ recreateInternalStateLocked(getUserStateLocked(mUserId));
}
}
}
@@ -1817,8 +1947,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
}
- AccessibilityConnectionWrapper wrapper = mWindowIdToInteractionConnectionWrapperMap.get(
- windowId);
+ AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
+ if (wrapper == null) {
+ wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
+ }
if (wrapper != null && wrapper.mConnection != null) {
return wrapper.mConnection;
}
@@ -1828,7 +1960,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return null;
}
- private int resolveAccessibilityWindowId(int accessibilityWindowId) {
+ private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
return mSecurityPolicy.mActiveWindowId;
}
@@ -1836,9 +1968,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
private float getCompatibilityScale(int windowId) {
- IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId);
try {
- return mWindowManager.getWindowCompatibilityScale(windowToken);
+ IBinder windowToken = mGlobalWindowTokens.get(windowId);
+ if (windowToken != null) {
+ return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+ }
+ windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ if (windowToken != null) {
+ return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+ }
} catch (RemoteException re) {
/* ignore */
}
@@ -1941,6 +2079,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID) {
+ return mCurrentUserId;
+ }
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ if (callingUserId == userId) {
+ return userId;
+ }
+ if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
+ throw new SecurityException("Call from user " + callingUserId + " as user "
+ + userId + " without permission INTERACT_ACROSS_USERS or "
+ + "INTERACT_ACROSS_USERS_FULL not allowed.");
+ }
+ if (userId == UserHandle.USER_CURRENT
+ || userId == UserHandle.USER_CURRENT_OR_SELF) {
+ return mCurrentUserId;
+ }
+ throw new IllegalArgumentException("Calling user can be changed to only "
+ + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
+ }
+
+ public boolean isCallerInteractingAcrossUsers(int userId) {
+ final int callingUid = Binder.getCallingUid();
+ return (callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID
+ || userId == UserHandle.USER_CURRENT
+ || userId == UserHandle.USER_CURRENT_OR_SELF);
+ }
+
private boolean isRetrievalAllowingWindow(int windowId) {
return (mActiveWindowId == windowId);
}
@@ -1953,22 +2123,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (OWN_PROCESS_ID == Binder.getCallingPid()) {
return;
}
- final int permissionStatus = mContext.checkCallingPermission(permission);
- if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
+ if (!hasPermission(permission)) {
throw new SecurityException("You do not have " + permission
+ " required to call " + function);
}
}
+ private boolean hasPermission(String permission) {
+ return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
+ }
+
private int getFocusedWindowId() {
final long identity = Binder.clearCallingIdentity();
try {
// We call this only on window focus change or after touch
// exploration gesture end and the shown windows are not that
// many, so the linear look up is just fine.
- IBinder token = mWindowManager.getFocusedWindowToken();
+ IBinder token = mWindowManagerService.getFocusedWindowToken();
if (token != null) {
- SparseArray<IBinder> windows = mWindowIdToWindowTokenMap;
+ SparseArray<IBinder> windows = getCurrentUserStateLocked().mWindowTokens;
final int windowCount = windows.size();
for (int i = 0; i < windowCount; i++) {
if (windows.valueAt(i) == token) {
@@ -1984,4 +2157,129 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return -1;
}
}
+
+ private class UserState {
+ public final int mUserId;
+
+ public final CopyOnWriteArrayList<Service> mServices = new CopyOnWriteArrayList<Service>();
+
+ public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
+ new RemoteCallbackList<IAccessibilityManagerClient>();
+
+ public final Map<ComponentName, Service> mComponentNameToServiceMap =
+ new HashMap<ComponentName, Service>();
+
+ public final List<AccessibilityServiceInfo> mInstalledServices =
+ new ArrayList<AccessibilityServiceInfo>();
+
+ public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+
+ public final Set<ComponentName> mTouchExplorationGrantedServices =
+ new HashSet<ComponentName>();
+
+ public final SparseArray<AccessibilityConnectionWrapper>
+ mInteractionConnections =
+ new SparseArray<AccessibilityConnectionWrapper>();
+
+ public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
+
+ public int mHandledFeedbackTypes = 0;
+
+ public boolean mIsAccessibilityEnabled;
+ public boolean mIsTouchExplorationEnabled;
+ public boolean mIsDisplayMagnificationEnabled;
+
+ public UserState(int userId) {
+ mUserId = userId;
+ }
+ }
+
+ private final class AccessibilityContentObserver extends ContentObserver {
+
+ private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_ENABLED);
+
+ private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED);
+
+ private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
+
+ private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+
+ private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
+ .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+
+ public AccessibilityContentObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void register(ContentResolver contentResolver) {
+ contentResolver.registerContentObserver(mAccessibilityEnabledUri,
+ false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
+ false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
+ false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
+ false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(
+ mTouchExplorationGrantedAccessibilityServicesUri,
+ false, this, UserHandle.USER_ALL);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mAccessibilityEnabledUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ handleAccessibilityEnabledSettingChangedLocked(userState);
+ updateInputFilterLocked(userState);
+ scheduleSendStateToClientsLocked(userState);
+ }
+ }
+ } else if (mTouchExplorationEnabledUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ handleTouchExplorationEnabledSettingChangedLocked(userState);
+ updateInputFilterLocked(userState);
+ scheduleSendStateToClientsLocked(userState);
+ }
+ }
+ } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ handleDisplayMagnificationEnabledSettingChangedLocked(userState);
+ updateInputFilterLocked(userState);
+ scheduleSendStateToClientsLocked(userState);
+ }
+ }
+ } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ populateEnabledAccessibilityServicesLocked(userState);
+ manageServicesLocked(userState);
+ }
+ }
+ } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
+ handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index cb6b31a..c84f988 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -1150,20 +1150,9 @@ class TouchExplorer implements EventStreamTransformation {
return;
}
- if (Build.IS_DEBUGGABLE) {
- if (mSendHoverEnterDelayed.isPending()) {
- throw new IllegalStateException("mSendHoverEnterDelayed must not be pending.");
- }
- if (mSendHoverExitDelayed.isPending()) {
- throw new IllegalStateException("mSendHoverExitDelayed must not be pending.");
- }
- if (!mPerformLongPressDelayed.isPending()) {
- throw new IllegalStateException(
- "mPerformLongPressDelayed must not be pending.");
- }
- }
-
// Remove pending event deliveries.
+ mSendHoverEnterDelayed.remove();
+ mSendHoverExitDelayed.remove();
mPerformLongPressDelayed.remove();
// The touch interaction has ended since we will send a click.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f162dae..a6f2974 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6414,10 +6414,6 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " (pid=" + Binder.getCallingPid()
+ ") when getting content provider " + name);
}
- if (r.userId != userId) {
- throw new SecurityException("Calling requested user " + userId
- + " but app is user " + r.userId);
- }
}
// First check if this content provider has been published...
@@ -6666,7 +6662,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public final ContentProviderHolder getContentProvider(
- IApplicationThread caller, String name, boolean stable) {
+ IApplicationThread caller, String name, int userId, boolean stable) {
enforceNotIsolatedCaller("getContentProvider");
if (caller == null) {
String msg = "null IApplicationThread when getting content provider "
@@ -6675,14 +6671,18 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- return getContentProviderImpl(caller, name, null, stable,
- UserHandle.getCallingUserId());
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "getContentProvider", null);
+ return getContentProviderImpl(caller, name, null, stable, userId);
}
- public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
+ public ContentProviderHolder getContentProviderExternal(
+ String name, int userId, IBinder token) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
- return getContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
+ userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, true, "getContentProvider", null);
+ return getContentProviderExternalUnchecked(name, token, userId);
}
private ContentProviderHolder getContentProviderExternalUnchecked(String name,
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 05ff379..1707ff0 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -4329,6 +4329,9 @@ final class ActivityStack {
if (resumed != null && resumed.thumbHolder == tr) {
info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
}
+ if (info.mainThumbnail == null) {
+ info.mainThumbnail = tr.lastThumbnail;
+ }
return info;
}
@@ -4343,7 +4346,7 @@ final class ActivityStack {
// thumbnail to return.
TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
if (info.numSubThumbbails <= 0) {
- return info.mainThumbnail;
+ return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
} else {
return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
}
@@ -4387,6 +4390,8 @@ final class ActivityStack {
while (j < NA) {
ActivityRecord ar = mHistory.get(j);
if (!ar.finishing && ar.task.taskId == taskId) {
+ thumbs.root = ar;
+ thumbs.rootIndex = j;
holder = ar.thumbHolder;
if (holder != null) {
thumbs.mainThumbnail = holder.lastThumbnail;
@@ -4401,9 +4406,6 @@ final class ActivityStack {
return thumbs;
}
- thumbs.root = mHistory.get(j);
- thumbs.rootIndex = j;
-
ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
thumbs.subtasks = subtasks;
while (j < NA) {
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index b109f2a..85f3b56 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -536,6 +536,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
return;
}
+ Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
+
mDisplayDevices.add(device);
addLogicalDisplayLocked(device);
scheduleTraversalLocked();
@@ -550,6 +552,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
return;
}
+ Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
+
device.applyPendingDisplayDeviceInfoChangesLocked();
if (updateLogicalDisplaysLocked()) {
scheduleTraversalLocked();
@@ -565,6 +569,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
return;
}
+ Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
+
mRemovedDisplayDevices.add(device);
updateLogicalDisplaysLocked();
scheduleTraversalLocked();
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index eab4c9a..9c51463 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -19,7 +19,9 @@ package com.android.server.display;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.util.SparseArray;
+import android.view.DisplayEventReceiver;
import android.view.Surface;
import android.view.Surface.PhysicalDisplayInfo;
@@ -41,12 +43,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private final SparseArray<LocalDisplayDevice> mDevices =
new SparseArray<LocalDisplayDevice>();
+ private final HotplugDisplayEventReceiver mHotplugReceiver;
private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
super(syncRoot, context, handler, listener, TAG);
+ mHotplugReceiver = new HotplugDisplayEventReceiver(handler.getLooper());
}
@Override
@@ -148,4 +152,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println("mPhys=" + mPhys);
}
}
-}
+
+ private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
+ public HotplugDisplayEventReceiver(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+ synchronized (getSyncRoot()) {
+ scanDisplaysLocked();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index 58f0445..d533c94 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -73,7 +73,7 @@ final class WifiDisplayController implements DumpUtils.Dump {
private static final int DEFAULT_CONTROL_PORT = 7236;
private static final int MAX_THROUGHPUT = 50;
- private static final int CONNECTION_TIMEOUT_SECONDS = 30;
+ private static final int CONNECTION_TIMEOUT_SECONDS = 60;
private static final int RTSP_TIMEOUT_SECONDS = 15;
private static final int DISCOVER_PEERS_MAX_RETRIES = 10;
diff --git a/services/java/com/android/server/location/LocationFudger.java b/services/java/com/android/server/location/LocationFudger.java
index 84fd255..2a68743 100644
--- a/services/java/com/android/server/location/LocationFudger.java
+++ b/services/java/com/android/server/location/LocationFudger.java
@@ -22,6 +22,7 @@ import java.security.SecureRandom;
import android.content.Context;
import android.database.ContentObserver;
import android.location.Location;
+import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
@@ -40,8 +41,6 @@ public class LocationFudger {
private static final boolean D = false;
private static final String TAG = "LocationFudge";
- private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
-
/**
* Default coarse accuracy in meters.
*/
@@ -168,18 +167,10 @@ public class LocationFudger {
*/
public Location getOrCreate(Location location) {
synchronized (mLock) {
- Bundle extras = location.getExtras();
- if (extras == null) {
- return addCoarseLocationExtraLocked(location);
- }
- Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
- if (parcel == null) {
- return addCoarseLocationExtraLocked(location);
- }
- if (!(parcel instanceof Location)) {
+ Location coarse = location.getExtraLocation(Location.EXTRA_COARSE_LOCATION);
+ if (coarse == null) {
return addCoarseLocationExtraLocked(location);
}
- Location coarse = (Location) parcel;
if (coarse.getAccuracy() < mAccuracyInMeters) {
return addCoarseLocationExtraLocked(location);
}
@@ -188,11 +179,8 @@ public class LocationFudger {
}
private Location addCoarseLocationExtraLocked(Location location) {
- Bundle extras = location.getExtras();
- if (extras == null) extras = new Bundle();
Location coarse = createCoarseLocked(location);
- extras.putParcelable(EXTRA_COARSE_LOCATION, coarse);
- location.setExtras(extras);
+ location.setExtraLocation(Location.EXTRA_COARSE_LOCATION, coarse);
return coarse;
}
diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java
index 0ce21b7..71bae07 100644
--- a/services/java/com/android/server/location/PassiveProvider.java
+++ b/services/java/com/android/server/location/PassiveProvider.java
@@ -114,6 +114,6 @@ public class PassiveProvider implements LocationProviderInterface {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("mReportLocaiton=" + mReportLocation);
+ pw.println("mReportLocation=" + mReportLocation);
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 739caa0..4800e7db 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -413,7 +413,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// package uri's from external media onto secure containers
// or internal storage.
private IMediaContainerService mContainerService = null;
- private int mContainerServiceUserId;
static final int SEND_PENDING_BROADCAST = 1;
static final int MCS_BOUND = 3;
@@ -482,15 +481,8 @@ public class PackageManagerService extends IPackageManager.Stub {
" DefaultContainerService");
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- mContainerServiceUserId = 0;
- if (mPendingInstalls.size() > 0) {
- mContainerServiceUserId = mPendingInstalls.get(0).getUser().getIdentifier();
- if (mContainerServiceUserId == UserHandle.USER_ALL) {
- mContainerServiceUserId = 0;
- }
- }
if (mContext.bindService(service, mDefContainerConn,
- Context.BIND_AUTO_CREATE, mContainerServiceUserId)) {
+ Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
@@ -567,15 +559,6 @@ public class PackageManagerService extends IPackageManager.Stub {
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
- // Check if we're connected to the correct service, if it's an install
- // request.
- final int installFor = params.getUser().getIdentifier();
- if (installFor != mContainerServiceUserId
- && (installFor == UserHandle.USER_ALL
- && mContainerServiceUserId != 0)) {
- mHandler.sendEmptyMessage(MCS_RECONNECT);
- return;
- }
if (params.startCopy()) {
// We are done... look for more work or to
// go idle.
@@ -693,20 +676,23 @@ public class PackageManagerService extends IPackageManager.Stub {
}
case START_CLEANING_PACKAGE: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- PackageCleanItem item = new PackageCleanItem((String)msg.obj,
- msg.arg2 != 0);
+ final String packageName = (String)msg.obj;
+ final int userId = msg.arg1;
+ final boolean andCode = msg.arg2 != 0;
synchronized (mPackages) {
- if (msg.arg1 == UserHandle.USER_ALL) {
+ if (userId == UserHandle.USER_ALL) {
int[] users = sUserManager.getUserIds();
for (int user : users) {
- mSettings.addPackageToCleanLPw(user, item);
+ mSettings.addPackageToCleanLPw(
+ new PackageCleanItem(user, packageName, andCode));
}
} else {
- mSettings.addPackageToCleanLPw(msg.arg1, item);
+ mSettings.addPackageToCleanLPw(
+ new PackageCleanItem(userId, packageName, andCode));
}
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- startCleaningPackages(-1);
+ startCleaningPackages();
} break;
case POST_INSTALL: {
if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
@@ -1715,6 +1701,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public int[] getPackageGids(String packageName) {
+ final boolean enforcedDefault = isPermissionEnforcedDefault(READ_EXTERNAL_STORAGE);
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -1726,7 +1713,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int[] gids = suid != null ? suid.gids : ps.gids;
// include GIDs for any unenforced permissions
- if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
+ if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE, enforcedDefault)) {
final BasePermission basePerm = mSettings.mPermissions.get(
READ_EXTERNAL_STORAGE);
gids = appendInts(gids, basePerm.gids);
@@ -2054,6 +2041,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public int checkPermission(String permName, String pkgName) {
+ final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(pkgName);
if (p != null && p.mExtras != null) {
@@ -2066,7 +2054,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
- if (!isPermissionEnforcedLocked(permName)) {
+ if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
return PackageManager.PERMISSION_GRANTED;
}
}
@@ -2074,6 +2062,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
public int checkUidPermission(String permName, int uid) {
+ final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
if (obj != null) {
@@ -2087,7 +2076,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.PERMISSION_GRANTED;
}
}
- if (!isPermissionEnforcedLocked(permName)) {
+ if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
return PackageManager.PERMISSION_GRANTED;
}
}
@@ -2488,6 +2477,15 @@ public class PackageManagerService extends IPackageManager.Stub {
if (ri != null) {
return ri;
}
+ if (userId != 0) {
+ ri = new ResolveInfo(mResolveInfo);
+ ri.activityInfo = new ActivityInfo(ri.activityInfo);
+ ri.activityInfo.applicationInfo = new ApplicationInfo(
+ ri.activityInfo.applicationInfo);
+ ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
+ UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
+ return ri;
+ }
return mResolveInfo;
}
}
@@ -3668,7 +3666,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mResolveActivity.applicationInfo = mAndroidApplication;
mResolveActivity.name = ResolverActivity.class.getName();
mResolveActivity.packageName = mAndroidApplication.packageName;
- mResolveActivity.processName = mAndroidApplication.processName;
+ mResolveActivity.processName = "system:ui";
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
@@ -4181,10 +4179,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
- for (int i=0; i<mSettings.mPackagesToBeCleaned.size(); i++) {
- mSettings.mPackagesToBeCleaned.valueAt(i).remove(pkgName);
+ final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
+ while (iter.hasNext()) {
+ PackageCleanItem item = iter.next();
+ if (pkgName.equals(item.packageName)) {
+ iter.remove();
+ }
}
-
+
// Take care of first install / last update times.
if (currentTime != 0) {
if (pkgSetting.firstInstallTime == 0) {
@@ -5431,7 +5433,6 @@ public class PackageManagerService extends IPackageManager.Stub {
public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
// writer
- final int userId = UserHandle.getCallingUserId();
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
// If the external storage is no longer mounted at this point,
@@ -5439,23 +5440,13 @@ public class PackageManagerService extends IPackageManager.Stub {
// packages files and can not delete any more. Bail.
return null;
}
- ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned.get(userId);
- if (pkgs != null) {
- if (lastPackage != null) {
- pkgs.remove(lastPackage);
- }
- if (pkgs.size() > 0) {
- return pkgs.get(0);
- }
+ final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
+ if (lastPackage != null) {
+ pkgs.remove(lastPackage);
+ }
+ if (pkgs.size() > 0) {
+ return pkgs.get(0);
}
- mSettings.mPackagesToBeCleaned.remove(userId);
- }
- // Move on to the next user to clean.
- long ident = Binder.clearCallingIdentity();
- try {
- startCleaningPackages(userId);
- } finally {
- Binder.restoreCallingIdentity(ident);
}
return null;
}
@@ -5471,34 +5462,22 @@ public class PackageManagerService extends IPackageManager.Stub {
userId, andCode ? 1 : 0, packageName));
}
- void startCleaningPackages(int lastUser) {
+ void startCleaningPackages() {
// reader
- int nextUser = -1;
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
return;
}
- final int N = mSettings.mPackagesToBeCleaned.size();
- if (N <= 0) {
+ if (mSettings.mPackagesToBeCleaned.isEmpty()) {
return;
}
- for (int i=0; i<N; i++) {
- int user = mSettings.mPackagesToBeCleaned.keyAt(i);
- if (user > lastUser) {
- nextUser = user;
- break;
- }
- }
- if (nextUser < 0) {
- nextUser = mSettings.mPackagesToBeCleaned.keyAt(0);
- }
}
Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.startService(null, intent, null, nextUser);
+ am.startService(null, intent, null, UserHandle.USER_OWNER);
} catch (RemoteException e) {
}
}
@@ -5904,11 +5883,20 @@ public class PackageManagerService extends IPackageManager.Stub {
*
* @return true if verification should be performed
*/
- private boolean isVerificationEnabled() {
+ private boolean isVerificationEnabled(int flags) {
if (!DEFAULT_VERIFY_ENABLE) {
return false;
}
+ // Check if installing from ADB
+ if ((flags & PackageManager.INSTALL_FROM_ADB) != 0) {
+ // Check if the developer does not want package verification for ADB installs
+ if (android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
+ return false;
+ }
+ }
+
return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
}
@@ -6406,7 +6394,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, 0);
- if (requiredUid != -1 && isVerificationEnabled()) {
+ if (requiredUid != -1 && isVerificationEnabled(flags)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
@@ -8378,10 +8366,11 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
users = new int[] { userId };
}
- for (int curUser : users) {
- ClearStorageConnection conn = new ClearStorageConnection();
- if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE, curUser)) {
- try {
+ final ClearStorageConnection conn = new ClearStorageConnection();
+ if (mContext.bindService(
+ containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_OWNER)) {
+ try {
+ for (int curUser : users) {
long timeout = SystemClock.uptimeMillis() + 5000;
synchronized (conn) {
long now = SystemClock.uptimeMillis();
@@ -8417,9 +8406,9 @@ public class PackageManagerService extends IPackageManager.Stub {
} catch (RemoteException e) {
}
}
- } finally {
- mContext.unbindService(conn);
}
+ } finally {
+ mContext.unbindService(conn);
}
}
}
@@ -9575,7 +9564,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Loading packages");
loadMediaPackages(processCids, uidArr, removeCids);
- startCleaningPackages(-1);
+ startCleaningPackages();
} else {
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Unloading packages");
@@ -10115,19 +10104,36 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public boolean isPermissionEnforced(String permission) {
+ final boolean enforcedDefault = isPermissionEnforcedDefault(permission);
synchronized (mPackages) {
- return isPermissionEnforcedLocked(permission);
+ return isPermissionEnforcedLocked(permission, enforcedDefault);
}
}
- private boolean isPermissionEnforcedLocked(String permission) {
+ /**
+ * Check if given permission should be enforced by default. Should always be
+ * called outside of {@link #mPackages} lock.
+ */
+ private boolean isPermissionEnforcedDefault(String permission) {
+ if (READ_EXTERNAL_STORAGE.equals(permission)) {
+ return Secure.getInt(mContext.getContentResolver(),
+ Secure.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0) != 0;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Check if user has requested that given permission be enforced, using
+ * given default if undefined.
+ */
+ private boolean isPermissionEnforcedLocked(String permission, boolean enforcedDefault) {
if (READ_EXTERNAL_STORAGE.equals(permission)) {
if (mSettings.mReadExternalStorageEnforced != null) {
return mSettings.mReadExternalStorageEnforced;
} else {
- // if user hasn't defined, fall back to secure default
- return Secure.getInt(mContext.getContentResolver(),
- Secure.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0) != 0;
+ // User hasn't defined; fall back to secure default
+ return enforcedDefault;
}
} else {
return true;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 23e54678..2fb853a 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -159,8 +159,7 @@ final class Settings {
// Packages that have been uninstalled and still need their external
// storage data deleted.
- final SparseArray<ArrayList<PackageCleanItem>> mPackagesToBeCleaned
- = new SparseArray<ArrayList<PackageCleanItem>>();
+ final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
// Packages that have been renamed since they were first installed.
// Keys are the new names of the packages, values are the original
@@ -1257,18 +1256,13 @@ final class Settings {
}
if (mPackagesToBeCleaned.size() > 0) {
- for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
- final int userId = mPackagesToBeCleaned.keyAt(i);
- final String userStr = Integer.toString(userId);
- final ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.valueAt(i);
- for (int j=0; j<pkgs.size(); j++) {
- serializer.startTag(null, "cleaning-package");
- PackageCleanItem item = pkgs.get(j);
- serializer.attribute(null, ATTR_NAME, item.packageName);
- serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
- serializer.attribute(null, ATTR_USER, userStr);
- serializer.endTag(null, "cleaning-package");
- }
+ for (PackageCleanItem item : mPackagesToBeCleaned) {
+ final String userStr = Integer.toString(item.userId);
+ serializer.startTag(null, "cleaning-package");
+ serializer.attribute(null, ATTR_NAME, item.packageName);
+ serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
+ serializer.attribute(null, ATTR_USER, userStr);
+ serializer.endTag(null, "cleaning-package");
}
}
@@ -1524,14 +1518,9 @@ final class Settings {
return ret;
}
- void addPackageToCleanLPw(int userId, PackageCleanItem pkg) {
- ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.get(userId);
- if (pkgs == null) {
- pkgs = new ArrayList<PackageCleanItem>();
- mPackagesToBeCleaned.put(userId, pkgs);
- }
- if (!pkgs.contains(pkg)) {
- pkgs.add(pkg);
+ void addPackageToCleanLPw(PackageCleanItem pkg) {
+ if (!mPackagesToBeCleaned.contains(pkg)) {
+ mPackagesToBeCleaned.add(pkg);
}
}
@@ -1615,18 +1604,18 @@ final class Settings {
String userStr = parser.getAttributeValue(null, ATTR_USER);
String codeStr = parser.getAttributeValue(null, ATTR_CODE);
if (name != null) {
- int user = 0;
+ int userId = 0;
boolean andCode = true;
try {
if (userStr != null) {
- user = Integer.parseInt(userStr);
+ userId = Integer.parseInt(userStr);
}
} catch (NumberFormatException e) {
}
if (codeStr != null) {
andCode = Boolean.parseBoolean(codeStr);
}
- addPackageToCleanLPw(user, new PackageCleanItem(name, andCode));
+ addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
}
} else if (tagName.equals("renamed-package")) {
String nname = parser.getAttributeValue(null, "new");