WorkLockActivity.java revision 3fef1f284390a2ff7a58e0dcd56cb90bf83d2017
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 17package com.android.systemui.keyguard; 18 19import static android.app.ActivityManager.TaskDescription; 20 21import android.annotation.ColorInt; 22import android.annotation.UserIdInt; 23import android.app.Activity; 24import android.app.ActivityManager; 25import android.app.ActivityOptions; 26import android.app.KeyguardManager; 27import android.app.PendingIntent; 28import android.app.admin.DevicePolicyManager; 29import android.content.BroadcastReceiver; 30import android.content.Context; 31import android.content.Intent; 32import android.content.IntentFilter; 33import android.graphics.Color; 34import android.os.Bundle; 35import android.os.RemoteException; 36import android.os.UserHandle; 37import android.util.Log; 38import android.view.View; 39 40/** 41 * Bouncer between work activities and the activity used to confirm credentials before unlocking 42 * a managed profile. 43 * <p> 44 * Shows a solid color when started, based on the organization color of the user it is supposed to 45 * be blocking. Once focused, it switches to a screen to confirm credentials and auto-dismisses if 46 * credentials are accepted. 47 */ 48public class WorkLockActivity extends Activity { 49 private static final String TAG = "WorkLockActivity"; 50 51 /** 52 * ID of the locked user that this activity blocks access to. 53 */ 54 @UserIdInt 55 private int mUserId; 56 57 /** 58 * {@see KeyguardManager} 59 */ 60 private KeyguardManager mKgm; 61 62 /** 63 * {@see DevicePolicyManager} 64 */ 65 private DevicePolicyManager mDpm; 66 67 @Override 68 public void onCreate(Bundle savedInstanceState) { 69 super.onCreate(savedInstanceState); 70 71 mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); 72 mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 73 mKgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 74 75 final IntentFilter lockFilter = new IntentFilter(); 76 lockFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED); 77 registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL, lockFilter, 78 /* permission */ null, /* scheduler */ null); 79 80 // Once the receiver is registered, check whether anything happened between now and the time 81 // when this activity was launched. If it did and the user is unlocked now, just quit. 82 if (!mKgm.isDeviceLocked(mUserId)) { 83 finish(); 84 return; 85 } 86 87 // Get the organization color; this is a 24-bit integer provided by a DPC, guaranteed to 88 // be completely opaque. 89 final @ColorInt int color = mDpm.getOrganizationColorForUser(mUserId); 90 91 // Draw captions overlaid on the content view, so the whole window is one solid color. 92 setOverlayWithDecorCaptionEnabled(true); 93 94 // Match task description to the task stack we are replacing so it's still recognizably the 95 // original task stack with the same icon and title text. 96 setTaskDescription(new TaskDescription(null, null, color)); 97 98 // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with 99 // redaction switched on. 100 final View blankView = new View(this); 101 blankView.setBackgroundColor(color); 102 setContentView(blankView); 103 104 // Respond to input events by showing the prompt to confirm credentials. 105 blankView.setOnClickListener((View v) -> { 106 showConfirmCredentialActivity(); 107 }); 108 } 109 110 @Override 111 public void onDestroy() { 112 unregisterReceiver(mLockEventReceiver); 113 super.onDestroy(); 114 } 115 116 @Override 117 public void onBackPressed() { 118 // Ignore back presses. 119 return; 120 } 121 122 private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() { 123 @Override 124 public void onReceive(Context context, Intent intent) { 125 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, mUserId); 126 if (userId == mUserId && !mKgm.isDeviceLocked(mUserId)) { 127 finish(); 128 } 129 } 130 }; 131 132 private void showConfirmCredentialActivity() { 133 if (isFinishing() || !mKgm.isDeviceLocked(mUserId)) { 134 // Don't show the confirm credentials screen if we are already unlocked / unlocking. 135 return; 136 } 137 138 final Intent credential = mKgm.createConfirmDeviceCredentialIntent(null, null, mUserId); 139 if (credential == null) { 140 return; 141 } 142 143 final ActivityOptions options = ActivityOptions.makeBasic(); 144 options.setLaunchTaskId(getTaskId()); 145 146 // Bring this activity back to the foreground after confirming credentials. 147 final PendingIntent target = PendingIntent.getActivity(this, /* request */ -1, getIntent(), 148 PendingIntent.FLAG_CANCEL_CURRENT | 149 PendingIntent.FLAG_ONE_SHOT | 150 PendingIntent.FLAG_IMMUTABLE, options.toBundle()); 151 152 credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender()); 153 try { 154 ActivityManager.getService().startConfirmDeviceCredentialIntent(credential); 155 } catch (RemoteException e) { 156 Log.e(TAG, "Failed to start confirm credential intent", e); 157 } 158 } 159} 160