summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvet Ganov <svetoslavganov@google.com>2014-08-20 09:47:47 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2014-08-20 20:25:10 +0000
commit6bd702538d90005add1cfc33746da19404090dc1 (patch)
tree7e2c16fbd334aff123794f7d1788f85adb61cc18
parent4746bc78ec242c29171a1963c4f3f9cac73f2084 (diff)
downloadframeworks_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
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java25
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java76
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java125
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);
+ }
}
}
}