OSDN Git Service

Allow direct-boot aware activity to show before profile is unlocked
authorRubin Xu <rubinxu@google.com>
Thu, 28 Jul 2016 13:34:26 +0000 (14:34 +0100)
committerRubin Xu <rubinxu@google.com>
Wed, 14 Sep 2016 10:59:56 +0000 (11:59 +0100)
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

core/java/android/app/ActivityManagerNative.java
core/java/android/app/IActivityManager.java
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityStartInterceptor.java

index aacd5da..50479c8 100644 (file)
@@ -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;
 }
index e411e03..5a4470b 100644 (file)
@@ -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;
 }
index a1854fa..b3a1893 100644 (file)
@@ -1944,9 +1944,18 @@ public abstract class BaseStatusBar extends SystemUI implements
                                             .getIdentifier();
                                     if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                                             && mKeyguardManager.isDeviceLocked(userId)) {
-                                        if (startWorkChallengeIfNecessary(userId,
-                                                intent.getIntentSender(), notificationKey)) {
-                                            // Show work challenge, do not run pendingintent and
+                                        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
                                             // remove notification
                                             return;
                                         }
index aef4cd8..f65fab8 100644 (file)
@@ -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;
+    }
 }
index f26e47e..d719c58 100644 (file)
@@ -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 },