Loading services/java/com/android/server/AppWidgetService.java +42 −109 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -272,8 +199,10 @@ class AppWidgetService extends IAppWidgetService.Stub } public void onUserRemoved(int userId) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); if (userId < 1) return; synchronized (mAppWidgetServices) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); mAppWidgetServices.remove(userId); if (impl == null) { AppWidgetServiceImpl.getSettingsFile(userId).delete(); Loading @@ -281,22 +210,29 @@ class AppWidgetService extends IAppWidgetService.Stub impl.onUserRemoved(); } } } public void onUserStopped(int userId) { } private AppWidgetServiceImpl getImplForUser(int userId) { AppWidgetServiceImpl service = mAppWidgetServices.get(userId); boolean sendInitial = false; AppWidgetServiceImpl service; synchronized (mAppWidgetServices) { service = mAppWidgetServices.get(userId); if (service == null) { Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user"); 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. service.sendInitialBroadcasts(); mAppWidgetServices.append(userId, service); sendInitial = true; } } if (sendInitial) { service.sendInitialBroadcasts(); } return service; } Loading Loading @@ -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(); Loading Loading @@ -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 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, pw, args); service.dump(fd, ipw, args); ipw.decreaseIndent(); } } } Loading services/java/com/android/server/AppWidgetServiceImpl.java +20 −7 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -425,7 +433,8 @@ class AppWidgetServiceImpl { mAppWidgetIds.add(id); saveStateLocked(); if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId + " id=" + appWidgetId); return appWidgetId; } } Loading Loading @@ -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(); Loading @@ -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) { Loading Loading @@ -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; } } Loading @@ -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(); Loading Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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 }); Loading Loading
services/java/com/android/server/AppWidgetService.java +42 −109 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -272,8 +199,10 @@ class AppWidgetService extends IAppWidgetService.Stub } public void onUserRemoved(int userId) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); if (userId < 1) return; synchronized (mAppWidgetServices) { AppWidgetServiceImpl impl = mAppWidgetServices.get(userId); mAppWidgetServices.remove(userId); if (impl == null) { AppWidgetServiceImpl.getSettingsFile(userId).delete(); Loading @@ -281,22 +210,29 @@ class AppWidgetService extends IAppWidgetService.Stub impl.onUserRemoved(); } } } public void onUserStopped(int userId) { } private AppWidgetServiceImpl getImplForUser(int userId) { AppWidgetServiceImpl service = mAppWidgetServices.get(userId); boolean sendInitial = false; AppWidgetServiceImpl service; synchronized (mAppWidgetServices) { service = mAppWidgetServices.get(userId); if (service == null) { Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user"); 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. service.sendInitialBroadcasts(); mAppWidgetServices.append(userId, service); sendInitial = true; } } if (sendInitial) { service.sendInitialBroadcasts(); } return service; } Loading Loading @@ -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(); Loading Loading @@ -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 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, pw, args); service.dump(fd, ipw, args); ipw.decreaseIndent(); } } } Loading
services/java/com/android/server/AppWidgetServiceImpl.java +20 −7 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -425,7 +433,8 @@ class AppWidgetServiceImpl { mAppWidgetIds.add(id); saveStateLocked(); if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId + " id=" + appWidgetId); return appWidgetId; } } Loading Loading @@ -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(); Loading @@ -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) { Loading Loading @@ -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; } } Loading @@ -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(); Loading Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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 }); Loading