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

Commit 89927b3c authored by Rubin Xu's avatar Rubin Xu
Browse files

Allow direct-boot aware activity to show before profile is unlocked

Work profile challenge is shown by intercepting normal activity launching and
replacing it with the confirm credential activity. For direct boot aware
activities, they should be able to be displayed when the work profile is
still locked, so add a conditional in the activity intercepting logic to bypass
work challenge in this case.

Also launching work profile activities from notification is handled specially
in order to avoid dismissing the notification if the work challenge is canceled,
so add similar logic there to allow direct boot aware activity to go through.

Bug: 30296144
Change-Id: Ib6395271cee2d4781009bb08d50351d73824de0c
parent 4efd735a
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -3017,6 +3017,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeNoException();
            return true;
        }
        case CAN_BYPASS_WORK_CHALLENGE: {
            data.enforceInterface(IActivityManager.descriptor);
            final PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data);
            final boolean result = canBypassWorkChallenge(intent);
            reply.writeNoException();
            reply.writeInt(result ? 1 : 0);
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -7091,6 +7099,20 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
        return;
    }
    @Override
    public boolean canBypassWorkChallenge(PendingIntent intent)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        intent.writeToParcel(data, 0);
        mRemote.transact(CAN_BYPASS_WORK_CHALLENGE, data, reply, 0);
        reply.readException();
        final int result = reply.readInt();
        data.recycle();
        reply.recycle();
        return result != 0;
    }

    private IBinder mRemote;
}
+13 −0
Original line number Diff line number Diff line
@@ -671,6 +671,18 @@ public interface IActivityManager extends IInterface {
     */
    public void setHasTopUi(boolean hasTopUi) throws RemoteException;

    /**
     * Returns if the target of the PendingIntent can be fired directly, without triggering
     * a work profile challenge. This can happen if the PendingIntent is to start direct-boot
     * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow
     * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet.
     * @param intent the {@link  PendingIntent} to be tested.
     * @return {@code true} if the intent should not trigger a work challenge, {@code false}
     *     otherwise.
     * @throws RemoteException
     */
    public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException;

    /*
     * Private non-Binder interfaces
     */
@@ -1062,4 +1074,5 @@ public interface IActivityManager extends IInterface {
    int SET_VR_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 377;
    int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
    int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
    int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380;
}
+12 −3
Original line number Diff line number Diff line
@@ -1944,9 +1944,18 @@ public abstract class BaseStatusBar extends SystemUI implements
                                            .getIdentifier();
                                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                                            && mKeyguardManager.isDeviceLocked(userId)) {
                                        if (startWorkChallengeIfNecessary(userId,
                                        boolean canBypass = false;
                                        try {
                                            canBypass = ActivityManagerNative.getDefault()
                                                    .canBypassWorkChallenge(intent);
                                        } catch (RemoteException e) {
                                        }
                                        // For direct-boot aware activities, they can be shown when
                                        // the device is still locked without triggering the work
                                        // challenge.
                                        if ((!canBypass) && startWorkChallengeIfNecessary(userId,
                                                    intent.getIntentSender(), notificationKey)) {
                                            // Show work challenge, do not run pendingintent and
                                            // Show work challenge, do not run PendingIntent and
                                            // remove notification
                                            return;
                                        }
+18 −0
Original line number Diff line number Diff line
@@ -22198,4 +22198,22 @@ public final class ActivityManagerService extends ActivityManagerNative
            Binder.restoreCallingIdentity(callingId);
        }
    }
    @Override
    public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException {
        final int userId = intent.getCreatorUserHandle().getIdentifier();
        if (!mUserController.isUserRunningLocked(userId, ActivityManager.FLAG_AND_LOCKED)) {
            return false;
        }
        IIntentSender target = intent.getTarget();
        if (!(target instanceof PendingIntentRecord)) {
            return false;
        }
        final PendingIntentRecord record = (PendingIntentRecord) target;
        final ResolveInfo rInfo = mStackSupervisor.resolveIntent(record.key.requestIntent,
                record.key.requestResolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE);
        // For direct boot aware activities, they can be shown without triggering a work challenge
        // before the profile user is unlocked.
        return rInfo != null && rInfo.activityInfo != null;
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;

import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManagerInternal;
@@ -210,6 +211,11 @@ class ActivityStartInterceptor {
        if (!mService.mUserController.shouldConfirmCredentials(userId)) {
            return null;
        }
        // Allow direct boot aware activity to be displayed before the user is unlocked.
        if (aInfo.directBootAware && mService.mUserController.isUserRunningLocked(userId,
                ActivityManager.FLAG_AND_LOCKED)) {
            return null;
        }
        final IIntentSender target = mService.getIntentSenderLocked(
                INTENT_SENDER_ACTIVITY, callingPackage,
                Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },