diff options
author | Svet Ganov <svetoslavganov@google.com> | 2014-08-20 09:47:47 -0700 |
---|---|---|
committer | Svetoslav Ganov <svetoslavganov@google.com> | 2014-08-20 20:25:10 +0000 |
commit | 6bd702538d90005add1cfc33746da19404090dc1 (patch) | |
tree | 7e2c16fbd334aff123794f7d1788f85adb61cc18 | |
parent | 4746bc78ec242c29171a1963c4f3f9cac73f2084 (diff) | |
download | frameworks_base-6bd702538d90005add1cfc33746da19404090dc1.zip frameworks_base-6bd702538d90005add1cfc33746da19404090dc1.tar.gz frameworks_base-6bd702538d90005add1cfc33746da19404090dc1.tar.bz2 |
Notify app widget hosts when cross-profile providers change.
1. Notify the hosts in the group if a package gets white-listed or
un-white-listed for providing widgets across profiles.
2. Notify hosts in the group for provider changes when a profile
is deleted.
bug:17126070
Change-Id: Ic719c1c68e45842d50decc95603f1d61583b8f02
3 files changed, 188 insertions, 38 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index edd8199..a1f1d92 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -26,6 +26,22 @@ import java.util.List; public abstract class DevicePolicyManagerInternal { /** + * Listener for changes in the white-listed packages to show cross-profile + * widgets. + */ + public interface OnCrossProfileWidgetProvidersChangeListener { + + /** + * Called when the white-listed packages to show cross-profile widgets + * have changed for a given user. + * + * @param profileId The profile for which the white-listed packages changed. + * @param packages The white-listed packages. + */ + public void onCrossProfileWidgetProvidersChanged(int profileId, List<String> packages); + } + + /** * Gets the packages whose widget providers are white-listed to be * available in the parent user. * @@ -35,4 +51,13 @@ public abstract class DevicePolicyManagerInternal { * profile. */ public abstract List<String> getCrossProfileWidgetProviders(int profileId); + + /** + * Adds a listener for changes in the white-listed packages to show + * cross-profile app widgets. + * + * @param listener The listener to add. + */ + public abstract void addOnCrossProfileWidgetProvidersChangeListener( + OnCrossProfileWidgetProvidersChangeListener listener); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 609ffda..c6aa30b 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -20,6 +20,7 @@ import android.app.AlarmManager; import android.app.AppGlobals; import android.app.PendingIntent; import android.app.admin.DevicePolicyManagerInternal; +import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; @@ -102,7 +103,8 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider { +class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider, + OnCrossProfileWidgetProvidersChangeListener { private static final String TAG = "AppWidgetServiceImpl"; private static boolean DEBUG = false; @@ -199,6 +201,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mSecurityPolicy = new SecurityPolicy(); computeMaximumWidgetBitmapMemory(); registerBroadcastReceiver(); + registerOnCrossProfileProvidersChangedListener(); } private void computeMaximumWidgetBitmapMemory() { @@ -243,6 +246,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku userFilter, null, null); } + private void registerOnCrossProfileProvidersChangedListener() { + DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( + DevicePolicyManagerInternal.class); + // The device policy is an optional component. + if (devicePolicyManager != null) { + devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this); + } + } + public void setSafeMode(boolean safeMode) { mSafeMode = safeMode; } @@ -368,7 +380,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku saveGroupStateAsync(userId); // If the set of providers has been modified, notify each active AppWidgetHost - scheduleNotifyHostsForProvidersChangedLocked(); + scheduleNotifyGroupHostsForProvidersChangedLocked(userId); } } } @@ -1657,11 +1669,27 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } - private void scheduleNotifyHostsForProvidersChangedLocked() { + private void scheduleNotifyGroupHostsForProvidersChangedLocked(int userId) { + final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId); + final int N = mHosts.size(); for (int i = N - 1; i >= 0; i--) { Host host = mHosts.get(i); + boolean hostInGroup = false; + final int M = profileIds.length; + for (int j = 0; j < M; j++) { + final int profileId = profileIds[j]; + if (host.getUserId() == profileId) { + hostInGroup = true; + break; + } + } + + if (!hostInGroup) { + continue; + } + if (host == null || host.zombie || host.callbacks == null) { continue; } @@ -2617,6 +2645,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private void onUserStopped(int userId) { synchronized (mLock) { + boolean providersChanged = false; + boolean crossProfileWidgetsChanged = false; + // Remove widgets that have both host and provider in the user. final int widgetCount = mWidgets.size(); for (int i = widgetCount - 1; i >= 0; i--) { @@ -2645,6 +2676,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku for (int i = hostCount - 1; i >= 0; i--) { Host host = mHosts.get(i); if (host.getUserId() == userId) { + crossProfileWidgetsChanged |= !host.widgets.isEmpty(); deleteHostLocked(host); } } @@ -2654,6 +2686,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku for (int i = providerCount - 1; i >= 0; i--) { Provider provider = mProviders.get(i); if (provider.getUserId() == userId) { + crossProfileWidgetsChanged |= !provider.widgets.isEmpty(); + providersChanged = true; deleteProviderLocked(provider); } } @@ -2678,6 +2712,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (nextIdIndex >= 0) { mNextAppWidgetIds.removeAt(nextIdIndex); } + + // Announce removed provider changes to all hosts in the group. + if (providersChanged) { + scheduleNotifyGroupHostsForProvidersChangedLocked(userId); + } + + // Save state if removing a profile changed the group state. + // Nothing will be saved if the group parent was removed. + if (crossProfileWidgetsChanged) { + saveGroupStateAsync(userId); + } } } @@ -2843,6 +2888,31 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @Override + public void onCrossProfileWidgetProvidersChanged(int userId, List<String> packages) { + final int parentId = mSecurityPolicy.getProfileParent(userId); + // We care only if the white-listed package is in a profile of + // the group parent as only the parent can add widgets from the + // profile and not the other way around. + if (parentId != userId) { + synchronized (mLock) { + boolean providersChanged = false; + + final int packageCount = packages.size(); + for (int i = 0; i < packageCount; i++) { + String packageName = packages.get(i); + providersChanged |= updateProvidersForPackageLocked(packageName, + userId, null); + } + + if (providersChanged) { + saveGroupStateAsync(userId); + scheduleNotifyGroupHostsForProvidersChangedLocked(userId); + } + } + } + } + private final class CallbackHandler extends Handler { public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1; public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 02f8bd5..21ba31e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -165,6 +165,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final UserManager mUserManager; final PowerManager.WakeLock mWakeLock; + final LocalService mLocalService; + IPowerManager mIPowerManager; IWindowManager mIWindowManager; NotificationManager mNotificationManager; @@ -790,6 +792,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { PackageManager.FEATURE_DEVICE_ADMIN); mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)) .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM"); + mLocalService = new LocalService(); if (!mHasFeature) { // Skip the rest of the initialization return; @@ -810,7 +813,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { filter.addDataScheme("package"); context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); - LocalServices.addService(DevicePolicyManagerInternal.class, new LocalService()); + LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService); } /** @@ -1899,44 +1902,71 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - if (activeAdmin.crossProfileWidgetProviders == null) { - activeAdmin.crossProfileWidgetProviders = new ArrayList<>(); + final int userId = UserHandle.getCallingUserId(); + List<String> changedProviders = null; + + synchronized (this) { + ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (activeAdmin.crossProfileWidgetProviders == null) { + activeAdmin.crossProfileWidgetProviders = new ArrayList<>(); + } + List<String> providers = activeAdmin.crossProfileWidgetProviders; + if (!providers.contains(packageName)) { + providers.add(packageName); + changedProviders = new ArrayList<>(providers); + saveSettingsLocked(userId); + } } - if (activeAdmin.crossProfileWidgetProviders.add(packageName)) { - saveSettingsLocked(UserHandle.getCallingUserId()); + + if (changedProviders != null) { + mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders); return true; } + return false; } @Override public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - if (activeAdmin.crossProfileWidgetProviders == null) { - return false; + final int userId = UserHandle.getCallingUserId(); + List<String> changedProviders = null; + + synchronized (this) { + ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (activeAdmin.crossProfileWidgetProviders == null) { + return false; + } + List<String> providers = activeAdmin.crossProfileWidgetProviders; + if (providers.remove(packageName)) { + changedProviders = new ArrayList<>(providers); + saveSettingsLocked(userId); + } } - if (activeAdmin.crossProfileWidgetProviders.remove(packageName)) { - saveSettingsLocked(UserHandle.getCallingUserId()); + + if (changedProviders != null) { + mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders); return true; } + return false; } @Override public List<String> getCrossProfileWidgetProviders(ComponentName admin) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - if (activeAdmin.crossProfileWidgetProviders == null - || activeAdmin.crossProfileWidgetProviders.isEmpty()) { - return null; - } - if (Binder.getCallingUid() == Process.myUid()) { - return new ArrayList<>(activeAdmin.crossProfileWidgetProviders); - } else { - return activeAdmin.crossProfileWidgetProviders; + synchronized (this) { + ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (activeAdmin.crossProfileWidgetProviders == null + || activeAdmin.crossProfileWidgetProviders.isEmpty()) { + return null; + } + if (Binder.getCallingUid() == Process.myUid()) { + return new ArrayList<>(activeAdmin.crossProfileWidgetProviders); + } else { + return activeAdmin.crossProfileWidgetProviders; + } } } @@ -4674,26 +4704,51 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } private final class LocalService extends DevicePolicyManagerInternal { + private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners; + @Override public List<String> getCrossProfileWidgetProviders(int profileId) { - ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId); - if (ownerComponent == null) { - return Collections.emptyList(); - } + synchronized (DevicePolicyManagerService.this) { + ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId); + if (ownerComponent == null) { + return Collections.emptyList(); + } - DevicePolicyData policy = getUserData(profileId); - ActiveAdmin admin = policy.mAdminMap.get(ownerComponent); + DevicePolicyData policy = getUserData(profileId); + ActiveAdmin admin = policy.mAdminMap.get(ownerComponent); - if (admin == null) { - return Collections.emptyList(); + if (admin == null || admin.crossProfileWidgetProviders == null + || admin.crossProfileWidgetProviders.isEmpty()) { + return Collections.emptyList(); + } + + return admin.crossProfileWidgetProviders; } + } - if (admin.crossProfileWidgetProviders == null - || admin.crossProfileWidgetProviders.isEmpty()) { - return Collections.emptyList(); + @Override + public void addOnCrossProfileWidgetProvidersChangeListener( + OnCrossProfileWidgetProvidersChangeListener listener) { + synchronized (DevicePolicyManagerService.this) { + if (mWidgetProviderListeners == null) { + mWidgetProviderListeners = new ArrayList<>(); + } + if (!mWidgetProviderListeners.contains(listener)) { + mWidgetProviderListeners.add(listener); + } } + } - return admin.crossProfileWidgetProviders; + private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) { + final List<OnCrossProfileWidgetProvidersChangeListener> listeners; + synchronized (DevicePolicyManagerService.this) { + listeners = new ArrayList<>(mWidgetProviderListeners); + } + final int listenerCount = listeners.size(); + for (int i = 0; i < listenerCount; i++) { + OnCrossProfileWidgetProvidersChangeListener listener = listeners.get(i); + listener.onCrossProfileWidgetProvidersChanged(userId, packages); + } } } } |