summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2009-08-06 21:24:25 -0700
committerJeff Sharkey <jsharkey@android.com>2009-08-06 21:53:56 -0700
commitb8560b66fd2bdf465a8c7fad983f2236778e8106 (patch)
tree496f26bad3dd80cb0f83d0143f6b37a344af5e32
parent3397f16949d2e86442c32f3b82d5ee3ace99ba82 (diff)
downloadframeworks_base-b8560b66fd2bdf465a8c7fad983f2236778e8106.zip
frameworks_base-b8560b66fd2bdf465a8c7fad983f2236778e8106.tar.gz
frameworks_base-b8560b66fd2bdf465a8c7fad983f2236778e8106.tar.bz2
Fix AppWidget layout inflation to resolve references.
When RemoteViews inflates a layout and set of actions, it uses a cloned remote Context so it can fully access the resources needed to complete the inflate. However, in one specific case when inflating the root view, LayoutInflater calls back to the soon-to-be parent view to request the correct set of LayoutParams through generateLayoutParams(). The default implementation of generateLayoutParams() uses the Context of the /local/ View instead of the remote Context being used for the inflation, which means that any LayoutParam references in the root view are unresolved. To fix this, we internally create our own copy of the target remote Context. This way, when the remote LayoutInflater calls generateLayoutParams(), we inflate it using the remote Context to correctly resolve any references. This change is required as part of http://b/2038594
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java49
1 files changed, 41 insertions, 8 deletions
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 62d9267..9799ac4 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -18,11 +18,13 @@ package android.appwidget;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.SystemClock;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -31,6 +33,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
+import android.widget.FrameLayout.LayoutParams;
/**
* Provides the glue to show AppWidget views. This class offers automatic animation
@@ -58,7 +61,8 @@ public class AppWidgetHostView extends FrameLayout {
};
Context mContext;
-
+ Context mRemoteContext;
+
int mAppWidgetId;
AppWidgetProviderInfo mInfo;
View mView;
@@ -104,6 +108,16 @@ public class AppWidgetHostView extends FrameLayout {
return mInfo;
}
+ /** {@inheritDoc} */
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ // We're being asked to inflate parameters, probably by a LayoutInflater
+ // in a remote Context. To help resolve any remote references, we
+ // inflate through our last mRemoteContext when it exists.
+ final Context context = mRemoteContext != null ? mRemoteContext : mContext;
+ return new FrameLayout.LayoutParams(context, attrs);
+ }
+
/**
* Process a set of {@link RemoteViews} coming in as an update from the
* AppWidget provider. Will animate into these new views as needed.
@@ -143,6 +157,9 @@ public class AppWidgetHostView extends FrameLayout {
mLayoutId = -1;
mViewMode = VIEW_MODE_DEFAULT;
} else {
+ // Prepare a local reference to the remote Context so we're ready to
+ // inflate any requested LayoutParams.
+ mRemoteContext = getRemoteContext(remoteViews);
int layoutId = remoteViews.getLayoutId();
// If our stale view has been prepared to match active, and the new
@@ -203,6 +220,24 @@ public class AppWidgetHostView extends FrameLayout {
}
}
+ /**
+ * Build a {@link Context} cloned into another package name, usually for the
+ * purposes of reading remote resources.
+ */
+ private Context getRemoteContext(RemoteViews views) {
+ // Bail if missing package name
+ final String packageName = views.getPackage();
+ if (packageName == null) return mContext;
+
+ try {
+ // Return if cloned successfully, otherwise default
+ return mContext.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Package name " + packageName + " not found");
+ return mContext;
+ }
+ }
+
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (CROSSFADE) {
int alpha;
@@ -246,17 +281,15 @@ public class AppWidgetHostView extends FrameLayout {
* {@link FrameLayout.LayoutParams} before inserting.
*/
protected void prepareView(View view) {
- // Take requested dimensions from parent, but apply default gravity.
- ViewGroup.LayoutParams requested = view.getLayoutParams();
+ // Take requested dimensions from child, but apply default gravity.
+ FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams();
if (requested == null) {
requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
}
-
- FrameLayout.LayoutParams params =
- new FrameLayout.LayoutParams(requested.width, requested.height);
- params.gravity = Gravity.CENTER;
- view.setLayoutParams(params);
+
+ requested.gravity = Gravity.CENTER;
+ view.setLayoutParams(requested);
}
/**