summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/AppWidgetService.java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-10-05 16:10:38 -0700
committerAmith Yamasani <yamasani@google.com>2012-10-05 17:24:37 -0700
commit8320de8e29819963845d3d386d6d087844a5ae31 (patch)
tree75138b98999e2b721256c2833d4f22325cab604f /services/java/com/android/server/AppWidgetService.java
parent9dc11eb848bfcd463e504133e4e356c7e6497842 (diff)
downloadframeworks_base-8320de8e29819963845d3d386d6d087844a5ae31.zip
frameworks_base-8320de8e29819963845d3d386d6d087844a5ae31.tar.gz
frameworks_base-8320de8e29819963845d3d386d6d087844a5ae31.tar.bz2
Fix widget cross-talk between users due to Settings widget
Bug: 7247911 Bug: 7294899 Also did some cleanup of unused code that resulted from refactoring the app widget service. Fixed a few more ambiguous calls that weren't using the correct user id. Added some logging and improved the dump() formatting. Change-Id: I27abb5c6341458e1e50a2cc9ab67e8de573ab283
Diffstat (limited to 'services/java/com/android/server/AppWidgetService.java')
-rw-r--r--services/java/com/android/server/AppWidgetService.java151
1 files changed, 42 insertions, 109 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 9be7045..c18fe0e 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -17,34 +17,28 @@
package com.android.server;
import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.widget.RemoteViews;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.widget.IRemoteViewsAdapterConnection;
+import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -56,85 +50,11 @@ class AppWidgetService extends IAppWidgetService.Stub
{
private static final String TAG = "AppWidgetService";
- /*
- * When identifying a Host or Provider based on the calling process, use the uid field.
- * When identifying a Host or Provider based on a package manager broadcast, use the
- * package given.
- */
-
- static class Provider {
- int uid;
- AppWidgetProviderInfo info;
- ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
- PendingIntent broadcast;
- boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
-
- int tag; // for use while saving state (the index)
- }
-
- static class Host {
- int uid;
- int hostId;
- String packageName;
- ArrayList<AppWidgetId> instances = new ArrayList<AppWidgetId>();
- IAppWidgetHost callbacks;
- boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
-
- int tag; // for use while saving state (the index)
- }
-
- static class AppWidgetId {
- int appWidgetId;
- Provider provider;
- RemoteViews views;
- Host host;
- }
-
- /**
- * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection.
- * This needs to be a static inner class since a reference to the ServiceConnection is held
- * globally and may lead us to leak AppWidgetService instances (if there were more than one).
- */
- static class ServiceConnectionProxy implements ServiceConnection {
- private final IBinder mConnectionCb;
-
- ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
- mConnectionCb = connectionCb;
- }
- public void onServiceConnected(ComponentName name, IBinder service) {
- final IRemoteViewsAdapterConnection cb =
- IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
- try {
- cb.onServiceConnected(service);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public void onServiceDisconnected(ComponentName name) {
- disconnect();
- }
- public void disconnect() {
- final IRemoteViewsAdapterConnection cb =
- IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
- try {
- cb.onServiceDisconnected();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
Context mContext;
Locale mLocale;
PackageManager mPackageManager;
- AlarmManager mAlarmManager;
- ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
- int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
- final ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList<AppWidgetId>();
- ArrayList<Host> mHosts = new ArrayList<Host>();
boolean mSafeMode;
-
private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
AppWidgetService(Context context) {
@@ -195,9 +115,16 @@ class AppWidgetService extends IAppWidgetService.Stub
}, UserHandle.ALL, userFilter, null, null);
}
+ /**
+ * 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();
- if (callingUid == android.os.Process.myUid()) {
+ // 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) {
@@ -272,13 +199,16 @@ class AppWidgetService extends IAppWidgetService.Stub
}
public void onUserRemoved(int userId) {
- AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
if (userId < 1) return;
-
- if (impl == null) {
- AppWidgetServiceImpl.getSettingsFile(userId).delete();
- } else {
- impl.onUserRemoved();
+ synchronized (mAppWidgetServices) {
+ AppWidgetServiceImpl impl = mAppWidgetServices.get(userId);
+ mAppWidgetServices.remove(userId);
+
+ if (impl == null) {
+ AppWidgetServiceImpl.getSettingsFile(userId).delete();
+ } else {
+ impl.onUserRemoved();
+ }
}
}
@@ -286,17 +216,23 @@ class AppWidgetService extends IAppWidgetService.Stub
}
private AppWidgetServiceImpl getImplForUser(int userId) {
- AppWidgetServiceImpl service = mAppWidgetServices.get(userId);
- if (service == null) {
- Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user");
- // TODO: Verify that it's a valid user
- service = new AppWidgetServiceImpl(mContext, userId);
- service.systemReady(mSafeMode);
- // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
+ boolean sendInitial = false;
+ AppWidgetServiceImpl service;
+ synchronized (mAppWidgetServices) {
+ service = mAppWidgetServices.get(userId);
+ if (service == null) {
+ Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
+ // TODO: Verify that it's a valid user
+ service = new AppWidgetServiceImpl(mContext, userId);
+ service.systemReady(mSafeMode);
+ // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
+ mAppWidgetServices.append(userId, service);
+ sendInitial = true;
+ }
+ }
+ if (sendInitial) {
service.sendInitialBroadcasts();
- mAppWidgetServices.append(userId, service);
}
-
return service;
}
@@ -325,15 +261,6 @@ class AppWidgetService extends IAppWidgetService.Stub
return getImplForUser(getCallingOrCurrentUserId()).getAppWidgetOptions(appWidgetId);
}
- static int[] getAppWidgetIds(Provider p) {
- int instancesSize = p.instances.size();
- int appWidgetIds[] = new int[instancesSize];
- for (int i=0; i<instancesSize; i++) {
- appWidgetIds[i] = p.instances.get(i).appWidgetId;
- }
- return appWidgetIds;
- }
-
@Override
public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
return getImplForUser(getCallingOrCurrentUserId()).getInstalledProviders();
@@ -378,9 +305,15 @@ class AppWidgetService extends IAppWidgetService.Stub
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
// Dump the state of all the app widget providers
- for (int i = 0; i < mAppWidgetServices.size(); i++) {
- AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
- service.dump(fd, pw, args);
+ synchronized (mAppWidgetServices) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ pw.println("User: " + mAppWidgetServices.keyAt(i));
+ ipw.increaseIndent();
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.dump(fd, ipw, args);
+ ipw.decreaseIndent();
+ }
}
}