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

Commit f2869fd6 authored by Manish Singh's avatar Manish Singh Committed by Android (Google) Code Review
Browse files

Merge "Remove all Settings tasks from Recents when PS is locked" into main

parents fd27947e f42207e1
Loading
Loading
Loading
Loading
+101 −6
Original line number Diff line number Diff line
@@ -23,20 +23,21 @@ import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_DEV
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.UserInfo;
import android.os.Flags;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

@@ -54,9 +55,12 @@ public class PrivateSpaceMaintainer {

    private final Context mContext;
    private final UserManager mUserManager;
    private final ActivityManager mActivityManager;
    @GuardedBy("this")
    private UserHandle mUserHandle;
    private final KeyguardManager mKeyguardManager;
    /** This variable should be accessed via {@link #getBroadcastReceiver()} only. */
    @Nullable private ProfileAvailabilityBroadcastReceiver mProfileAvailabilityBroadcastReceiver;

    /** This is the default value for the hide private space entry point settings. */
    public static final int HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL = 0;
@@ -106,12 +110,13 @@ public class PrivateSpaceMaintainer {
                return false;
            }

            IActivityManager am = ActivityManager.getService();
            registerBroadcastReceiver();

            try {
                //TODO(b/313926659): To check and handle failure of startProfile
                am.startProfile(mUserHandle.getIdentifier());
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to start private profile");
                mActivityManager.startProfile(mUserHandle);
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Unexpected that " + mUserHandle.getIdentifier() + " is not a profile");
                return false;
            }

@@ -136,6 +141,7 @@ public class PrivateSpaceMaintainer {
            Log.i(TAG, "Deleting Private space with id: " + mUserHandle.getIdentifier());
            if (mUserManager.removeUser(mUserHandle)) {
                Log.i(TAG, "Private space deleted");
                unregisterBroadcastReceiver();
                mUserHandle = null;

                return ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE;
@@ -162,6 +168,7 @@ public class PrivateSpaceMaintainer {
        for (UserInfo user : users) {
            if (user.isPrivateProfile()) {
                mUserHandle = user.getUserHandle();
                registerBroadcastReceiver();
                return true;
            }
        }
@@ -215,6 +222,7 @@ public class PrivateSpaceMaintainer {
        mContext = context.getApplicationContext();
        mUserManager = mContext.getSystemService(UserManager.class);
        mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
        mActivityManager = mContext.getSystemService(ActivityManager.class);
    }


@@ -338,4 +346,91 @@ public class PrivateSpaceMaintainer {
                && android.multiuser.Flags.supportAutolockForPrivateSpace()
                && android.multiuser.Flags.enablePrivateSpaceFeatures();
    }

    /** {@link BroadcastReceiver} which handles the private profile's availability related
     * broadcasts.
     */
    private final class ProfileAvailabilityBroadcastReceiver extends BroadcastReceiver {
        void register() {
            Log.d(TAG, "Registering the receiver");
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_PROFILE_UNAVAILABLE);
            mContext.registerReceiver(/* receiver= */ this, filter, Context.RECEIVER_NOT_EXPORTED);
        }

        void unregister() {
            Log.d(TAG, "Unregistering the receiver");
            mContext.unregisterReceiver(/* receiver= */ this);
        }

        @Override
        public void onReceive(@NonNull Context context, @NonNull Intent intent) {
            UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
            if (!userHandle.equals(getPrivateProfileHandle())) {
                Log.d(TAG, "Ignoring intent for non-private profile with user id "
                        + userHandle.getIdentifier());
                return;
            }

            Log.i(TAG, "Removing all Settings tasks.");
            removeSettingsAllTasks();
        }
    }

    private synchronized void registerBroadcastReceiver() {
        if (!android.os.Flags.allowPrivateProfile()
                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
            return;
        }
        var broadcastReceiver = getBroadcastReceiver();
        if (broadcastReceiver == null) {
            return;
        }
        broadcastReceiver.register();
    }

    private synchronized void unregisterBroadcastReceiver() {
        if (!android.os.Flags.allowPrivateProfile()
                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
            return;
        }
        if (mProfileAvailabilityBroadcastReceiver == null) {
            Log.w(TAG, "Requested to unregister when there is no receiver.");
            return;
        }
        mProfileAvailabilityBroadcastReceiver.unregister();
        mProfileAvailabilityBroadcastReceiver = null;
    }

    /** Always use this getter to access {@link #mProfileAvailabilityBroadcastReceiver}. */
    @VisibleForTesting
    @Nullable synchronized ProfileAvailabilityBroadcastReceiver getBroadcastReceiver() {
        if (!android.os.Flags.allowPrivateProfile()
                || !android.multiuser.Flags.enablePrivateSpaceFeatures()) {
            return null;
        }
        if (!doesPrivateSpaceExist()) {
            Log.e(TAG, "Cannot return a broadcast receiver when private space doesn't exist");
            return null;
        }
        if (mProfileAvailabilityBroadcastReceiver == null) {
            mProfileAvailabilityBroadcastReceiver = new ProfileAvailabilityBroadcastReceiver();
        }
        return mProfileAvailabilityBroadcastReceiver;
    }

    /** This is purely for testing purpose only, and should not be used elsewhere. */
    @VisibleForTesting
    synchronized void resetBroadcastReceiver() {
        mProfileAvailabilityBroadcastReceiver = null;
    }

    private void removeSettingsAllTasks() {
        List<ActivityManager.AppTask> appTasks = mActivityManager.getAppTasks();
        for (var appTask : appTasks) {
            if (!appTask.getTaskInfo().isVisible()) {
                appTask.finishAndRemoveTask();
            }
        }
    }
}
+25 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ public class PrivateSpaceMaintainerTest {
                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
        PrivateSpaceMaintainer privateSpaceMaintainer =
                PrivateSpaceMaintainer.getInstance(mContext);
        privateSpaceMaintainer.deletePrivateSpace();
        ErrorDeletingPrivateSpace errorDeletingPrivateSpace =
                privateSpaceMaintainer.deletePrivateSpace();
        assertThat(errorDeletingPrivateSpace)
@@ -197,6 +198,30 @@ public class PrivateSpaceMaintainerTest {
                .isEqualTo(HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL);
    }

    @Test
    public void createPrivateSpace_psDoesNotExist_registersTheBroadcastReceiver() {
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
        PrivateSpaceMaintainer privateSpaceMaintainer =
                PrivateSpaceMaintainer.getInstance(mContext);
        privateSpaceMaintainer.deletePrivateSpace();
        privateSpaceMaintainer.createPrivateSpace();
        // test that no exception is thrown, which would indicate that the receiver was registered.
        mContext.unregisterReceiver(privateSpaceMaintainer.getBroadcastReceiver());
        privateSpaceMaintainer.resetBroadcastReceiver();
    }

    @Test
    public void deletePrivateSpace_psExists_unregistersTheBroadcastReceiver() {
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
                android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
        PrivateSpaceMaintainer privateSpaceMaintainer =
                PrivateSpaceMaintainer.getInstance(mContext);
        privateSpaceMaintainer.createPrivateSpace();
        privateSpaceMaintainer.deletePrivateSpace();
        assertThat(privateSpaceMaintainer.getBroadcastReceiver()).isNull();
    }

    /**
     * Tests that {@link PrivateSpaceMaintainer#lockPrivateSpace()} when PS exists and is running
     * locks the private profile.