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

Commit f42207e1 authored by Manish Singh's avatar Manish Singh
Browse files

Remove all Settings tasks from Recents when PS is locked

Bug: 330865434
Test: manual
Test: atest PrivateSpaceMaintainerTest
Change-Id: I56b12a6ea5bfedd243fd138ef898f8496301199e
parent a9f13784
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;
@@ -104,12 +108,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;
            }

@@ -134,6 +139,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;
@@ -160,6 +166,7 @@ public class PrivateSpaceMaintainer {
        for (UserInfo user : users) {
            if (user.isPrivateProfile()) {
                mUserHandle = user.getUserHandle();
                registerBroadcastReceiver();
                return true;
            }
        }
@@ -213,6 +220,7 @@ public class PrivateSpaceMaintainer {
        mContext = context.getApplicationContext();
        mUserManager = mContext.getSystemService(UserManager.class);
        mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
        mActivityManager = mContext.getSystemService(ActivityManager.class);
    }


@@ -328,4 +336,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
@@ -90,6 +90,7 @@ public class PrivateSpaceMaintainerTest {
    public void deletePrivateSpace_psDoesNotExist_returnsNoPSError() {
        PrivateSpaceMaintainer privateSpaceMaintainer =
                PrivateSpaceMaintainer.getInstance(mContext);
        privateSpaceMaintainer.deletePrivateSpace();
        ErrorDeletingPrivateSpace errorDeletingPrivateSpace =
                privateSpaceMaintainer.deletePrivateSpace();
        assertThat(errorDeletingPrivateSpace)
@@ -178,6 +179,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.