diff options
| author | Amith Yamasani <yamasani@google.com> | 2012-10-05 16:10:38 -0700 |
|---|---|---|
| committer | Amith Yamasani <yamasani@google.com> | 2012-10-05 17:24:37 -0700 |
| commit | 8320de8e29819963845d3d386d6d087844a5ae31 (patch) | |
| tree | 75138b98999e2b721256c2833d4f22325cab604f /services/java/com/android/server/AppWidgetService.java | |
| parent | 9dc11eb848bfcd463e504133e4e356c7e6497842 (diff) | |
| download | frameworks_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.java | 151 |
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(); + } } } |
