ActivityStartInterceptor.java revision 58d25998321d9f4b1b76d18a5af9d42cdbaad30d
1package com.android.server.am; 2 3import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; 4import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; 5import static android.app.PendingIntent.FLAG_IMMUTABLE; 6import static android.app.PendingIntent.FLAG_ONE_SHOT; 7import static android.content.Context.KEYGUARD_SERVICE; 8import static android.content.Intent.EXTRA_INTENT; 9import static android.content.Intent.EXTRA_PACKAGE_NAME; 10import static android.content.Intent.EXTRA_TASK_ID; 11import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 12import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 13import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED; 14 15import android.app.KeyguardManager; 16import android.content.IIntentSender; 17import android.content.Intent; 18import android.content.IntentSender; 19import android.content.pm.ActivityInfo; 20import android.content.pm.ResolveInfo; 21import android.content.pm.UserInfo; 22import android.os.Binder; 23import android.os.UserHandle; 24import android.os.UserManager; 25 26import com.android.internal.app.UnlaunchableAppActivity; 27 28/** 29 * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked} 30 * It's initialized 31 */ 32class ActivityStartInterceptor { 33 34 private final ActivityManagerService mService; 35 private UserManager mUserManager; 36 private final ActivityStackSupervisor mSupervisor; 37 38 /* 39 * Per-intent states loaded from ActivityStarter than shouldn't be changed by any 40 * interception routines. 41 */ 42 private int mRealCallingPid; 43 private int mRealCallingUid; 44 private int mUserId; 45 private int mStartFlags; 46 private String mCallingPackage; 47 48 /* 49 * Per-intent states that were load from ActivityStarter and are subject to modifications 50 * by the interception routines. After calling {@link #intercept} the caller should assign 51 * these values back to {@link ActivityStarter#startActivityLocked}'s local variables. 52 */ 53 Intent mIntent; 54 int mCallingPid; 55 int mCallingUid; 56 ResolveInfo mRInfo; 57 ActivityInfo mAInfo; 58 String mResolvedType; 59 TaskRecord mInTask; 60 61 ActivityStartInterceptor(ActivityManagerService service, ActivityStackSupervisor supervisor) { 62 mService = service; 63 mSupervisor = supervisor; 64 } 65 66 void setStates(int userId, int realCallingPid, int realCallingUid, int startFlags, 67 String callingPackage) { 68 mRealCallingPid = realCallingPid; 69 mRealCallingUid = realCallingUid; 70 mUserId = userId; 71 mStartFlags = startFlags; 72 mCallingPackage = callingPackage; 73 } 74 75 void intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, 76 TaskRecord inTask, int callingPid, int callingUid) { 77 mUserManager = UserManager.get(mService.mContext); 78 mIntent = intent; 79 mCallingPid = callingPid; 80 mCallingUid = callingUid; 81 mRInfo = rInfo; 82 mAInfo = aInfo; 83 mResolvedType = resolvedType; 84 mInTask = inTask; 85 interceptQuietProfileIfNeeded(); 86 interceptSuspendPackageIfNeed(); 87 interceptWorkProfileChallengeIfNeeded(); 88 } 89 90 private void interceptQuietProfileIfNeeded() { 91 // Do not intercept if the user has not turned off the profile 92 if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) { 93 return; 94 } 95 mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId); 96 mCallingPid = mRealCallingPid; 97 mCallingUid = mRealCallingUid; 98 mResolvedType = null; 99 100 final UserInfo parent = mUserManager.getProfileParent(mUserId); 101 mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id); 102 mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, 103 null /*profilerInfo*/); 104 } 105 106 private void interceptSuspendPackageIfNeed() { 107 // Do not intercept if the admin did not suspend the package 108 if (mAInfo == null || mAInfo.applicationInfo == null || 109 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) { 110 return; 111 } 112 mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName, 113 mUserId); 114 mCallingPid = mRealCallingPid; 115 mCallingUid = mRealCallingUid; 116 mResolvedType = null; 117 118 final UserInfo parent = mUserManager.getProfileParent(mUserId); 119 if (parent != null) { 120 mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id); 121 } else { 122 mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId); 123 } 124 mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, 125 null /*profilerInfo*/); 126 } 127 128 private void interceptWorkProfileChallengeIfNeeded() { 129 final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mIntent, 130 mResolvedType, mAInfo, mCallingPackage, mUserId); 131 if (interceptingIntent == null) { 132 return; 133 } 134 mIntent = interceptingIntent; 135 mCallingPid = mRealCallingPid; 136 mCallingUid = mRealCallingUid; 137 mResolvedType = null; 138 // If we are intercepting and there was a task, convert it into an extra for the 139 // ConfirmCredentials intent and unassign it, as otherwise the task will move to 140 // front even if ConfirmCredentials is cancelled. 141 if (mInTask != null) { 142 mIntent.putExtra(EXTRA_TASK_ID, mInTask.taskId); 143 mInTask = null; 144 } 145 146 final UserInfo parent = mUserManager.getProfileParent(mUserId); 147 mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id); 148 mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, 149 null /*profilerInfo*/); 150 } 151 152 /** 153 * Creates an intent to intercept the current activity start with Confirm Credentials if needed. 154 * 155 * @return The intercepting intent if needed. 156 */ 157 private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType, 158 ActivityInfo aInfo, String callingPackage, int userId) { 159 if (!mService.mUserController.shouldConfirmCredentials(userId)) { 160 return null; 161 } 162 final IIntentSender target = mService.getIntentSenderLocked( 163 INTENT_SENDER_ACTIVITY, callingPackage, 164 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent }, 165 new String[]{ resolvedType }, 166 FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE, null); 167 final int flags = intent.getFlags(); 168 final KeyguardManager km = (KeyguardManager) mService.mContext 169 .getSystemService(KEYGUARD_SERVICE); 170 final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, userId); 171 if (newIntent == null) { 172 return null; 173 } 174 newIntent.setFlags(flags | FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 175 newIntent.putExtra(EXTRA_PACKAGE_NAME, aInfo.packageName); 176 newIntent.putExtra(EXTRA_INTENT, new IntentSender(target)); 177 return newIntent; 178 } 179 180} 181