Merge "App ops: don't crash when provide read access is off." into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index 8b77cc9..2e28d7b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6726,6 +6726,7 @@
field public static final int DONT_KILL_APP = 1; // 0x1
field public static final java.lang.String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
+ field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera";
@@ -6736,6 +6737,8 @@
field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
+ field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
+ field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0d463ee..0bea138 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1145,6 +1145,29 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports app widgets.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_APP_WIDGETS = "android.software.app_widgets";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports a home screen that is replaceable
+ * by third party applications.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_HOME_SCREEN = "android.software.home_screen";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports adding new input methods implemented
+ * with the {@link android.inputmethodservice.InputMethodService} API.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_INPUT_METHODS = "android.software.input_methods";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports WiFi (802.11) networking.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3ce4c13..b30dc83 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3562,7 +3562,7 @@
+ " accelMovement=" + accelMovement
+ " accel=" + accel);
if (accelMovement > movement) {
- if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
+ keycode);
movement--;
int repeatCount = accelMovement - movement;
@@ -3572,7 +3572,7 @@
InputDevice.SOURCE_KEYBOARD));
}
while (movement > 0) {
- if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
+ if (DEBUG_TRACKBALL) Log.v(TAG, "Delivering fake DPAD: "
+ keycode);
movement--;
curTime = SystemClock.uptimeMillis();
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 6eea928..fb2828b 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -177,18 +177,20 @@
// Manages persistent references to RemoteViewsServices from different App Widgets
private final HashMap<FilterComparison, HashSet<Integer>> mRemoteViewsServicesAppWidgets = new HashMap<FilterComparison, HashSet<Integer>>();
- Context mContext;
+ final Context mContext;
+ final IPackageManager mPm;
+ final AlarmManager mAlarmManager;
+ final ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
+ final int mUserId;
+ final boolean mHasFeature;
+
Locale mLocale;
- IPackageManager mPm;
- AlarmManager mAlarmManager;
- ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
- ArrayList<Host> mHosts = new ArrayList<Host>();
+ final ArrayList<Host> mHosts = new ArrayList<Host>();
// set of package names
- HashSet<String> mPackagesWithBindWidgetPermission = new HashSet<String>();
+ final HashSet<String> mPackagesWithBindWidgetPermission = new HashSet<String>();
boolean mSafeMode;
- int mUserId;
boolean mStateLoaded;
int mMaxWidgetBitmapMemory;
@@ -204,6 +206,8 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserId = userId;
mSaveStateHandler = saveStateHandler;
+ mHasFeature = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_APP_WIDGETS);
computeMaximumWidgetBitmapMemory();
}
@@ -426,6 +430,9 @@
private void ensureStateLoadedLocked() {
if (!mStateLoaded) {
+ if (!mHasFeature) {
+ return;
+ }
loadAppWidgetListLocked();
loadStateLocked();
mStateLoaded = true;
@@ -435,6 +442,9 @@
public int allocateAppWidgetId(String packageName, int hostId) {
int callingUid = enforceSystemOrCallingUid(packageName);
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return -1;
+ }
ensureStateLoadedLocked();
int appWidgetId = mNextAppWidgetId++;
@@ -456,6 +466,9 @@
public void deleteAppWidgetId(int appWidgetId) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id != null) {
@@ -467,6 +480,9 @@
public void deleteHost(int hostId) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
int callingUid = Binder.getCallingUid();
Host host = lookupHostLocked(callingUid, hostId);
@@ -479,6 +495,9 @@
public void deleteAllHosts() {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
int callingUid = Binder.getCallingUid();
final int N = mHosts.size();
@@ -561,6 +580,9 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
options = cloneIfLocalBinder(options);
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
@@ -622,6 +644,9 @@
public boolean bindAppWidgetIdIfAllowed(
String packageName, int appWidgetId, ComponentName provider, Bundle options) {
+ if (!mHasFeature) {
+ return false;
+ }
try {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
} catch (SecurityException se) {
@@ -649,6 +674,9 @@
}
public boolean hasBindAppWidgetPermission(String packageName) {
+ if (!mHasFeature) {
+ return false;
+ }
mContext.enforceCallingPermission(
android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
"hasBindAppWidgetPermission packageName=" + packageName);
@@ -660,6 +688,9 @@
}
public void setBindAppWidgetPermission(String packageName, boolean permission) {
+ if (!mHasFeature) {
+ return;
+ }
mContext.enforceCallingPermission(
android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS,
"setBindAppWidgetPermission packageName=" + packageName);
@@ -678,6 +709,9 @@
// Binds to a specific RemoteViewsService
public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id == null) {
@@ -735,6 +769,9 @@
// Unbinds from a specific RemoteViewsService
public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
// Unbind from the RemoteViewsService (which will trigger a callback to the bound
// RemoteViewsAdapter)
@@ -846,6 +883,9 @@
public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return null;
+ }
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id != null && id.provider != null && !id.provider.zombie) {
@@ -858,6 +898,9 @@
public RemoteViews getAppWidgetViews(int appWidgetId) {
if (DBG) log("getAppWidgetViews id=" + appWidgetId);
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return null;
+ }
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id != null) {
@@ -870,6 +913,9 @@
public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return new ArrayList<AppWidgetProviderInfo>(0);
+ }
ensureStateLoadedLocked();
final int N = mInstalledProviders.size();
ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>(N);
@@ -884,6 +930,9 @@
}
public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
+ if (!mHasFeature) {
+ return;
+ }
if (appWidgetIds == null) {
return;
}
@@ -929,6 +978,9 @@
public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
options = cloneIfLocalBinder(options);
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
@@ -953,6 +1005,9 @@
public Bundle getAppWidgetOptions(int appWidgetId) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return Bundle.EMPTY;
+ }
ensureStateLoadedLocked();
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id != null && id.options != null) {
@@ -964,6 +1019,9 @@
}
public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views) {
+ if (!mHasFeature) {
+ return;
+ }
if (appWidgetIds == null) {
return;
}
@@ -987,6 +1045,9 @@
}
public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
+ if (!mHasFeature) {
+ return;
+ }
if (appWidgetIds == null) {
return;
}
@@ -1005,6 +1066,9 @@
}
public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) {
+ if (!mHasFeature) {
+ return;
+ }
synchronized (mAppWidgetIds) {
ensureStateLoadedLocked();
Provider p = lookupProviderLocked(provider);
@@ -1147,6 +1211,9 @@
public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
List<RemoteViews> updatedViews) {
+ if (!mHasFeature) {
+ return new int[0];
+ }
int callingUid = enforceCallingUid(packageName);
synchronized (mAppWidgetIds) {
ensureStateLoadedLocked();
@@ -1169,6 +1236,9 @@
public void stopListening(int hostId) {
synchronized (mAppWidgetIds) {
+ if (!mHasFeature) {
+ return;
+ }
ensureStateLoadedLocked();
Host host = lookupHostLocked(Binder.getCallingUid(), hostId);
if (host != null) {
@@ -1558,6 +1628,9 @@
}
void saveStateLocked() {
+ if (!mHasFeature) {
+ return;
+ }
AtomicFile file = savedStateFile();
FileOutputStream stream;
try {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 0863bd6..dd081a1 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -164,6 +164,7 @@
final SettingsObserver mSettingsObserver;
final IWindowManager mIWindowManager;
final HandlerCaller mCaller;
+ final boolean mHasFeature;
private InputMethodFileManager mFileManager;
private InputMethodAndSubtypeListManager mImListManager;
private final HardKeyboardListener mHardKeyboardListener;
@@ -608,6 +609,8 @@
}, true /*asyncHandler*/);
mWindowManagerService = windowManager;
mHardKeyboardListener = new HardKeyboardListener();
+ mHasFeature = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_INPUT_METHODS);
mImeSwitcherNotification = new Notification();
mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index d84018f..527e891 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1070,14 +1070,6 @@
if (userState.mBindingServices.contains(componentName)) {
continue;
}
- // No enabled installed services => disable accessibility to avoid
- // sending accessibility events with no recipient across processes.
- if (userState.mEnabledServices.isEmpty()) {
- userState.mIsAccessibilityEnabled = false;
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
- return;
- }
if (userState.mEnabledServices.contains(componentName)) {
if (service == null) {
service = new Service(userState.mUserId, componentName, installedService);
@@ -1098,6 +1090,14 @@
}
}
}
+
+ // No enabled installed services => disable accessibility to avoid
+ // sending accessibility events with no recipient across processes.
+ if (isEnabled && userState.mEnabledServices.isEmpty()) {
+ userState.mIsAccessibilityEnabled = false;
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
+ }
}
private void scheduleUpdateClientsIfNeededLocked(UserState userState) {