Merge "Notify app widget hosts when cross-profile providers change." into lmp-dev
This commit is contained in:
@@ -25,6 +25,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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
if (admin == null || admin.crossProfileWidgetProviders == null
|
||||
|| admin.crossProfileWidgetProviders.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return admin.crossProfileWidgetProviders;
|
||||
}
|
||||
}
|
||||
|
||||
DevicePolicyData policy = getUserData(profileId);
|
||||
ActiveAdmin admin = policy.mAdminMap.get(ownerComponent);
|
||||
|
||||
if (admin == null) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (admin.crossProfileWidgetProviders == null
|
||||
|| admin.crossProfileWidgetProviders.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
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);
|
||||
}
|
||||
|
||||
return admin.crossProfileWidgetProviders;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user