diff options
| author | 2014-08-06 14:11:37 -0700 | |
|---|---|---|
| committer | 2014-08-07 00:30:44 +0000 | |
| commit | 0da85b6c9073956b620c6a88b44027e9ee80066c (patch) | |
| tree | 95989c7e6920028752fdcf03b63da5003fce19f7 | |
| parent | 5557e65b2076c7214c5ef8942f3a7fd8bc4bb6d0 (diff) | |
Fix regression in remote views.
Now remote views contain the application info for the app on whose
behalf they should show content. The application info contains the
user id and the package name which makes it unique in the multi
user environment. If the app which creates the remote views does
not have the same package as the one passed in the contructor of
the remote views, we lookup the app info for the target package.
There is a special hidden overload that allows creating a remote
views instance that represents an app in given package and user
(requires interact across users) permission. The latter is used
by SystemUi when creating remote views for apps that posted a
notification.
bug:16838651
Change-Id: I2daa974629f89a2446848e59300d994dadcf4439
| -rw-r--r-- | core/java/android/app/Notification.java | 7 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViews.java | 89 |
2 files changed, 61 insertions, 35 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 5b36b8bd74fb..5684a7a0966b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2577,7 +2577,8 @@ public class Notification implements Parcelable private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) { Bitmap profileIcon = getProfileBadge(); - RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(), resId); + RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(), + mOriginatingUserId, resId); boolean showLine3 = false; boolean showLine2 = false; @@ -4576,8 +4577,8 @@ public class Notification implements Parcelable super(parcel); } - public BuilderRemoteViews(String packageName, int layoutId) { - super(packageName, layoutId); + public BuilderRemoteViews(String packageName, int userId, int layoutId) { + super(packageName, userId, layoutId); } @Override diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 1098fa23db37..8aef304872e9 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -18,6 +18,7 @@ package android.widget; import android.app.ActivityOptions; import android.app.ActivityThread; +import android.app.Application; import android.app.PendingIntent; import android.appwidget.AppWidgetHostView; import android.content.Context; @@ -81,12 +82,6 @@ public class RemoteViews implements Parcelable, Filter { private ApplicationInfo mApplication; /** - * The package name of the package containing the layout - * resource. (Added to the parcel) - */ - private final String mPackage; - - /** * The resource ID of the layout file. (Added to the parcel) */ private final int mLayoutId; @@ -1635,11 +1630,34 @@ public class RemoteViews implements Parcelable, Filter { * @param layoutId The id of the layout resource */ public RemoteViews(String packageName, int layoutId) { - mPackage = packageName; + this(getApplicationInfo(packageName, UserHandle.myUserId()), layoutId); + } + + /** + * Create a new RemoteViews object that will display the views contained + * in the specified layout file. + * + * @param packageName Name of the package that contains the layout resource. + * @param userId The user under which the package is running. + * @param layoutId The id of the layout resource. + * + * @hide + */ + public RemoteViews(String packageName, int userId, int layoutId) { + this(getApplicationInfo(packageName, userId), layoutId); + } + + /** + * Create a new RemoteViews object that will display the views contained + * in the specified layout file. + * + * @param application The application whose content is shown by the views. + * @param layoutId The id of the layout resource. + */ + private RemoteViews(ApplicationInfo application, int layoutId) { + mApplication = application; mLayoutId = layoutId; mBitmapCache = new BitmapCache(); - mApplication = ActivityThread.currentApplication().getApplicationInfo(); - // setup the memory usage statistics mMemoryUsageCounter = new MemoryUsageCounter(); recalculateMemoryUsage(); @@ -1660,10 +1678,11 @@ public class RemoteViews implements Parcelable, Filter { if (landscape == null || portrait == null) { throw new RuntimeException("Both RemoteViews must be non-null"); } - if (landscape.getPackage().compareTo(portrait.getPackage()) != 0) { - throw new RuntimeException("Both RemoteViews must share the same package"); + if (landscape.mApplication.uid != portrait.mApplication.uid + || !landscape.mApplication.packageName.equals(portrait.mApplication.packageName)) { + throw new RuntimeException("Both RemoteViews must share the same package and user"); } - mPackage = portrait.getPackage(); + mApplication = portrait.mApplication; mLayoutId = portrait.getLayoutId(); mLandscape = landscape; @@ -1700,7 +1719,7 @@ public class RemoteViews implements Parcelable, Filter { } if (mode == MODE_NORMAL) { - mPackage = parcel.readString(); + mApplication = parcel.readParcelable(null); mLayoutId = parcel.readInt(); mIsWidgetCollectionChild = parcel.readInt() == 1; @@ -1764,12 +1783,10 @@ public class RemoteViews implements Parcelable, Filter { // MODE_HAS_LANDSCAPE_AND_PORTRAIT mLandscape = new RemoteViews(parcel, mBitmapCache); mPortrait = new RemoteViews(parcel, mBitmapCache); - mPackage = mPortrait.getPackage(); + mApplication = mPortrait.mApplication; mLayoutId = mPortrait.getLayoutId(); } - mApplication = parcel.readParcelable(null); - // setup the memory usage statistics mMemoryUsageCounter = new MemoryUsageCounter(); recalculateMemoryUsage(); @@ -1786,7 +1803,7 @@ public class RemoteViews implements Parcelable, Filter { } public String getPackage() { - return mPackage; + return mApplication.packageName; } /** @@ -2565,19 +2582,7 @@ public class RemoteViews implements Parcelable, Filter { return context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { - Log.e(LOG_TAG, "Package name " + mPackage + " not found"); - } - } - - if (mPackage != null) { - if (context.getPackageName().equals(mPackage)) { - return context; - } - try { - return context.createPackageContext( - mPackage, Context.CONTEXT_RESTRICTED); - } catch (NameNotFoundException e) { - Log.e(LOG_TAG, "Package name " + mPackage + " not found"); + Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found"); } } @@ -2614,7 +2619,7 @@ public class RemoteViews implements Parcelable, Filter { if (mIsRoot) { mBitmapCache.writeBitmapsToParcel(dest, flags); } - dest.writeString(mPackage); + dest.writeParcelable(mApplication, flags); dest.writeInt(mLayoutId); dest.writeInt(mIsWidgetCollectionChild ? 1 : 0); int count; @@ -2638,8 +2643,28 @@ public class RemoteViews implements Parcelable, Filter { mLandscape.writeToParcel(dest, flags); mPortrait.writeToParcel(dest, flags); } + } + + private static ApplicationInfo getApplicationInfo(String packageName, int userId) { + // Get the application for the passed in package and user. + Application application = ActivityThread.currentApplication(); + if (application == null) { + throw new IllegalStateException("Cannot create remote views out of an aplication."); + } + + ApplicationInfo applicationInfo = application.getApplicationInfo(); + if (UserHandle.getUserId(applicationInfo.uid) != userId + || !applicationInfo.packageName.equals(packageName)) { + try { + Context context = application.getApplicationContext().createPackageContextAsUser( + packageName, 0, new UserHandle(userId)); + applicationInfo = context.getApplicationInfo(); + } catch (NameNotFoundException nnfe) { + throw new IllegalArgumentException("No such package " + packageName); + } + } - dest.writeParcelable(mApplication, 0); + return applicationInfo; } /** |