diff options
Diffstat (limited to 'core/java/android/widget')
-rw-r--r-- | core/java/android/widget/AnalogClock.java | 10 | ||||
-rw-r--r-- | core/java/android/widget/RemoteViews.java | 167 | ||||
-rw-r--r-- | core/java/android/widget/RemoteViewsAdapter.java | 42 | ||||
-rw-r--r-- | core/java/android/widget/ViewFlipper.java | 14 |
4 files changed, 121 insertions, 112 deletions
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java index 5b80648..1716dbd 100644 --- a/core/java/android/widget/AnalogClock.java +++ b/core/java/android/widget/AnalogClock.java @@ -111,7 +111,15 @@ public class AnalogClock extends View { filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); - getContext().registerReceiver(mIntentReceiver, filter, null, mHandler); + // OK, this is gross but needed. This class is supported by the + // remote views machanism and as a part of that the remote views + // can be inflated by a context for another user without the app + // having interact users permission - just for loading resources. + // For exmaple, when adding widgets from a user profile to the + // home screen. Therefore, we register the receiver as the current + // user not the one the context is for. + getContext().registerReceiverAsUser(mIntentReceiver, + android.os.Process.myUserHandle(), filter, null, mHandler); } // NOTE: It's safe to do these after registering the receiver since the receiver always runs diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 5c7a43b..1098fa2 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -17,6 +17,7 @@ package android.widget; import android.app.ActivityOptions; +import android.app.ActivityThread; import android.app.PendingIntent; import android.appwidget.AppWidgetHostView; import android.content.Context; @@ -73,11 +74,11 @@ public class RemoteViews implements Parcelable, Filter { static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId"; /** - * User that these views should be applied as. Requires - * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} when - * crossing user boundaries. + * Application that hosts the remote views. + * + * @hide */ - private UserHandle mUser = android.os.Process.myUserHandle(); + private ApplicationInfo mApplication; /** * The package name of the package containing the layout @@ -275,9 +276,9 @@ public class RemoteViews implements Parcelable, Filter { /** * Merges the passed RemoteViews actions with this RemoteViews actions according to * action-specific merge rules. - * + * * @param newRv - * + * * @hide */ public void mergeRemoteViews(RemoteViews newRv) { @@ -1608,16 +1609,16 @@ public class RemoteViews implements Parcelable, Filter { int bpp = 4; if (c != null) { switch (c) { - case ALPHA_8: - bpp = 1; - break; - case RGB_565: - case ARGB_4444: - bpp = 2; - break; - case ARGB_8888: - bpp = 4; - break; + case ALPHA_8: + bpp = 1; + break; + case RGB_565: + case ARGB_4444: + bpp = 2; + break; + case ARGB_8888: + bpp = 4; + break; } } increment(b.getWidth() * b.getHeight() * bpp); @@ -1637,17 +1638,13 @@ public class RemoteViews implements Parcelable, Filter { mPackage = packageName; mLayoutId = layoutId; mBitmapCache = new BitmapCache(); + mApplication = ActivityThread.currentApplication().getApplicationInfo(); // setup the memory usage statistics mMemoryUsageCounter = new MemoryUsageCounter(); recalculateMemoryUsage(); } - /** {@hide} */ - public void setUser(UserHandle user) { - mUser = user; - } - private boolean hasLandscapeAndPortraitLayouts() { return (mLandscape != null) && (mPortrait != null); } @@ -1713,53 +1710,53 @@ public class RemoteViews implements Parcelable, Filter { for (int i=0; i<count; i++) { int tag = parcel.readInt(); switch (tag) { - case SetOnClickPendingIntent.TAG: - mActions.add(new SetOnClickPendingIntent(parcel)); - break; - case SetDrawableParameters.TAG: - mActions.add(new SetDrawableParameters(parcel)); - break; - case ReflectionAction.TAG: - mActions.add(new ReflectionAction(parcel)); - break; - case ViewGroupAction.TAG: - mActions.add(new ViewGroupAction(parcel, mBitmapCache)); - break; - case ReflectionActionWithoutParams.TAG: - mActions.add(new ReflectionActionWithoutParams(parcel)); - break; - case SetEmptyView.TAG: - mActions.add(new SetEmptyView(parcel)); - break; - case SetPendingIntentTemplate.TAG: - mActions.add(new SetPendingIntentTemplate(parcel)); - break; - case SetOnClickFillInIntent.TAG: - mActions.add(new SetOnClickFillInIntent(parcel)); - break; - case SetRemoteViewsAdapterIntent.TAG: - mActions.add(new SetRemoteViewsAdapterIntent(parcel)); - break; - case TextViewDrawableAction.TAG: - mActions.add(new TextViewDrawableAction(parcel)); - break; - case TextViewSizeAction.TAG: - mActions.add(new TextViewSizeAction(parcel)); - break; - case ViewPaddingAction.TAG: - mActions.add(new ViewPaddingAction(parcel)); - break; - case BitmapReflectionAction.TAG: - mActions.add(new BitmapReflectionAction(parcel)); - break; - case SetRemoteViewsAdapterList.TAG: - mActions.add(new SetRemoteViewsAdapterList(parcel)); - break; - case TextViewDrawableColorFilterAction.TAG: - mActions.add(new TextViewDrawableColorFilterAction(parcel)); - break; - default: - throw new ActionException("Tag " + tag + " not found"); + case SetOnClickPendingIntent.TAG: + mActions.add(new SetOnClickPendingIntent(parcel)); + break; + case SetDrawableParameters.TAG: + mActions.add(new SetDrawableParameters(parcel)); + break; + case ReflectionAction.TAG: + mActions.add(new ReflectionAction(parcel)); + break; + case ViewGroupAction.TAG: + mActions.add(new ViewGroupAction(parcel, mBitmapCache)); + break; + case ReflectionActionWithoutParams.TAG: + mActions.add(new ReflectionActionWithoutParams(parcel)); + break; + case SetEmptyView.TAG: + mActions.add(new SetEmptyView(parcel)); + break; + case SetPendingIntentTemplate.TAG: + mActions.add(new SetPendingIntentTemplate(parcel)); + break; + case SetOnClickFillInIntent.TAG: + mActions.add(new SetOnClickFillInIntent(parcel)); + break; + case SetRemoteViewsAdapterIntent.TAG: + mActions.add(new SetRemoteViewsAdapterIntent(parcel)); + break; + case TextViewDrawableAction.TAG: + mActions.add(new TextViewDrawableAction(parcel)); + break; + case TextViewSizeAction.TAG: + mActions.add(new TextViewSizeAction(parcel)); + break; + case ViewPaddingAction.TAG: + mActions.add(new ViewPaddingAction(parcel)); + break; + case BitmapReflectionAction.TAG: + mActions.add(new BitmapReflectionAction(parcel)); + break; + case SetRemoteViewsAdapterList.TAG: + mActions.add(new SetRemoteViewsAdapterList(parcel)); + break; + case TextViewDrawableColorFilterAction.TAG: + mActions.add(new TextViewDrawableColorFilterAction(parcel)); + break; + default: + throw new ActionException("Tag " + tag + " not found"); } } } @@ -1771,6 +1768,8 @@ public class RemoteViews implements Parcelable, Filter { mLayoutId = mPortrait.getLayoutId(); } + mApplication = parcel.readParcelable(null); + // setup the memory usage statistics mMemoryUsageCounter = new MemoryUsageCounter(); recalculateMemoryUsage(); @@ -2557,22 +2556,32 @@ public class RemoteViews implements Parcelable, Filter { } private Context prepareContext(Context context) { - Context c; - String packageName = mPackage; + if (mApplication != null) { + if (context.getUserId() == UserHandle.getUserId(mApplication.uid) + && context.getPackageName().equals(mApplication.packageName)) { + return context; + } + try { + return context.createApplicationContext(mApplication, + Context.CONTEXT_RESTRICTED); + } catch (NameNotFoundException e) { + Log.e(LOG_TAG, "Package name " + mPackage + " not found"); + } + } - if (packageName != null) { + if (mPackage != null) { + if (context.getPackageName().equals(mPackage)) { + return context; + } try { - c = context.createPackageContextAsUser( - packageName, Context.CONTEXT_RESTRICTED, mUser); + return context.createPackageContext( + mPackage, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { - Log.e(LOG_TAG, "Package name " + packageName + " not found"); - c = context; + Log.e(LOG_TAG, "Package name " + mPackage + " not found"); } - } else { - c = context; } - return c; + return context; } /** @@ -2629,6 +2638,8 @@ public class RemoteViews implements Parcelable, Filter { mLandscape.writeToParcel(dest, flags); mPortrait.writeToParcel(dest, flags); } + + dest.writeParcelable(mApplication, 0); } /** diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index bbe6f9e..5d21e0b 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -114,8 +114,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback // construction (happens when we have a cached FixedSizeRemoteViewsCache). private boolean mDataReady = false; - int mUserId; - /** * An interface for the RemoteAdapter to notify other classes when adapters * are actually connected to/disconnected from their actual services. @@ -159,9 +157,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback RemoteViewsAdapter adapter; final AppWidgetManager mgr = AppWidgetManager.getInstance(context); if ((adapter = mAdapter.get()) != null) { - checkInteractAcrossUsersPermission(context, adapter.mUserId); - mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(), - new UserHandle(adapter.mUserId)); + mgr.bindRemoteViewsService(context.getPackageName(), appWidgetId, + intent, asBinder()); } else { Slog.w(TAG, "bind: adapter was null"); } @@ -179,9 +176,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback RemoteViewsAdapter adapter; final AppWidgetManager mgr = AppWidgetManager.getInstance(context); if ((adapter = mAdapter.get()) != null) { - checkInteractAcrossUsersPermission(context, adapter.mUserId); - mgr.unbindRemoteViewsService(appWidgetId, intent, - new UserHandle(adapter.mUserId)); + mgr.unbindRemoteViewsService(context.getPackageName(), appWidgetId, intent); } else { Slog.w(TAG, "unbind: adapter was null"); } @@ -796,12 +791,10 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback static class RemoteViewsCacheKey { final Intent.FilterComparison filter; final int widgetId; - final int userId; - RemoteViewsCacheKey(Intent.FilterComparison filter, int widgetId, int userId) { + RemoteViewsCacheKey(Intent.FilterComparison filter, int widgetId) { this.filter = filter; this.widgetId = widgetId; - this.userId = userId; } @Override @@ -810,29 +803,28 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback return false; } RemoteViewsCacheKey other = (RemoteViewsCacheKey) o; - return other.filter.equals(filter) && other.widgetId == widgetId - && other.userId == userId; + return other.filter.equals(filter) && other.widgetId == widgetId; } @Override public int hashCode() { - return (filter == null ? 0 : filter.hashCode()) ^ (widgetId << 2) ^ (userId << 10); + return (filter == null ? 0 : filter.hashCode()) ^ (widgetId << 2); } } - public RemoteViewsAdapter(Context context, Intent intent, RemoteAdapterConnectionCallback callback) { + public RemoteViewsAdapter(Context context, Intent intent, + RemoteAdapterConnectionCallback callback) { mContext = context; mIntent = intent; + mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1); + mLayoutInflater = LayoutInflater.from(context); if (mIntent == null) { throw new IllegalArgumentException("Non-null Intent must be specified."); } mRequestedViews = new RemoteViewsFrameLayoutRefSet(); - checkInteractAcrossUsersPermission(context, UserHandle.myUserId()); - mUserId = context.getUserId(); - // Strip the previously injected app widget id from service intent if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) { intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID); @@ -855,7 +847,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback mServiceConnection = new RemoteViewsAdapterServiceConnection(this); RemoteViewsCacheKey key = new RemoteViewsCacheKey(new Intent.FilterComparison(mIntent), - mAppWidgetId, mUserId); + mAppWidgetId); synchronized(sCachedRemoteViewsCaches) { if (sCachedRemoteViewsCaches.containsKey(key)) { @@ -876,15 +868,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback } } - private static void checkInteractAcrossUsersPermission(Context context, int userId) { - if (context.getUserId() != userId - && context.checkCallingOrSelfPermission(MULTI_USER_PERM) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Must have permission " + MULTI_USER_PERM - + " to inflate another user's widget"); - } - } - @Override protected void finalize() throws Throwable { try { @@ -906,7 +889,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback public void saveRemoteViewsCache() { final RemoteViewsCacheKey key = new RemoteViewsCacheKey( - new Intent.FilterComparison(mIntent), mAppWidgetId, mUserId); + new Intent.FilterComparison(mIntent), mAppWidgetId); synchronized(sCachedRemoteViewsCaches) { // If we already have a remove runnable posted for this key, remove it. @@ -1028,7 +1011,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback long itemId = 0; try { remoteViews = factory.getViewAt(position); - remoteViews.setUser(new UserHandle(mUserId)); itemId = factory.getItemId(position); } catch (RemoteException e) { Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + e.getMessage()); diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java index b152297..cf1f554 100644 --- a/core/java/android/widget/ViewFlipper.java +++ b/core/java/android/widget/ViewFlipper.java @@ -21,8 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.TypedArray; -import android.os.Handler; -import android.os.Message; +import android.os.*; import android.util.AttributeSet; import android.util.Log; import android.view.accessibility.AccessibilityEvent; @@ -90,7 +89,16 @@ public class ViewFlipper extends ViewAnimator { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); - getContext().registerReceiver(mReceiver, filter, null, mHandler); + + // OK, this is gross but needed. This class is supported by the + // remote views machanism and as a part of that the remote views + // can be inflated by a context for another user without the app + // having interact users permission - just for loading resources. + // For exmaple, when adding widgets from a user profile to the + // home screen. Therefore, we register the receiver as the current + // user not the one the context is for. + getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(), + filter, null, mHandler); if (mAutoStart) { // Automatically start when requested |