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

Commit 9a151070 authored by Lucas Silva's avatar Lucas Silva
Browse files

Reapply "Clear dream settings when package uninstalled"

This includes some additional null-checking to avoid the
NullPointerException which caused the change to be reverted. This also
wraps the fix in a flag which can be rolled out and verified slowly.

This reverts commit 089a8e88.

Bug: 338210427
Test: manually on device by setting 3P screensaver and then uninstalling
Flag: android.service.dreams.cleanup_dream_settings_on_uninstall
Change-Id: Ic8c1111420c6fc8ff0244032721bbb34ac5a0fab
parent 85091178
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -67,3 +67,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "cleanup_dream_settings_on_uninstall"
    namespace: "systemui"
    description: "Cleans up dream settings if dream package is uninstalled."
    bug: "338210427"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+77 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.Manifest.permission.BIND_DREAM_SERVICE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.service.dreams.Flags.cleanupDreamSettingsOnUninstall;
import static android.service.dreams.Flags.dreamHandlesBeingObscured;

import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;
@@ -64,12 +65,15 @@ import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.DumpUtils;
@@ -86,6 +90,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -155,6 +160,10 @@ public final class DreamManagerService extends SystemService {
    private ComponentName mDreamOverlayServiceName;

    private final AmbientDisplayConfiguration mDozeConfig;

    /** Stores {@link PerUserPackageMonitor} to monitor dream uninstalls. */
    private final SparseArray<PackageMonitor> mPackageMonitors = new SparseArray<>();

    private final ActivityInterceptorCallback mActivityInterceptorCallback =
            new ActivityInterceptorCallback() {
                @Nullable
@@ -218,6 +227,15 @@ public final class DreamManagerService extends SystemService {
        }
    }

    private final class PerUserPackageMonitor extends PackageMonitor {
        @Override
        public void onPackageRemoved(String packageName, int uid) {
            super.onPackageRemoved(packageName, uid);
            final int userId = getChangingUserId();
            updateDreamOnPackageRemoved(packageName, userId);
        }
    }

    public DreamManagerService(Context context) {
        this(context, new DreamHandler(FgThread.get().getLooper()));
    }
@@ -333,6 +351,37 @@ public final class DreamManagerService extends SystemService {
        });
    }

    @Override
    public void onUserStarting(@NonNull TargetUser user) {
        super.onUserStarting(user);
        if (cleanupDreamSettingsOnUninstall()) {
            mHandler.post(() -> {
                final int userId = user.getUserIdentifier();
                if (!mPackageMonitors.contains(userId)) {
                    final PackageMonitor monitor = new PerUserPackageMonitor();
                    monitor.register(mContext, UserHandle.of(userId), mHandler);
                    mPackageMonitors.put(userId, monitor);
                } else {
                    Slog.w(TAG, "Package monitor already registered for " + userId);
                }
            });
        }
    }

    @Override
    public void onUserStopping(@NonNull TargetUser user) {
        super.onUserStopping(user);
        if (cleanupDreamSettingsOnUninstall()) {
            mHandler.post(() -> {
                final PackageMonitor monitor = mPackageMonitors.removeReturnOld(
                        user.getUserIdentifier());
                if (monitor != null) {
                    monitor.unregister();
                }
            });
        }
    }

    private void dumpInternal(PrintWriter pw) {
        synchronized (mLock) {
            pw.println("DREAM MANAGER (dumpsys dreams)");
@@ -664,6 +713,30 @@ public final class DreamManagerService extends SystemService {
        return validComponents.toArray(new ComponentName[validComponents.size()]);
    }

    private void updateDreamOnPackageRemoved(String packageName, int userId) {
        final ComponentName[] componentNames = componentsFromString(
                Settings.Secure.getStringForUser(mContext.getContentResolver(),
                        Settings.Secure.SCREENSAVER_COMPONENTS,
                        userId));
        if (componentNames != null) {
            // Filter out any components in the removed package.
            final ComponentName[] filteredComponents =
                    Arrays.stream(componentNames)
                            .filter((componentName -> !isSamePackage(packageName, componentName)))
                            .toArray(ComponentName[]::new);
            if (filteredComponents.length != componentNames.length) {
                setDreamComponentsForUser(userId, filteredComponents);
            }
        }
    }

    private static boolean isSamePackage(String packageName, ComponentName componentName) {
        if (packageName == null || componentName == null) {
            return false;
        }
        return TextUtils.equals(componentName.getPackageName(), packageName);
    }

    private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
        Settings.Secure.putStringForUser(mContext.getContentResolver(),
                Settings.Secure.SCREENSAVER_COMPONENTS,
@@ -824,7 +897,10 @@ public final class DreamManagerService extends SystemService {
        }
        StringBuilder names = new StringBuilder();
        for (ComponentName componentName : componentNames) {
            if (names.length() > 0) {
            if (componentName == null) {
                continue;
            }
            if (!names.isEmpty()) {
                names.append(',');
            }
            names.append(componentName.flattenToString());