am 580ee8b0: Merge "Fixing AppWidgetService / AppWidgetHost to work in system process" into jb-mr1-dev
* commit '580ee8b0c6e1aea1e2e1d60499b603b9168b44f0': Fixing AppWidgetService / AppWidgetHost to work in system process
This commit is contained in:
@@ -4476,6 +4476,7 @@ package android.appwidget {
|
|||||||
public class AppWidgetProviderInfo implements android.os.Parcelable {
|
public class AppWidgetProviderInfo implements android.os.Parcelable {
|
||||||
ctor public AppWidgetProviderInfo();
|
ctor public AppWidgetProviderInfo();
|
||||||
ctor public AppWidgetProviderInfo(android.os.Parcel);
|
ctor public AppWidgetProviderInfo(android.os.Parcel);
|
||||||
|
method public android.appwidget.AppWidgetProviderInfo clone();
|
||||||
method public int describeContents();
|
method public int describeContents();
|
||||||
method public void writeToParcel(android.os.Parcel, int);
|
method public void writeToParcel(android.os.Parcel, int);
|
||||||
field public static final android.os.Parcelable.Creator CREATOR;
|
field public static final android.os.Parcelable.Creator CREATOR;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -57,6 +58,9 @@ public class AppWidgetHost {
|
|||||||
|
|
||||||
class Callbacks extends IAppWidgetHost.Stub {
|
class Callbacks extends IAppWidgetHost.Stub {
|
||||||
public void updateAppWidget(int appWidgetId, RemoteViews views) {
|
public void updateAppWidget(int appWidgetId, RemoteViews views) {
|
||||||
|
if (isLocalBinder() && views != null) {
|
||||||
|
views = views.clone();
|
||||||
|
}
|
||||||
Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
|
Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
|
||||||
msg.arg1 = appWidgetId;
|
msg.arg1 = appWidgetId;
|
||||||
msg.obj = views;
|
msg.obj = views;
|
||||||
@@ -64,6 +68,9 @@ public class AppWidgetHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) {
|
public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) {
|
||||||
|
if (isLocalBinder() && info != null) {
|
||||||
|
info = info.clone();
|
||||||
|
}
|
||||||
Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
|
Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
|
||||||
msg.arg1 = appWidgetId;
|
msg.arg1 = appWidgetId;
|
||||||
msg.obj = info;
|
msg.obj = info;
|
||||||
@@ -225,6 +232,10 @@ public class AppWidgetHost {
|
|||||||
throw new SecurityException("Disallowed call for uid " + uid);
|
throw new SecurityException("Disallowed call for uid " + uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isLocalBinder() {
|
||||||
|
return Process.myPid() == Binder.getCallingPid();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop listening to changes for this AppWidget.
|
* Stop listening to changes for this AppWidget.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -281,6 +281,28 @@ public class AppWidgetProviderInfo implements Parcelable {
|
|||||||
out.writeInt(this.widgetFeatures);
|
out.writeInt(this.widgetFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppWidgetProviderInfo clone() {
|
||||||
|
AppWidgetProviderInfo that = new AppWidgetProviderInfo();
|
||||||
|
that.provider = this.provider == null ? null : this.provider.clone();
|
||||||
|
that.minWidth = this.minWidth;
|
||||||
|
that.minHeight = this.minHeight;
|
||||||
|
that.minResizeWidth = this.minResizeHeight;
|
||||||
|
that.minResizeHeight = this.minResizeHeight;
|
||||||
|
that.updatePeriodMillis = this.updatePeriodMillis;
|
||||||
|
that.initialLayout = that.initialLayout;
|
||||||
|
that.initialKeyguardLayout = this.initialKeyguardLayout;
|
||||||
|
that.configure = this.configure == null ? null : this.configure.clone();
|
||||||
|
that.label = this.label == null ? null : this.label.substring(0);
|
||||||
|
that.icon = this.icon;
|
||||||
|
that.previewImage = this.previewImage;
|
||||||
|
that.autoAdvanceViewId = this.autoAdvanceViewId;
|
||||||
|
that.resizeMode = this.resizeMode;
|
||||||
|
that.widgetCategory = this.widgetCategory;
|
||||||
|
that.widgetFeatures = this.widgetFeatures;
|
||||||
|
return that;
|
||||||
|
}
|
||||||
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,12 +237,11 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void mergeRemoteViews(RemoteViews newRv) {
|
public void mergeRemoteViews(RemoteViews newRv) {
|
||||||
|
if (newRv == null) return;
|
||||||
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
|
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
|
||||||
// reference the bitmap cache. We don't want to modify the object as it may need to
|
// reference the bitmap cache. We don't want to modify the object as it may need to
|
||||||
// be merged and applied multiple times.
|
// be merged and applied multiple times.
|
||||||
Parcel p = Parcel.obtain();
|
RemoteViews copy = newRv.clone();
|
||||||
newRv.writeToParcel(p, 0);
|
|
||||||
RemoteViews copy = new RemoteViews(p);
|
|
||||||
|
|
||||||
HashMap<String, Action> map = new HashMap<String, Action>();
|
HashMap<String, Action> map = new HashMap<String, Action>();
|
||||||
if (mActions == null) {
|
if (mActions == null) {
|
||||||
@@ -261,7 +260,7 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
Action a = newActions.get(i);
|
Action a = newActions.get(i);
|
||||||
String key = newActions.get(i).getUniqueKey();
|
String key = newActions.get(i).getUniqueKey();
|
||||||
int mergeBehavior = map.get(key).mergeBehavior();
|
int mergeBehavior = newActions.get(i).mergeBehavior();
|
||||||
if (map.containsKey(key) && mergeBehavior == Action.MERGE_REPLACE) {
|
if (map.containsKey(key) && mergeBehavior == Action.MERGE_REPLACE) {
|
||||||
mActions.remove(map.get(key));
|
mActions.remove(map.get(key));
|
||||||
map.remove(key);
|
map.remove(key);
|
||||||
@@ -1581,23 +1580,12 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
recalculateMemoryUsage();
|
recalculateMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RemoteViews clone() {
|
|
||||||
RemoteViews that;
|
|
||||||
if (!hasLandscapeAndPortraitLayouts()) {
|
|
||||||
that = new RemoteViews(mPackage, mLayoutId);
|
|
||||||
|
|
||||||
if (mActions != null) {
|
public RemoteViews clone() {
|
||||||
that.mActions = (ArrayList<Action>)mActions.clone();
|
Parcel p = Parcel.obtain();
|
||||||
}
|
writeToParcel(p, 0);
|
||||||
} else {
|
p.setDataPosition(0);
|
||||||
RemoteViews land = mLandscape.clone();
|
return new RemoteViews(p);
|
||||||
RemoteViews port = mPortrait.clone();
|
|
||||||
that = new RemoteViews(land, port);
|
|
||||||
}
|
|
||||||
// update the memory usage stats of the cloned RemoteViews
|
|
||||||
that.recalculateMemoryUsage();
|
|
||||||
return that;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackage() {
|
public String getPackage() {
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ class AppWidgetServiceImpl {
|
|||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (mAppWidgetIds) {
|
synchronized (mAppWidgetIds) {
|
||||||
|
options = cloneIfLocalBinder(options);
|
||||||
ensureStateLoadedLocked();
|
ensureStateLoadedLocked();
|
||||||
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
@@ -817,7 +818,7 @@ class AppWidgetServiceImpl {
|
|||||||
ensureStateLoadedLocked();
|
ensureStateLoadedLocked();
|
||||||
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
||||||
if (id != null && id.provider != null && !id.provider.zombie) {
|
if (id != null && id.provider != null && !id.provider.zombie) {
|
||||||
return id.provider.info;
|
return cloneIfLocalBinder(id.provider.info);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -828,7 +829,7 @@ class AppWidgetServiceImpl {
|
|||||||
ensureStateLoadedLocked();
|
ensureStateLoadedLocked();
|
||||||
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
return id.views;
|
return cloneIfLocalBinder(id.views);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -842,7 +843,7 @@ class AppWidgetServiceImpl {
|
|||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
Provider p = mInstalledProviders.get(i);
|
Provider p = mInstalledProviders.get(i);
|
||||||
if (!p.zombie) {
|
if (!p.zombie) {
|
||||||
result.add(p.info);
|
result.add(cloneIfLocalBinder(p.info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -881,6 +882,7 @@ class AppWidgetServiceImpl {
|
|||||||
|
|
||||||
public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
|
public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
|
||||||
synchronized (mAppWidgetIds) {
|
synchronized (mAppWidgetIds) {
|
||||||
|
options = cloneIfLocalBinder(options);
|
||||||
ensureStateLoadedLocked();
|
ensureStateLoadedLocked();
|
||||||
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
||||||
|
|
||||||
@@ -907,7 +909,7 @@ class AppWidgetServiceImpl {
|
|||||||
ensureStateLoadedLocked();
|
ensureStateLoadedLocked();
|
||||||
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
|
||||||
if (id != null && id.options != null) {
|
if (id != null && id.options != null) {
|
||||||
return id.options;
|
return cloneIfLocalBinder(id.options);
|
||||||
} else {
|
} else {
|
||||||
return Bundle.EMPTY;
|
return Bundle.EMPTY;
|
||||||
}
|
}
|
||||||
@@ -1062,6 +1064,34 @@ class AppWidgetServiceImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isLocalBinder() {
|
||||||
|
return Process.myPid() == Binder.getCallingPid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RemoteViews cloneIfLocalBinder(RemoteViews rv) {
|
||||||
|
if (isLocalBinder() && rv != null) {
|
||||||
|
return rv.clone();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppWidgetProviderInfo cloneIfLocalBinder(AppWidgetProviderInfo info) {
|
||||||
|
if (isLocalBinder() && info != null) {
|
||||||
|
return info.clone();
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bundle cloneIfLocalBinder(Bundle bundle) {
|
||||||
|
// Note: this is only a shallow copy. For now this will be fine, but it could be problematic
|
||||||
|
// if we start adding objects to the options. Further, it would only be an issue if keyguard
|
||||||
|
// used such options.
|
||||||
|
if (isLocalBinder() && bundle != null) {
|
||||||
|
return (Bundle) bundle.clone();
|
||||||
|
}
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
|
public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId,
|
||||||
List<RemoteViews> updatedViews) {
|
List<RemoteViews> updatedViews) {
|
||||||
int callingUid = enforceCallingUid(packageName);
|
int callingUid = enforceCallingUid(packageName);
|
||||||
@@ -1078,7 +1108,7 @@ class AppWidgetServiceImpl {
|
|||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
AppWidgetId id = instances.get(i);
|
AppWidgetId id = instances.get(i);
|
||||||
updatedIds[i] = id.appWidgetId;
|
updatedIds[i] = id.appWidgetId;
|
||||||
updatedViews.add(id.views);
|
updatedViews.add(cloneIfLocalBinder(id.views));
|
||||||
}
|
}
|
||||||
return updatedIds;
|
return updatedIds;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user