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;
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.
*
= "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.
private int mColor = COLOR_DEFAULT;
/**
- * The user that built the notification originally.
- */
- private int mOriginatingUserId;
-
- /**
* Contains extras related to rebuilding during the build phase.
*/
private Bundle mRebuildBundle = new Bundle();
// 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() {
* @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);
*/
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);
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
}
// 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);
* object.
*/
public Notification build() {
- mOriginatingUserId = mContext.getUserId();
mHasThreeLines = hasThreeLines();
Notification n = buildUnstyled();
super(parcel);
}
- public BuilderRemoteViews(String packageName, int userId, int layoutId) {
- super(packageName, userId, layoutId);
+ public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) {
+ super(appInfo, layoutId);
}
@Override
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;
*
* @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();
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);
}
}
- prepareContext(context);
rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
}
}
}
- 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)) {