summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2013-02-21 00:00:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-02-21 00:00:49 +0000
commitab8e936e852b984624087c97dffc4c74b250fc68 (patch)
tree49e365cba1bd0fafb2dece3e3bd7393a65a71928
parentc94f06754a24f775072578d27eb08e4e55ddd93b (diff)
parenta75a883fe9ea1790803148f0a561473073e3f264 (diff)
downloadframeworks_base-ab8e936e852b984624087c97dffc4c74b250fc68.zip
frameworks_base-ab8e936e852b984624087c97dffc4c74b250fc68.tar.gz
frameworks_base-ab8e936e852b984624087c97dffc4c74b250fc68.tar.bz2
Merge "Add explicit userId to AppWidget binder calls"
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java145
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java43
-rw-r--r--core/java/android/content/Context.java8
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetHost.aidl8
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetService.aidl47
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java50
-rw-r--r--services/java/com/android/server/AppWidgetService.java157
-rw-r--r--services/java/com/android/server/AppWidgetServiceImpl.java9
-rw-r--r--test-runner/src/android/test/mock/MockContext.java6
10 files changed, 241 insertions, 238 deletions
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index fa3bf4d..a470e70 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -31,6 +31,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.TypedValue;
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
@@ -55,38 +56,39 @@ public class AppWidgetHost {
Context mContext;
String mPackageName;
+ Handler mHandler;
+ int mHostId;
+ Callbacks mCallbacks = new Callbacks();
+ final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
+ private OnClickHandler mOnClickHandler;
class Callbacks extends IAppWidgetHost.Stub {
- public void updateAppWidget(int appWidgetId, RemoteViews views) {
+ public void updateAppWidget(int appWidgetId, RemoteViews views, int userId) {
if (isLocalBinder() && views != null) {
views = views.clone();
- views.setUser(mUser);
+ views.setUser(new UserHandle(userId));
}
- Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
- msg.arg1 = appWidgetId;
- msg.obj = views;
+ Message msg = mHandler.obtainMessage(HANDLE_UPDATE, appWidgetId, userId, views);
msg.sendToTarget();
}
- public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) {
+ public void providerChanged(int appWidgetId, AppWidgetProviderInfo info, int userId) {
if (isLocalBinder() && info != null) {
info = info.clone();
}
- Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
- msg.arg1 = appWidgetId;
- msg.obj = info;
+ Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED,
+ appWidgetId, userId, info);
msg.sendToTarget();
}
- public void providersChanged() {
- Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED);
+ public void providersChanged(int userId) {
+ Message msg = mHandler.obtainMessage(HANDLE_PROVIDERS_CHANGED, userId, 0);
msg.sendToTarget();
}
- public void viewDataChanged(int appWidgetId, int viewId) {
- Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED);
- msg.arg1 = appWidgetId;
- msg.arg2 = viewId;
+ public void viewDataChanged(int appWidgetId, int viewId, int userId) {
+ Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED,
+ appWidgetId, viewId, userId);
msg.sendToTarget();
}
}
@@ -99,7 +101,7 @@ public class AppWidgetHost {
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLE_UPDATE: {
- updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj);
+ updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj, msg.arg2);
break;
}
case HANDLE_PROVIDER_CHANGED: {
@@ -107,26 +109,17 @@ public class AppWidgetHost {
break;
}
case HANDLE_PROVIDERS_CHANGED: {
- onProvidersChanged();
+ onProvidersChanged(msg.arg1);
break;
}
case HANDLE_VIEW_DATA_CHANGED: {
- viewDataChanged(msg.arg1, msg.arg2);
+ viewDataChanged(msg.arg1, msg.arg2, (Integer) msg.obj);
break;
}
}
}
}
- Handler mHandler;
-
- int mHostId;
- Callbacks mCallbacks = new Callbacks();
- final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
- private OnClickHandler mOnClickHandler;
- // Optionally set by lockscreen
- private UserHandle mUser;
-
public AppWidgetHost(Context context, int hostId) {
this(context, hostId, null, context.getMainLooper());
}
@@ -140,14 +133,9 @@ public class AppWidgetHost {
mOnClickHandler = handler;
mHandler = new UpdateHandler(looper);
mDisplayMetrics = context.getResources().getDisplayMetrics();
- mUser = Process.myUserHandle();
bindService();
}
- /** @hide */
- public void setUserId(int userId) {
- mUser = new UserHandle(userId);
- }
private static void bindService() {
synchronized (sServiceLock) {
@@ -163,23 +151,15 @@ public class AppWidgetHost {
* becomes visible, i.e. from onStart() in your Activity.
*/
public void startListening() {
- startListeningAsUser(UserHandle.myUserId());
- }
-
- /**
- * Start receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity
- * becomes visible, i.e. from onStart() in your Activity.
- * @hide
- */
- public void startListeningAsUser(int userId) {
int[] updatedIds;
ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
+ final int userId = mContext.getUserId();
try {
if (mPackageName == null) {
mPackageName = mContext.getPackageName();
}
- updatedIds = sService.startListeningAsUser(
+ updatedIds = sService.startListening(
mCallbacks, mPackageName, mHostId, updatedViews, userId);
}
catch (RemoteException e) {
@@ -191,7 +171,7 @@ public class AppWidgetHost {
if (updatedViews.get(i) != null) {
updatedViews.get(i).setUser(new UserHandle(userId));
}
- updateAppWidgetView(updatedIds[i], updatedViews.get(i));
+ updateAppWidgetView(updatedIds[i], updatedViews.get(i), userId);
}
}
@@ -201,26 +181,14 @@ public class AppWidgetHost {
*/
public void stopListening() {
try {
- sService.stopListeningAsUser(mHostId, UserHandle.myUserId());
+ sService.stopListening(mHostId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
- }
- /**
- * Stop receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity is
- * no longer visible, i.e. from onStop() in your Activity.
- * @hide
- */
- public void stopListeningAsUser(int userId) {
- try {
- sService.stopListeningAsUser(mHostId, userId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- // Also clear the views
+ // This is here because keyguard needs it since it'll be switching users after this call.
+ // If it turns out other apps need to call this often, we should re-think how this works.
clearViews();
}
@@ -230,11 +198,12 @@ public class AppWidgetHost {
* @return a appWidgetId
*/
public int allocateAppWidgetId() {
+
try {
if (mPackageName == null) {
mPackageName = mContext.getPackageName();
}
- return sService.allocateAppWidgetId(mPackageName, mHostId);
+ return sService.allocateAppWidgetId(mPackageName, mHostId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -247,7 +216,7 @@ public class AppWidgetHost {
* @return a appWidgetId
* @hide
*/
- public static int allocateAppWidgetIdForSystem(int hostId) {
+ public static int allocateAppWidgetIdForSystem(int hostId, int userId) {
checkCallerIsSystem();
try {
if (sService == null) {
@@ -256,7 +225,7 @@ public class AppWidgetHost {
Context systemContext =
(Context) ActivityThread.currentActivityThread().getSystemContext();
String packageName = systemContext.getPackageName();
- return sService.allocateAppWidgetId(packageName, hostId);
+ return sService.allocateAppWidgetId(packageName, hostId, userId);
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
@@ -272,7 +241,7 @@ public class AppWidgetHost {
if (sService == null) {
bindService();
}
- return sService.getAppWidgetIdsForHost(mHostId);
+ return sService.getAppWidgetIdsForHost(mHostId, mContext.getUserId());
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
@@ -297,7 +266,7 @@ public class AppWidgetHost {
synchronized (mViews) {
mViews.remove(appWidgetId);
try {
- sService.deleteAppWidgetId(appWidgetId);
+ sService.deleteAppWidgetId(appWidgetId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -309,13 +278,13 @@ public class AppWidgetHost {
* Stop listening to changes for this AppWidget.
* @hide
*/
- public static void deleteAppWidgetIdForSystem(int appWidgetId) {
+ public static void deleteAppWidgetIdForSystem(int appWidgetId, int userId) {
checkCallerIsSystem();
try {
if (sService == null) {
bindService();
}
- sService.deleteAppWidgetId(appWidgetId);
+ sService.deleteAppWidgetId(appWidgetId, userId);
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
@@ -331,7 +300,7 @@ public class AppWidgetHost {
*/
public void deleteHost() {
try {
- sService.deleteHost(mHostId);
+ sService.deleteHost(mHostId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -347,8 +316,16 @@ public class AppWidgetHost {
* </ul>
*/
public static void deleteAllHosts() {
+ deleteAllHosts(UserHandle.myUserId());
+ }
+
+ /**
+ * Private method containing a userId
+ * @hide
+ */
+ public static void deleteAllHosts(int userId) {
try {
- sService.deleteAllHosts();
+ sService.deleteAllHosts(userId);
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -361,8 +338,9 @@ public class AppWidgetHost {
*/
public final AppWidgetHostView createView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
+ final int userId = context.getUserId();
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
- view.setUserId(mUser.getIdentifier());
+ view.setUserId(userId);
view.setOnClickHandler(mOnClickHandler);
view.setAppWidget(appWidgetId, appWidget);
synchronized (mViews) {
@@ -370,9 +348,9 @@ public class AppWidgetHost {
}
RemoteViews views;
try {
- views = sService.getAppWidgetViews(appWidgetId);
+ views = sService.getAppWidgetViews(appWidgetId, userId);
if (views != null) {
- views.setUser(mUser);
+ views.setUser(new UserHandle(mContext.getUserId()));
}
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -422,10 +400,20 @@ public class AppWidgetHost {
* are added, updated or removed, or widget components are enabled or disabled.)
*/
protected void onProvidersChanged() {
- // Do nothing
+ onProvidersChanged(mContext.getUserId());
}
- void updateAppWidgetView(int appWidgetId, RemoteViews views) {
+ /**
+ * Private method containing a userId
+ * @hide
+ */
+ protected void onProvidersChanged(int userId) {
+ checkUserMatch(userId);
+ // Does nothing
+ }
+
+ void updateAppWidgetView(int appWidgetId, RemoteViews views, int userId) {
+ checkUserMatch(userId);
AppWidgetHostView v;
synchronized (mViews) {
v = mViews.get(appWidgetId);
@@ -435,7 +423,8 @@ public class AppWidgetHost {
}
}
- void viewDataChanged(int appWidgetId, int viewId) {
+ void viewDataChanged(int appWidgetId, int viewId, int userId) {
+ checkUserMatch(userId);
AppWidgetHostView v;
synchronized (mViews) {
v = mViews.get(appWidgetId);
@@ -445,6 +434,16 @@ public class AppWidgetHost {
}
}
+ // Ensure that the userId passed to us agrees with the one associated with this instance
+ // of AppWidgetHost.
+ // TODO: This should be removed in production code.
+ private void checkUserMatch(int userId) {
+ if (userId != mContext.getUserId()) {
+ throw new IllegalStateException(
+ "User ids don't match, userId=" + userId + ", mUserId=" + mContext.getUserId());
+ }
+ }
+
/**
* Clear the list of Views that have been created by this AppWidgetHost.
*/
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 6b1c3e2..e68d23a 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,6 +16,7 @@
package android.appwidget;
+import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -268,8 +269,8 @@ public class AppWidgetManager {
/**
* Sent when the custom extras for an AppWidget change.
*
- * @see AppWidgetProvider#onAppWidgetOptionsChanged
- * AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
+ * @see AppWidgetProvider#onAppWidgetOptionsChanged
+ * AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
* AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
*/
public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
@@ -352,7 +353,7 @@ public class AppWidgetManager {
* It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
* and outside of the handler.
* This method will only work when called from the uid that owns the AppWidget provider.
- *
+ *
* <p>
* The total Bitmap memory used by the RemoteViews object cannot exceed that required to
* fill the screen 1.5 times, ie. (screen width x screen height x 4 x 1.5) bytes.
@@ -362,7 +363,7 @@ public class AppWidgetManager {
*/
public void updateAppWidget(int[] appWidgetIds, RemoteViews views) {
try {
- sService.updateAppWidgetIds(appWidgetIds, views);
+ sService.updateAppWidgetIds(appWidgetIds, views, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -382,7 +383,7 @@ public class AppWidgetManager {
*/
public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
try {
- sService.updateAppWidgetOptions(appWidgetId, options);
+ sService.updateAppWidgetOptions(appWidgetId, options, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -402,7 +403,7 @@ public class AppWidgetManager {
*/
public Bundle getAppWidgetOptions(int appWidgetId) {
try {
- return sService.getAppWidgetOptions(appWidgetId);
+ return sService.getAppWidgetOptions(appWidgetId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -436,7 +437,7 @@ public class AppWidgetManager {
* Perform an incremental update or command on the widget(s) specified by appWidgetIds.
*
* This update differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
- * RemoteViews object which is passed is understood to be an incomplete representation of the
+ * RemoteViews object which is passed is understood to be an incomplete representation of the
* widget, and hence does not replace the cached representation of the widget. As of API
* level 17, the new properties set within the views objects will be appended to the cached
* representation of the widget, and hence will persist.
@@ -458,7 +459,7 @@ public class AppWidgetManager {
*/
public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) {
try {
- sService.partiallyUpdateAppWidgetIds(appWidgetIds, views);
+ sService.partiallyUpdateAppWidgetIds(appWidgetIds, views, mContext.getUserId());
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
@@ -507,7 +508,7 @@ public class AppWidgetManager {
*/
public void updateAppWidget(ComponentName provider, RemoteViews views) {
try {
- sService.updateAppWidgetProvider(provider, views);
+ sService.updateAppWidgetProvider(provider, views, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -523,7 +524,7 @@ public class AppWidgetManager {
*/
public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
try {
- sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
+ sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -557,7 +558,8 @@ public class AppWidgetManager {
*/
public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
try {
- List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter);
+ List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter,
+ mContext.getUserId());
for (AppWidgetProviderInfo info : providers) {
// Converting complex to dp.
info.minWidth =
@@ -584,7 +586,8 @@ public class AppWidgetManager {
*/
public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
try {
- AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId);
+ AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId,
+ mContext.getUserId());
if (info != null) {
// Converting complex to dp.
info.minWidth =
@@ -617,7 +620,7 @@ public class AppWidgetManager {
*/
public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
try {
- sService.bindAppWidgetId(appWidgetId, provider, null);
+ sService.bindAppWidgetId(appWidgetId, provider, null, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -641,7 +644,7 @@ public class AppWidgetManager {
*/
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
try {
- sService.bindAppWidgetId(appWidgetId, provider, options);
+ sService.bindAppWidgetId(appWidgetId, provider, options, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -667,7 +670,7 @@ public class AppWidgetManager {
}
try {
return sService.bindAppWidgetIdIfAllowed(
- mContext.getPackageName(), appWidgetId, provider, null);
+ mContext.getPackageName(), appWidgetId, provider, null, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -696,8 +699,8 @@ public class AppWidgetManager {
return false;
}
try {
- return sService.bindAppWidgetIdIfAllowed(
- mContext.getPackageName(), appWidgetId, provider, options);
+ return sService.bindAppWidgetIdIfAllowed(mContext.getPackageName(), appWidgetId,
+ provider, options, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -715,7 +718,7 @@ public class AppWidgetManager {
*/
public boolean hasBindAppWidgetPermission(String packageName) {
try {
- return sService.hasBindAppWidgetPermission(packageName);
+ return sService.hasBindAppWidgetPermission(packageName, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -733,7 +736,7 @@ public class AppWidgetManager {
*/
public void setBindAppWidgetPermission(String packageName, boolean permission) {
try {
- sService.setBindAppWidgetPermission(packageName, permission);
+ sService.setBindAppWidgetPermission(packageName, permission, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -794,7 +797,7 @@ public class AppWidgetManager {
*/
public int[] getAppWidgetIds(ComponentName provider) {
try {
- return sService.getAppWidgetIds(provider);
+ return sService.getAppWidgetIds(provider, mContext.getUserId());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c964af4..8a9eed2 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2691,6 +2691,14 @@ public abstract class Context {
throws PackageManager.NameNotFoundException;
/**
+ * Get the userId associated with this context
+ * @return user id
+ *
+ * @hide
+ */
+ public abstract int getUserId();
+
+ /**
* Return a new Context object for the current Context but whose resources
* are adjusted to match the given Configuration. Each call to this method
* returns a new instance of a Context object; Context objects are not
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 736dd99..2f1bf8c 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -623,6 +623,12 @@ public class ContextWrapper extends Context {
return mBase.createPackageContextAsUser(packageName, flags, user);
}
+ /** @hide */
+ @Override
+ public int getUserId() {
+ return mBase.getUserId();
+ }
+
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
return mBase.createConfigurationContext(overrideConfiguration);
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
index 78b4466..6d51d38 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl
@@ -22,9 +22,9 @@ import android.widget.RemoteViews;
/** {@hide} */
oneway interface IAppWidgetHost {
- void updateAppWidget(int appWidgetId, in RemoteViews views);
- void providerChanged(int appWidgetId, in AppWidgetProviderInfo info);
- void providersChanged();
- void viewDataChanged(int appWidgetId, int viewId);
+ void updateAppWidget(int appWidgetId, in RemoteViews views, int userId);
+ void providerChanged(int appWidgetId, in AppWidgetProviderInfo info, int userId);
+ void providersChanged(int userId);
+ void viewDataChanged(int appWidgetId, int viewId, int userId);
}
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index e685e63..7ddd5d2 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -26,42 +26,39 @@ import android.widget.RemoteViews;
/** {@hide} */
interface IAppWidgetService {
-
+
//
// for AppWidgetHost
//
int[] startListening(IAppWidgetHost host, String packageName, int hostId,
- out List<RemoteViews> updatedViews);
- int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId,
out List<RemoteViews> updatedViews, int userId);
- void stopListening(int hostId);
- void stopListeningAsUser(int hostId, int userId);
- int allocateAppWidgetId(String packageName, int hostId);
- void deleteAppWidgetId(int appWidgetId);
- void deleteHost(int hostId);
- void deleteAllHosts();
- RemoteViews getAppWidgetViews(int appWidgetId);
- int[] getAppWidgetIdsForHost(int hostId);
+ void stopListening(int hostId, int userId);
+ int allocateAppWidgetId(String packageName, int hostId, int userId);
+ void deleteAppWidgetId(int appWidgetId, int userId);
+ void deleteHost(int hostId, int userId);
+ void deleteAllHosts(int userId);
+ RemoteViews getAppWidgetViews(int appWidgetId, int userId);
+ int[] getAppWidgetIdsForHost(int hostId, int userId);
//
// for AppWidgetManager
//
- void updateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views);
- void updateAppWidgetOptions(int appWidgetId, in Bundle extras);
- Bundle getAppWidgetOptions(int appWidgetId);
- void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views);
- void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
- void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, int viewId);
- List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter);
- AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
- boolean hasBindAppWidgetPermission(in String packageName);
- void setBindAppWidgetPermission(in String packageName, in boolean permission);
- void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options);
- boolean bindAppWidgetIdIfAllowed(
- in String packageName, int appWidgetId, in ComponentName provider, in Bundle options);
+ void updateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views, int userId);
+ void updateAppWidgetOptions(int appWidgetId, in Bundle extras, int userId);
+ Bundle getAppWidgetOptions(int appWidgetId, int userId);
+ void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views, int userId);
+ void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views, int userId);
+ void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, int viewId, int userId);
+ List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId);
+ AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId);
+ boolean hasBindAppWidgetPermission(in String packageName, int userId);
+ void setBindAppWidgetPermission(in String packageName, in boolean permission, int userId);
+ void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options, int userId);
+ boolean bindAppWidgetIdIfAllowed(in String packageName, int appWidgetId,
+ in ComponentName provider, in Bundle options, int userId);
void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection, int userId);
void unbindRemoteViewsService(int appWidgetId, in Intent intent, int userId);
- int[] getAppWidgetIds(in ComponentName provider);
+ int[] getAppWidgetIds(in ComponentName provider, int userId);
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index a0a5f5a..06f06b5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -30,6 +30,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -102,8 +103,9 @@ public class KeyguardHostView extends KeyguardViewBase {
private boolean mUserSetupCompleted;
- // User for whom this host view was created
- private int mUserId;
+ // User for whom this host view was created. Final because we should never change the
+ // id without reconstructing an instance of KeyguardHostView. See note below...
+ private final int mUserId;
private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
@@ -132,10 +134,35 @@ public class KeyguardHostView extends KeyguardViewBase {
public KeyguardHostView(Context context, AttributeSet attrs) {
super(context, attrs);
mLockPatternUtils = new LockPatternUtils(context);
+
+ // Note: This depends on KeyguardHostView getting reconstructed every time the
+ // user switches, since mUserId will be used for the entire session.
+ // Once created, keyguard should *never* re-use this instance with another user.
+ // In other words, mUserId should never change - hence it's marked final.
mUserId = mLockPatternUtils.getCurrentUser();
- mAppWidgetHost = new AppWidgetHost(
- context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper());
- mAppWidgetHost.setUserId(mUserId);
+
+ Context userContext = null;
+ try {
+ final String packageName = "system";
+ userContext = mContext.createPackageContextAsUser(packageName, 0,
+ new UserHandle(mUserId));
+
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ // This should never happen, but it's better to have no widgets than to crash.
+ userContext = context;
+ }
+
+ // These need to be created with the user context...
+ mAppWidgetHost = new AppWidgetHost(userContext, APPWIDGET_HOST_ID, mOnClickHandler,
+ Looper.myLooper());
+ mAppWidgetManager = AppWidgetManager.getInstance(userContext);
+
+ cleanupAppWidgetIds();
+
+ mSecurityModel = new KeyguardSecurityModel(context);
+
+ mViewStateManager = new KeyguardViewStateManager(this);
DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -355,21 +382,17 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mAppWidgetHost.startListeningAsUser(mUserId);
+ mAppWidgetHost.startListening();
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mAppWidgetHost.stopListeningAsUser(mUserId);
+ mAppWidgetHost.stopListening();
KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
}
- private AppWidgetHost getAppWidgetHost() {
- return mAppWidgetHost;
- }
-
void addWidget(AppWidgetHostView view, int pageIndex) {
mAppWidgetContainer.addWidget(view, pageIndex);
}
@@ -1020,12 +1043,13 @@ public class KeyguardHostView extends KeyguardViewBase {
private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
if (appWidgetInfo != null) {
- AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+ AppWidgetHostView view = mAppWidgetHost.createView(mContext, appId, appWidgetInfo);
addWidget(view, pageIndex);
return true;
} else {
if (updateDbIfFailed) {
- Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting");
+ Log.w(TAG, "*** AppWidgetInfo for app widget id " + appId + " was null for user"
+ + mUserId + ", deleting");
mAppWidgetHost.deleteAppWidgetId(appId);
mLockPatternUtils.removeAppWidget(appId);
}
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 06aeb29..d5715a5 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -16,7 +16,7 @@
package com.android.server;
-import android.app.ActivityManagerNative;
+import android.app.ActivityManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -121,107 +121,67 @@ class AppWidgetService extends IAppWidgetService.Stub
}, userFilter);
}
- /**
- * This returns the user id of the caller, if the caller is not the system process,
- * otherwise it assumes that the calls are from the lockscreen and hence are meant for the
- * current user. TODO: Instead, have lockscreen make explicit calls with userId
- */
- private int getCallingOrCurrentUserId() {
- int callingUid = Binder.getCallingUid();
- // Also check the PID because Settings (power control widget) also runs as System UID
- if (callingUid == android.os.Process.myUid()
- && Binder.getCallingPid() == android.os.Process.myPid()) {
- try {
- return ActivityManagerNative.getDefault().getCurrentUser().id;
- } catch (RemoteException re) {
- return UserHandle.getUserId(callingUid);
- }
- } else {
- return UserHandle.getUserId(callingUid);
- }
- }
-
@Override
- public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).allocateAppWidgetId(
- packageName, hostId);
+ public int allocateAppWidgetId(String packageName, int hostId, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).allocateAppWidgetId(packageName, hostId);
}
@Override
- public int[] getAppWidgetIdsForHost(int hostId) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIdsForHost(hostId);
+ public int[] getAppWidgetIdsForHost(int hostId, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetIdsForHost(hostId);
}
-
+
@Override
- public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).deleteAppWidgetId(appWidgetId);
+ public void deleteAppWidgetId(int appWidgetId, int userId) throws RemoteException {
+ getImplForUser(userId).deleteAppWidgetId(appWidgetId);
}
@Override
- public void deleteHost(int hostId) throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).deleteHost(hostId);
+ public void deleteHost(int hostId, int userId) throws RemoteException {
+ getImplForUser(userId).deleteHost(hostId);
}
@Override
- public void deleteAllHosts() throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).deleteAllHosts();
+ public void deleteAllHosts(int userId) throws RemoteException {
+ getImplForUser(userId).deleteAllHosts();
}
@Override
- public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)
+ public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options, int userId)
throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetId(appWidgetId, provider,
- options);
+ getImplForUser(userId).bindAppWidgetId(appWidgetId, provider, options);
}
@Override
public boolean bindAppWidgetIdIfAllowed(
- String packageName, int appWidgetId, ComponentName provider, Bundle options)
+ String packageName, int appWidgetId, ComponentName provider, Bundle options, int userId)
throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).bindAppWidgetIdIfAllowed(
+ return getImplForUser(userId).bindAppWidgetIdIfAllowed(
packageName, appWidgetId, provider, options);
}
@Override
- public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).hasBindAppWidgetPermission(
- packageName);
+ public boolean hasBindAppWidgetPermission(String packageName, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).hasBindAppWidgetPermission(packageName);
}
@Override
- public void setBindAppWidgetPermission(String packageName, boolean permission)
+ public void setBindAppWidgetPermission(String packageName, boolean permission, int userId)
throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).setBindAppWidgetPermission(
- packageName, permission);
+ getImplForUser(userId).setBindAppWidgetPermission(packageName, permission);
}
@Override
public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
int userId) throws RemoteException {
- if (Binder.getCallingPid() != android.os.Process.myPid()
- && userId != UserHandle.getCallingUserId()) {
- throw new SecurityException("Call from non-system process. Calling uid = "
- + Binder.getCallingUid());
- }
- getImplForUser(userId).bindRemoteViewsService(
- appWidgetId, intent, connection);
+ getImplForUser(userId).bindRemoteViewsService(appWidgetId, intent, connection);
}
@Override
public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
- List<RemoteViews> updatedViews) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).startListening(host,
- packageName, hostId, updatedViews);
- }
-
- @Override
- public int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId,
List<RemoteViews> updatedViews, int userId) throws RemoteException {
- if (Binder.getCallingPid() != android.os.Process.myPid()
- && userId != UserHandle.getCallingUserId()) {
- throw new SecurityException("Call from non-system process. Calling uid = "
- + Binder.getCallingUid());
- }
return getImplForUser(userId).startListening(host, packageName, hostId, updatedViews);
}
@@ -250,7 +210,19 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
+ private void checkPermission(int userId) {
+ int realUserId = ActivityManager.handleIncomingUser(
+ Binder.getCallingPid(),
+ Binder.getCallingUid(),
+ userId,
+ false, /* allowAll */
+ true, /* requireFull */
+ this.getClass().getSimpleName(),
+ this.getClass().getPackage().getName());
+ }
+
private AppWidgetServiceImpl getImplForUser(int userId) {
+ checkPermission(userId);
boolean sendInitial = false;
AppWidgetServiceImpl service;
synchronized (mAppWidgetServices) {
@@ -272,86 +244,73 @@ class AppWidgetService extends IAppWidgetService.Stub
}
@Override
- public int[] getAppWidgetIds(ComponentName provider) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetIds(provider);
+ public int[] getAppWidgetIds(ComponentName provider, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetIds(provider);
}
@Override
- public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetInfo(appWidgetId);
+ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId, int userId)
+ throws RemoteException {
+ return getImplForUser(userId).getAppWidgetInfo(appWidgetId);
}
@Override
- public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetViews(appWidgetId);
+ public RemoteViews getAppWidgetViews(int appWidgetId, int userId) throws RemoteException {
+ return getImplForUser(userId).getAppWidgetViews(appWidgetId);
}
@Override
- public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
- getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetOptions(appWidgetId, options);
+ public void updateAppWidgetOptions(int appWidgetId, Bundle options, int userId) {
+ getImplForUser(userId).updateAppWidgetOptions(appWidgetId, options);
}
@Override
- public Bundle getAppWidgetOptions(int appWidgetId) {
- return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetOptions(appWidgetId);
+ public Bundle getAppWidgetOptions(int appWidgetId, int userId) {
+ return getImplForUser(userId).getAppWidgetOptions(appWidgetId);
}
@Override
- public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter)
+ public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int userId)
throws RemoteException {
- return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders(categoryFilter);
+ return getImplForUser(userId).getInstalledProviders(categoryFilter);
}
@Override
- public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
+ public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId, int userId)
throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).notifyAppWidgetViewDataChanged(
+ getImplForUser(userId).notifyAppWidgetViewDataChanged(
appWidgetIds, viewId);
}
@Override
- public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views)
+ public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).partiallyUpdateAppWidgetIds(
+ getImplForUser(userId).partiallyUpdateAppWidgetIds(
appWidgetIds, views);
}
@Override
- public void stopListening(int hostId) throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).stopListening(hostId);
- }
-
- @Override
- public void stopListeningAsUser(int hostId, int userId) throws RemoteException {
- if (Binder.getCallingPid() != android.os.Process.myPid()
- && userId != UserHandle.getCallingUserId()) {
- throw new SecurityException("Call from non-system process. Calling uid = "
- + Binder.getCallingUid());
- }
+ public void stopListening(int hostId, int userId) throws RemoteException {
getImplForUser(userId).stopListening(hostId);
}
@Override
public void unbindRemoteViewsService(int appWidgetId, Intent intent, int userId)
throws RemoteException {
- if (Binder.getCallingPid() != android.os.Process.myPid()
- && userId != UserHandle.getCallingUserId()) {
- throw new SecurityException("Call from non-system process. Calling uid = "
- + Binder.getCallingUid());
- }
getImplForUser(userId).unbindRemoteViewsService(
appWidgetId, intent);
}
@Override
- public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetIds(appWidgetIds, views);
+ public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views, int userId)
+ throws RemoteException {
+ getImplForUser(userId).updateAppWidgetIds(appWidgetIds, views);
}
@Override
- public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
+ public void updateAppWidgetProvider(ComponentName provider, RemoteViews views, int userId)
throws RemoteException {
- getImplForUser(getCallingOrCurrentUserId()).updateAppWidgetProvider(provider, views);
+ getImplForUser(userId).updateAppWidgetProvider(provider, views);
}
@Override
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index d1829ab..6eea928 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -1046,7 +1046,7 @@ class AppWidgetServiceImpl {
if (id.host.callbacks != null) {
try {
// the lock is held, but this is a oneway call
- id.host.callbacks.updateAppWidget(id.appWidgetId, views);
+ id.host.callbacks.updateAppWidget(id.appWidgetId, views, mUserId);
} catch (RemoteException e) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.
@@ -1065,7 +1065,7 @@ class AppWidgetServiceImpl {
if (id.host.callbacks != null) {
try {
// the lock is held, but this is a oneway call
- id.host.callbacks.viewDataChanged(id.appWidgetId, viewId);
+ id.host.callbacks.viewDataChanged(id.appWidgetId, viewId, mUserId);
} catch (RemoteException e) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.
@@ -1934,7 +1934,8 @@ class AppWidgetServiceImpl {
id.views = null;
if (id.host != null && id.host.callbacks != null) {
try {
- id.host.callbacks.providerChanged(id.appWidgetId, p.info);
+ id.host.callbacks.providerChanged(id.appWidgetId, p.info,
+ mUserId);
} catch (RemoteException ex) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this
@@ -2001,7 +2002,7 @@ class AppWidgetServiceImpl {
Host host = mHosts.get(i);
try {
if (host.callbacks != null) {
- host.callbacks.providersChanged();
+ host.callbacks.providersChanged(mUserId);
}
} catch (RemoteException ex) {
// It failed; remove the callback. No need to prune because
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index cfc6bd7..29d6e4d 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -551,6 +551,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** {@hide} */
+ @Override
+ public int getUserId() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
throw new UnsupportedOperationException();