summaryrefslogtreecommitdiff
path: root/core/java/android/widget/RemoteViewsAdapter.java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-11-30 15:26:21 -0800
committerAmith Yamasani <yamasani@google.com>2012-11-30 17:28:08 -0800
commitc566b43d02596cba437e9a2723e9f989297cca72 (patch)
tree47afa340bf7f23fcb8d643ea9d51525e715c9878 /core/java/android/widget/RemoteViewsAdapter.java
parent20b76b9fff076241fe305fc99be3be7ab7d10407 (diff)
Fix crosstalk between users for widgets hosted in lockscreen
This was initially about the Clock widget crashing repeatedly on some devices with multiple users. Turned out that there were race conditions when switching users that could result in remote views of one user calling back to the RemoteViewsAdapter in keyguard that in turn sent an incorrect widget id to a different user's widget, resulting in a crash. Since KeyguardHostView is instantiated in the same process for different users, it needs to carry a user identity to pass along to AppWidgetService so that remote views services were bound to the correct user and callbacks were attached and detached properly. Added some aidl calls that take the userId to do the binding properly. A more complete fix might be needed in the future so that all calls from Keyguard carry the user id. Also, there was a problem in comparing host uid for secondary users, since Settings for a secondary user has a different uid than keyguard. Not an issue on single-user systems. Changed the host.uid comparison to accomodate for the secondary user. Bug: 7450247 Change-Id: Idbc36e3c60023cac74174f6cb7f2b2130dd3052c
Diffstat (limited to 'core/java/android/widget/RemoteViewsAdapter.java')
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java30
1 files changed, 28 insertions, 2 deletions
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e4817025c347..c122bb29b9f9 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -29,7 +29,9 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -40,6 +42,7 @@ import android.widget.RemoteViews.OnClickHandler;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;
+import com.android.internal.widget.LockPatternUtils;
/**
* An adapter to a RemoteViewsService which fetches and caches RemoteViews
@@ -106,6 +109,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
// construction (happens when we have a cached FixedSizeRemoteViewsCache).
private boolean mDataReady = false;
+ int mUserId;
+
/**
* An interface for the RemoteAdapter to notify other classes when adapters
* are actually connected to/disconnected from their actual services.
@@ -146,8 +151,16 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public synchronized void bind(Context context, int appWidgetId, Intent intent) {
if (!mIsConnecting) {
try {
+ RemoteViewsAdapter adapter;
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
- mgr.bindRemoteViewsService(appWidgetId, intent, asBinder());
+ if (Process.myUid() == Process.SYSTEM_UID
+ && (adapter = mAdapter.get()) != null) {
+ mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+ new UserHandle(adapter.mUserId));
+ } else {
+ mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+ Process.myUserHandle());
+ }
mIsConnecting = true;
} catch (Exception e) {
Log.e("RemoteViewsAdapterServiceConnection", "bind(): " + e.getMessage());
@@ -159,8 +172,15 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public synchronized void unbind(Context context, int appWidgetId, Intent intent) {
try {
+ RemoteViewsAdapter adapter;
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
- mgr.unbindRemoteViewsService(appWidgetId, intent);
+ if (Process.myUid() == Process.SYSTEM_UID
+ && (adapter = mAdapter.get()) != null) {
+ mgr.unbindRemoteViewsService(appWidgetId, intent,
+ new UserHandle(adapter.mUserId));
+ } else {
+ mgr.unbindRemoteViewsService(appWidgetId, intent, Process.myUserHandle());
+ }
mIsConnecting = false;
} catch (Exception e) {
Log.e("RemoteViewsAdapterServiceConnection", "unbind(): " + e.getMessage());
@@ -761,6 +781,12 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
}
mRequestedViews = new RemoteViewsFrameLayoutRefSet();
+ if (Process.myUid() == Process.SYSTEM_UID) {
+ mUserId = new LockPatternUtils(context).getCurrentUser();
+ } else {
+ mUserId = UserHandle.myUserId();
+ }
+
// Strip the previously injected app widget id from service intent
if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) {
intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID);