1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.systemui.keyguard; 18 19 import android.app.ActivityManager; 20 import android.app.ActivityOptions; 21 import android.app.ActivityTaskManager; 22 import android.app.IActivityTaskManager; 23 import android.app.KeyguardManager; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.os.Bundle; 28 import android.os.RemoteException; 29 import android.util.Log; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 import com.android.systemui.settings.UserTracker; 33 import com.android.systemui.shared.system.TaskStackChangeListener; 34 import com.android.systemui.shared.system.TaskStackChangeListeners; 35 36 public class WorkLockActivityController { 37 private static final String TAG = WorkLockActivityController.class.getSimpleName(); 38 39 private final Context mContext; 40 private final UserTracker mUserTracker; 41 private final IActivityTaskManager mIatm; 42 WorkLockActivityController(Context context, UserTracker userTracker)43 public WorkLockActivityController(Context context, UserTracker userTracker) { 44 this(context, userTracker, TaskStackChangeListeners.getInstance(), 45 ActivityTaskManager.getService()); 46 } 47 48 @VisibleForTesting WorkLockActivityController( Context context, UserTracker userTracker, TaskStackChangeListeners tscl, IActivityTaskManager iAtm)49 WorkLockActivityController( 50 Context context, UserTracker userTracker, TaskStackChangeListeners tscl, 51 IActivityTaskManager iAtm) { 52 mContext = context; 53 mUserTracker = userTracker; 54 mIatm = iAtm; 55 56 tscl.registerTaskStackListener(mLockListener); 57 } 58 startWorkChallengeInTask(ActivityManager.RunningTaskInfo info, int userId)59 private void startWorkChallengeInTask(ActivityManager.RunningTaskInfo info, int userId) { 60 String packageName = info.baseActivity != null ? info.baseActivity.getPackageName() : ""; 61 Intent intent = new Intent(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER) 62 .setComponent(new ComponentName(mContext, WorkLockActivity.class)) 63 .putExtra(Intent.EXTRA_USER_ID, userId) 64 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 65 .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT 66 | Intent.FLAG_ACTIVITY_CLEAR_TOP); 67 68 final ActivityOptions options = ActivityOptions.makeBasic(); 69 options.setLaunchTaskId(info.taskId); 70 options.setTaskOverlay(true, false /* canResume */); 71 72 final int result = startActivityAsUser(intent, options.toBundle(), 73 mUserTracker.getUserId()); 74 if (ActivityManager.isStartResultSuccessful(result)) { 75 // OK 76 } else { 77 // Starting the activity inside the task failed. We can't be sure why, so to be 78 // safe just remove the whole task if it still exists. 79 Log.w(TAG, "Failed to start work lock activity, will remove task=" + info.taskId); 80 try { 81 mIatm.removeTask(info.taskId); 82 } catch (RemoteException e) { 83 Log.e(TAG, "Failed to remove task=" + info.taskId); 84 } 85 } 86 } 87 88 /** 89 * Version of {@link Context#startActivityAsUser} which keeps the success code from 90 * IActivityManager, so we can read back whether ActivityManager thinks it started properly. 91 */ startActivityAsUser(Intent intent, Bundle options, int userId)92 private int startActivityAsUser(Intent intent, Bundle options, int userId) { 93 try { 94 return mIatm.startActivityAsUser( 95 mContext.getIApplicationThread() /*caller*/, 96 mContext.getBasePackageName() /*callingPackage*/, 97 mContext.getAttributionTag() /*callingAttributionTag*/, 98 intent /*intent*/, 99 intent.resolveTypeIfNeeded(mContext.getContentResolver()) /*resolvedType*/, 100 null /*resultTo*/, 101 null /*resultWho*/, 102 0 /*requestCode*/, 103 Intent.FLAG_ACTIVITY_NEW_TASK /*flags*/, 104 null /*profilerInfo*/, 105 options /*options*/, 106 userId /*user*/); 107 } catch (RemoteException e) { 108 return ActivityManager.START_CANCELED; 109 } catch (Exception e) { 110 return ActivityManager.START_CANCELED; 111 } 112 } 113 114 private final TaskStackChangeListener mLockListener = new TaskStackChangeListener() { 115 @Override 116 public void onTaskProfileLocked(ActivityManager.RunningTaskInfo info, int userId) { 117 startWorkChallengeInTask(info, userId); 118 } 119 }; 120 } 121