diff options
6 files changed, 108 insertions, 21 deletions
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index c76bf91..51a81c5 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -24,8 +24,10 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.RemoteViews; @@ -115,18 +117,22 @@ public class AppWidgetHost { private OnClickHandler mOnClickHandler; public AppWidgetHost(Context context, int hostId) { - this(context, hostId, null); + this(context, hostId, null, Looper.getMainLooper()); } /** * @hide */ - public AppWidgetHost(Context context, int hostId, OnClickHandler handler) { + public AppWidgetHost(Context context, int hostId, OnClickHandler handler, Looper looper) { mContext = context; mHostId = hostId; mOnClickHandler = handler; - mHandler = new UpdateHandler(context.getMainLooper()); + mHandler = new UpdateHandler(looper); mDisplayMetrics = context.getResources().getDisplayMetrics(); + bindService(); + } + + private static void bindService() { synchronized (sServiceLock) { if (sService == null) { IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); @@ -190,6 +196,32 @@ public class AppWidgetHost { } /** + * Get a appWidgetId for a host in the calling process. + * + * @return a appWidgetId + * @hide + */ + public static int allocateAppWidgetIdForHost(String packageName, int hostId) { + checkCallerIsSystem(); + try { + if (sService == null) { + bindService(); + } + return sService.allocateAppWidgetId(packageName, hostId); + } catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + private static void checkCallerIsSystem() { + int uid = Process.myUid(); + if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) { + return; + } + throw new SecurityException("Disallowed call for uid " + uid); + } + + /** * Stop listening to changes for this AppWidget. */ public void deleteAppWidgetId(int appWidgetId) { @@ -205,6 +237,22 @@ public class AppWidgetHost { } /** + * Stop listening to changes for this AppWidget. + * @hide + */ + public static void deleteAppWidgetIdForHost(int appWidgetId) { + checkCallerIsSystem(); + try { + if (sService == null) { + bindService(); + } + sService.deleteAppWidgetId(appWidgetId); + } catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** * Remove all records about this host from the AppWidget manager. * <ul> * <li>Call this when initializing your database, as it might be because of a data wipe.</li> diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 0a2a6f6..6fb6dc4 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -218,18 +218,26 @@ public class AppWidgetManager { /** * An intent extra to pass to the AppWidget picker which allows the picker to filter * the list based on the {@link AppWidgetProviderInfo#widgetCategory}. + * + * @hide */ - /** @hide */ public static final String EXTRA_CATEGORY_FILTER = "categoryFilter"; /** * An intent extra to pass to the AppWidget picker which allows the picker to filter * the list based on the {@link AppWidgetProviderInfo#widgetFeatures}. + * @hide */ - /** @hide */ public static final String EXTRA_FEATURES_FILTER = "featuresFilter"; /** + * An intent extra to pass to the AppWidget picker to specify whether or not to sort + * the list of caller-specified extra AppWidgets along with the rest of the AppWidgets + * @hide + */ + public static final String EXTRA_CUSTOM_SORT = "customSort"; + + /** * A sentiel value that the AppWidget manager will never return as a appWidgetId. */ public static final int INVALID_APPWIDGET_ID = 0; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c3d3c26..7c6db1d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3201,6 +3201,20 @@ public final class Settings { public static final String LOCK_SCREEN_OWNER_INFO = "lock_screen_owner_info"; /** + * Id of the time appwidget on the lockscreen, or -1 if none + * @hide + */ + public static final String LOCK_SCREEN_CLOCK_APPWIDGET_ID = + "lock_screen_clock_appwidget_id"; + + /** + * Id of the user-selected appwidget on the lockscreen, or -1 if none + * @hide + */ + public static final String LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID = + "lock_screen_user_selected_appwidget_id"; + + /** * This preference enables showing the owner info on LockScren. * @hide */ diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 4777c16..6a040a6 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1001,6 +1001,17 @@ public class LockPatternUtils { } } + public int[] getUserDefinedWidgets() { + int appWidgetId = -1; + String appWidgetIdString = Settings.Secure.getString( + mContentResolver, Settings.Secure.LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID); + if (appWidgetIdString != null) { + appWidgetId = (int) Integer.decode(appWidgetIdString); + } + + return new int[] { appWidgetId }; + } + private long getLong(String secureSettingKey, long defaultValue) { try { return getLockSettings().getLong(secureSettingKey, defaultValue, diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 1405260..95f8500 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -28,11 +28,11 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.Intent; import android.content.IntentSender; -import android.content.SharedPreferences; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; +import android.os.Looper; import android.os.UserManager; import android.util.AttributeSet; import android.util.Log; @@ -41,8 +41,6 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.animation.AnimationUtils; import android.widget.RemoteViews.OnClickHandler; @@ -61,6 +59,7 @@ public class KeyguardHostView extends KeyguardViewBase { // Use this to debug all of keyguard public static boolean DEBUG; + // also referenced in SecuritySettings.java static final int APPWIDGET_HOST_ID = 0x4B455947; private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs"; @@ -94,8 +93,9 @@ public class KeyguardHostView extends KeyguardViewBase { public KeyguardHostView(Context context, AttributeSet attrs) { super(context, attrs); mLockPatternUtils = new LockPatternUtils(context); - mAppWidgetHost = new AppWidgetHost(mContext, APPWIDGET_HOST_ID, mOnClickHandler); - mSecurityModel = new KeyguardSecurityModel(mContext); + mAppWidgetHost = new AppWidgetHost( + context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper()); + mSecurityModel = new KeyguardSecurityModel(context); // The following enables the MENU key to work for testing automation mEnableMenuKey = shouldEnableMenuKey(); @@ -212,7 +212,7 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetHost.stopListening(); } - AppWidgetHost getAppWidgetHost() { + private AppWidgetHost getAppWidgetHost() { return mAppWidgetHost; } @@ -674,15 +674,11 @@ public class KeyguardHostView extends KeyguardViewBase { return; } inflateAndAddUserSelectorWidgetIfNecessary(); - SharedPreferences prefs = mContext.getSharedPreferences( - KEYGUARD_WIDGET_PREFS, Context.MODE_PRIVATE); - for (String key : prefs.getAll().keySet()) { - int appId = prefs.getInt(key, -1); - if (appId != -1) { - Log.w(TAG, "populate: adding " + key); - addWidget(appId); - } else { - Log.w(TAG, "populate: can't find " + key); + + final int[] widgets = mLockPatternUtils.getUserDefinedWidgets(); + for (int i = 0; i < widgets.length; i++) { + if (widgets[i] != -1) { + addWidget(widgets[i]); } } } diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java index 5801551..499c15e 100644 --- a/services/java/com/android/server/AppWidgetServiceImpl.java +++ b/services/java/com/android/server/AppWidgetServiceImpl.java @@ -42,6 +42,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -409,7 +410,7 @@ class AppWidgetServiceImpl { } public int allocateAppWidgetId(String packageName, int hostId) { - int callingUid = enforceCallingUid(packageName); + int callingUid = enforceSystemOrCallingUid(packageName); synchronized (mAppWidgetIds) { ensureStateLoadedLocked(); int appWidgetId = mNextAppWidgetId++; @@ -1391,6 +1392,15 @@ class AppWidgetServiceImpl { return pkgInfo.applicationInfo.uid; } + int enforceSystemOrCallingUid(String packageName) throws IllegalArgumentException { + int callingUid = Binder.getCallingUid(); + int uid = Process.myUid(); + if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) { + return callingUid; + } + return enforceCallingUid(packageName); + } + int enforceCallingUid(String packageName) throws IllegalArgumentException { int callingUid = Binder.getCallingUid(); int packageUid; |