summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/widget')
-rw-r--r--core/java/android/widget/AnalogClock.java10
-rw-r--r--core/java/android/widget/RemoteViews.java167
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java42
-rw-r--r--core/java/android/widget/ViewFlipper.java14
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