diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 5921477eb8933..f8dfdd9d9925b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -21,6 +21,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -823,13 +824,6 @@ public class Notification implements Parcelable */ public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions"; - /** - * {@link #extras} key: the user that built the notification. - * - * @hide - */ - public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId"; - /** * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be * displayed in the heads up space. @@ -1813,10 +1807,12 @@ public class Notification implements Parcelable = "android.rebuild.hudViewActionCount"; /** - * The package name of the context used to create the notification via a Builder. + * The ApplicationInfo of the package that created the notification, used to create + * a context to rebuild the notification via a Builder. + * @hide */ - private static final String EXTRA_REBUILD_CONTEXT_PACKAGE = - "android.rebuild.contextPackage"; + private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO = + "android.rebuild.applicationInfo"; // Whether to enable stripping (at post time) & rebuilding (at listener receive time) of // memory intensive resources. @@ -1866,11 +1862,6 @@ public class Notification implements Parcelable private ArrayList mPeople; private int mColor = COLOR_DEFAULT; - /** - * The user that built the notification originally. - */ - private int mOriginatingUserId; - /** * Contains extras related to rebuilding during the build phase. */ @@ -2591,7 +2582,7 @@ public class Notification implements Parcelable // Note: This assumes that the current user can read the profile badge of the // originating user. UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0); + return userManager.getBadgeForUser(new UserHandle(mContext.getUserId()), 0); } private Bitmap getProfileBadge() { @@ -2670,8 +2661,7 @@ public class Notification implements Parcelable * @param hasProgress whether the progress bar should be shown and set */ private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) { - RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(), - mOriginatingUserId, resId); + RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId); resetStandardTemplate(contentView); @@ -3063,8 +3053,8 @@ public class Notification implements Parcelable */ public void populateExtras(Bundle extras) { // Store original information used in the construction of this object - extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId); - extras.putString(EXTRA_REBUILD_CONTEXT_PACKAGE, mContext.getPackageName()); + extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO, + mContext.getApplicationInfo()); extras.putCharSequence(EXTRA_TITLE, mContentTitle); extras.putCharSequence(EXTRA_TEXT, mContentText); extras.putCharSequence(EXTRA_SUB_TEXT, mSubText); @@ -3152,13 +3142,14 @@ public class Notification implements Parcelable extras.remove(EXTRA_NEEDS_REBUILD); // Re-create notification context so we can access app resources. - String packageName = extras.getString(EXTRA_REBUILD_CONTEXT_PACKAGE); + ApplicationInfo applicationInfo = extras.getParcelable( + EXTRA_REBUILD_CONTEXT_APPLICATION_INFO); Context builderContext; try { - builderContext = context.createPackageContext(packageName, + builderContext = context.createApplicationContext(applicationInfo, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { - Log.e(TAG, "Package name " + packageName + " not found"); + Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found"); builderContext = context; // try with our context } @@ -3293,7 +3284,6 @@ public class Notification implements Parcelable // Extras. Bundle extras = n.extras; - mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID); mContentTitle = extras.getCharSequence(EXTRA_TITLE); mContentText = extras.getCharSequence(EXTRA_TEXT); mSubText = extras.getCharSequence(EXTRA_SUB_TEXT); @@ -3326,7 +3316,6 @@ public class Notification implements Parcelable * object. */ public Notification build() { - mOriginatingUserId = mContext.getUserId(); mHasThreeLines = hasThreeLines(); Notification n = buildUnstyled(); @@ -4826,8 +4815,8 @@ public class Notification implements Parcelable super(parcel); } - public BuilderRemoteViews(String packageName, int userId, int layoutId) { - super(packageName, userId, layoutId); + public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) { + super(appInfo, layoutId); } @Override diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 69d5f40802ccd..90e9c69913e9b 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -22,11 +22,13 @@ import android.app.Application; import android.app.PendingIntent; import android.appwidget.AppWidgetHostView; import android.content.Context; +import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.Rect; @@ -1653,8 +1655,10 @@ public class RemoteViews implements Parcelable, Filter { * * @param application The application whose content is shown by the views. * @param layoutId The id of the layout resource. + * + * @hide */ - private RemoteViews(ApplicationInfo application, int layoutId) { + protected RemoteViews(ApplicationInfo application, int layoutId) { mApplication = application; mLayoutId = layoutId; mBitmapCache = new BitmapCache(); @@ -2515,15 +2519,29 @@ public class RemoteViews implements Parcelable, Filter { RemoteViews rvToApply = getRemoteViewsToApply(context); View result; - - Context c = prepareContext(context); + // RemoteViews may be built by an application installed in another + // user. So build a context that loads resources from that user but + // still returns the current users userId so settings like data / time formats + // are loaded without requiring cross user persmissions. + final Context contextForResources = getContextForResources(context); + Context inflationContext = new ContextWrapper(context) { + @Override + public Resources getResources() { + return contextForResources.getResources(); + } + @Override + public Resources.Theme getTheme() { + return contextForResources.getTheme(); + } + }; LayoutInflater inflater = (LayoutInflater) - c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater = inflater.cloneInContext(c); + // Clone inflater so we load resources from correct context and + // we don't add a filter to the static version returned by getSystemService. + inflater = inflater.cloneInContext(inflationContext); inflater.setFilter(this); - result = inflater.inflate(rvToApply.getLayoutId(), parent, false); rvToApply.performApply(result, parent, handler); @@ -2557,7 +2575,6 @@ public class RemoteViews implements Parcelable, Filter { } } - prepareContext(context); rvToApply.performApply(v, (ViewGroup) v.getParent(), handler); } @@ -2572,7 +2589,7 @@ public class RemoteViews implements Parcelable, Filter { } } - private Context prepareContext(Context context) { + private Context getContextForResources(Context context) { if (mApplication != null) { if (context.getUserId() == UserHandle.getUserId(mApplication.uid) && context.getPackageName().equals(mApplication.packageName)) {