diff options
Diffstat (limited to 'services/java/com/android')
-rw-r--r-- | services/java/com/android/server/AppWidgetService.java | 151 | ||||
-rw-r--r-- | services/java/com/android/server/AppWidgetServiceImpl.java | 27 |
2 files changed, 62 insertions, 116 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(); + } } } diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java index e77f8cf..41617c8 100644 --- a/services/java/com/android/server/AppWidgetServiceImpl.java +++ b/services/java/com/android/server/AppWidgetServiceImpl.java @@ -87,6 +87,8 @@ class AppWidgetServiceImpl { private static final String SETTINGS_FILENAME = "appwidgets.xml"; private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes + private static boolean DBG = false; + /* * 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. @@ -208,7 +210,12 @@ class AppWidgetServiceImpl { } } + private void log(String msg) { + Slog.i(TAG, "u=" + mUserId + ": " + msg); + } + void onConfigurationChanged() { + if (DBG) log("Got onConfigurationChanged()"); Locale revised = Locale.getDefault(); if (revised == null || mLocale == null || !(revised.equals(mLocale))) { mLocale = revised; @@ -235,6 +242,7 @@ class AppWidgetServiceImpl { } void onBroadcastReceived(Intent intent) { + if (DBG) log("onBroadcast " + intent); final String action = intent.getAction(); boolean added = false; boolean changed = false; @@ -425,7 +433,8 @@ class AppWidgetServiceImpl { mAppWidgetIds.add(id); saveStateLocked(); - + if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId + + " id=" + appWidgetId); return appWidgetId; } } @@ -518,6 +527,7 @@ class AppWidgetServiceImpl { } void cancelBroadcasts(Provider p) { + if (DBG) log("cancelBroadcasts for " + p); if (p.broadcast != null) { mAlarmManager.cancel(p.broadcast); long token = Binder.clearCallingIdentity(); @@ -531,6 +541,8 @@ class AppWidgetServiceImpl { } private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider, Bundle options) { + if (DBG) log("bindAppWidgetIdImpl appwid=" + appWidgetId + + " provider=" + provider); final long ident = Binder.clearCallingIdentity(); try { synchronized (mAppWidgetIds) { @@ -825,12 +837,14 @@ class AppWidgetServiceImpl { } public RemoteViews getAppWidgetViews(int appWidgetId) { + if (DBG) log("getAppWidgetViews id=" + appWidgetId); synchronized (mAppWidgetIds) { ensureStateLoadedLocked(); AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); if (id != null) { return cloneIfLocalBinder(id.views); } + if (DBG) log(" couldn't find appwidgetid"); return null; } } @@ -854,7 +868,7 @@ class AppWidgetServiceImpl { if (appWidgetIds == null) { return; } - + if (DBG) log("updateAppWidgetIds views: " + views); int bitmapMemoryUsage = 0; if (views != null) { bitmapMemoryUsage = views.estimateMemoryUsage(); @@ -1280,8 +1294,8 @@ class AppWidgetServiceImpl { intent.setComponent(p.info.provider); long token = Binder.clearCallingIdentity(); try { - p.broadcast = PendingIntent.getBroadcast(mContext, 1, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + p.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent, + PendingIntent.FLAG_UPDATE_CURRENT, new UserHandle(mUserId)); } finally { Binder.restoreCallingIdentity(token); } @@ -1353,7 +1367,7 @@ class AppWidgetServiceImpl { p.uid = activityInfo.applicationInfo.uid; Resources res = mContext.getPackageManager() - .getResourcesForApplication(activityInfo.applicationInfo); + .getResourcesForApplicationAsUser(activityInfo.packageName, mUserId); TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AppWidgetProviderInfo); @@ -1597,8 +1611,7 @@ class AppWidgetServiceImpl { final IPackageManager packageManager = AppGlobals.getPackageManager(); try { - packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0, - UserHandle.getCallingUserId()); + packageManager.getReceiverInfo(new ComponentName(pkg, cl), 0, mUserId); } catch (RemoteException e) { String[] pkgs = mContext.getPackageManager() .currentToCanonicalPackageNames(new String[] { pkg }); |