Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 635bc8bc authored by Svet Ganov's avatar Svet Ganov Committed by Android (Google) Code Review
Browse files

Merge "Notify app widget hosts when cross-profile providers change." into lmp-dev

parents 49cbfcc1 6bd70253
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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);
}
+73 −3
Original line number Diff line number Diff line
@@ -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;
+90 −35
Original line number Diff line number Diff line
@@ -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,34 +1902,60 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

    @Override
    public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
        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<>();
            }
        if (activeAdmin.crossProfileWidgetProviders.add(packageName)) {
            saveSettingsLocked(UserHandle.getCallingUserId());
            List<String> providers = activeAdmin.crossProfileWidgetProviders;
            if (!providers.contains(packageName)) {
                providers.add(packageName);
                changedProviders = new ArrayList<>(providers);
                saveSettingsLocked(userId);
            }
        }

        if (changedProviders != null) {
            mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
            return true;
        }

        return false;
    }

    @Override
    public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
        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;
            }
        if (activeAdmin.crossProfileWidgetProviders.remove(packageName)) {
            saveSettingsLocked(UserHandle.getCallingUserId());
            List<String> providers = activeAdmin.crossProfileWidgetProviders;
            if (providers.remove(packageName)) {
                changedProviders = new ArrayList<>(providers);
                saveSettingsLocked(userId);
            }
        }

        if (changedProviders != null) {
            mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
            return true;
        }

        return false;
    }

    @Override
    public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
        synchronized (this) {
            ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
            if (activeAdmin.crossProfileWidgetProviders == null
@@ -1939,6 +1968,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                return activeAdmin.crossProfileWidgetProviders;
            }
        }
    }

    /**
     * Return a single admin's expiration date/time, or the min (soonest) for all admins.
@@ -4674,8 +4704,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }

    private final class LocalService extends DevicePolicyManagerInternal {
        private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;

        @Override
        public List<String> getCrossProfileWidgetProviders(int profileId) {
            synchronized (DevicePolicyManagerService.this) {
                ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId);
                if (ownerComponent == null) {
                    return Collections.emptyList();
@@ -4684,11 +4717,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                DevicePolicyData policy = getUserData(profileId);
                ActiveAdmin admin = policy.mAdminMap.get(ownerComponent);

            if (admin == null) {
                return Collections.emptyList();
            }

            if (admin.crossProfileWidgetProviders == null
                if (admin == null || admin.crossProfileWidgetProviders == null
                        || admin.crossProfileWidgetProviders.isEmpty()) {
                    return Collections.emptyList();
                }
@@ -4696,4 +4725,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                return admin.crossProfileWidgetProviders;
            }
        }

        @Override
        public void addOnCrossProfileWidgetProvidersChangeListener(
                OnCrossProfileWidgetProvidersChangeListener listener) {
            synchronized (DevicePolicyManagerService.this) {
                if (mWidgetProviderListeners == null) {
                    mWidgetProviderListeners = new ArrayList<>();
                }
                if (!mWidgetProviderListeners.contains(listener)) {
                    mWidgetProviderListeners.add(listener);
                }
            }
        }

        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);
            }
        }
    }
}