diff options
| author | Elijah Taylor <elijahtaylor@google.com> | 2016-07-11 14:28:06 -0700 |
|---|---|---|
| committer | Luis Hector Chavez <lhchavez@google.com> | 2017-06-23 09:54:09 -0700 |
| commit | 6022aa57d3152c134b3de14c163379cd486dc58e (patch) | |
| tree | 9ea777b7bcf5924f4fe2d1749d26c96ee7904fef /core/java/android/appwidget/AppWidgetHost.java | |
| parent | 360eea897fe2085f75ccd2f5d57b351abbbddcef (diff) | |
Fix crashes in AppWidgetHost when app_widgets is not supported
Even though an app is supposed to declare android.software.app_widgets
when relying on the widgets API, some apps still use this API without
declaring the feature. Previously AppWidgetHost relied on having an
AppWidgetService available, without checking for feature development
before dereferencing the service.
This stubs out the AppWidgetHost interface when the app_widgets feature
is not available.
Bug: 28847209
Test: run nova launcher, observe no crash
Change-Id: Idaf46de990fffa6c6a03562f8e097c0a6a320c8a
(cherry picked from commit 0536802defc7df6edb22e076b1147d0d919da0f8)
Diffstat (limited to 'core/java/android/appwidget/AppWidgetHost.java')
| -rw-r--r-- | core/java/android/appwidget/AppWidgetHost.java | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index c1ff580cbce7..37360bad73c7 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -16,15 +16,13 @@ package android.appwidget; -import java.lang.ref.WeakReference; -import java.util.List; - import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.IntentSender; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -42,6 +40,9 @@ import android.widget.RemoteViews.OnClickHandler; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; +import java.lang.ref.WeakReference; +import java.util.List; + /** * AppWidgetHost provides the interaction with the AppWidget service for apps, * like the home screen, that want to embed AppWidgets in their UI. @@ -55,6 +56,7 @@ public class AppWidgetHost { final static Object sServiceLock = new Object(); static IAppWidgetService sService; + static boolean sServiceInitialized = false; private DisplayMetrics mDisplayMetrics; private String mContextOpPackageName; @@ -160,15 +162,21 @@ public class AppWidgetHost { mHandler = new UpdateHandler(looper); mCallbacks = new Callbacks(mHandler); mDisplayMetrics = context.getResources().getDisplayMetrics(); - bindService(); + bindService(context); } - private static void bindService() { + private static void bindService(Context context) { synchronized (sServiceLock) { - if (sService == null) { - IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); - sService = IAppWidgetService.Stub.asInterface(b); + if (sServiceInitialized) { + return; } + sServiceInitialized = true; + if (!context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_APP_WIDGETS)) { + return; + } + IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); + sService = IAppWidgetService.Stub.asInterface(b); } } @@ -177,6 +185,9 @@ public class AppWidgetHost { * becomes visible, i.e. from onStart() in your Activity. */ public void startListening() { + if (sService == null) { + return; + } final int[] idsToUpdate; synchronized (mViews) { int N = mViews.size(); @@ -215,6 +226,9 @@ public class AppWidgetHost { * no longer visible, i.e. from onStop() in your Activity. */ public void stopListening() { + if (sService == null) { + return; + } try { sService.stopListening(mContextOpPackageName, mHostId); } @@ -229,6 +243,9 @@ public class AppWidgetHost { * @return a appWidgetId */ public int allocateAppWidgetId() { + if (sService == null) { + return -1; + } try { return sService.allocateAppWidgetId(mContextOpPackageName, mHostId); } @@ -258,6 +275,9 @@ public class AppWidgetHost { */ public final void startAppWidgetConfigureActivityForResult(@NonNull Activity activity, int appWidgetId, int intentFlags, int requestCode, @Nullable Bundle options) { + if (sService == null) { + return; + } try { IntentSender intentSender = sService.createAppWidgetConfigIntentSender( mContextOpPackageName, appWidgetId, intentFlags); @@ -278,10 +298,10 @@ public class AppWidgetHost { * Gets a list of all the appWidgetIds that are bound to the current host */ public int[] getAppWidgetIds() { + if (sService == null) { + return new int[0]; + } try { - if (sService == null) { - bindService(); - } return sService.getAppWidgetIdsForHost(mContextOpPackageName, mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -292,6 +312,9 @@ public class AppWidgetHost { * Stop listening to changes for this AppWidget. */ public void deleteAppWidgetId(int appWidgetId) { + if (sService == null) { + return; + } synchronized (mViews) { mViews.remove(appWidgetId); try { @@ -312,6 +335,9 @@ public class AppWidgetHost { * </ul> */ public void deleteHost() { + if (sService == null) { + return; + } try { sService.deleteHost(mContextOpPackageName, mHostId); } @@ -329,6 +355,9 @@ public class AppWidgetHost { * </ul> */ public static void deleteAllHosts() { + if (sService == null) { + return; + } try { sService.deleteAllHosts(); } @@ -343,6 +372,9 @@ public class AppWidgetHost { */ public final AppWidgetHostView createView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { + if (sService == null) { + return null; + } AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget); view.setOnClickHandler(mOnClickHandler); view.setAppWidget(appWidgetId, appWidget); |
