WorkLockActivity.java revision f793d87b805f204473d130ce29ece72ff1b3cec6
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 // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with 95 // redaction switched on. 96 final View blankView = new View(this); 97 blankView.setBackgroundColor(color); 98 setContentView(blankView); 99 } 100 101 /** 102 * Respond to focus events by showing the prompt to confirm credentials. 103 * <p> 104 * We don't have anything particularly interesting to show here (just a solid-colored page) so 105 * there is no sense in sitting in the foreground doing nothing. 106 */ 107 @Override 108 public void onWindowFocusChanged(boolean hasFocus) { 109 if (hasFocus) { 110 showConfirmCredentialActivity(); 111 } 112 } 113 114 @Override 115 public void onDestroy() { 116 unregisterReceiver(mLockEventReceiver); 117 super.onDestroy(); 118 } 119 120 @Override 121 public void onBackPressed() { 122 // Ignore back presses. 123 return; 124 } 125 126 @Override 127 public void setTaskDescription(TaskDescription taskDescription) { 128 // Use the previous activity's task description. 129 } 130 131 private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() { 132 @Override 133 public void onReceive(Context context, Intent intent) { 134 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, mUserId); 135 if (userId == mUserId && !mKgm.isDeviceLocked(mUserId)) { 136 finish(); 137 } 138 } 139 }; 140 141 private void showConfirmCredentialActivity() { 142 if (isFinishing() || !mKgm.isDeviceLocked(mUserId)) { 143 // Don't show the confirm credentials screen if we are already unlocked / unlocking. 144 return; 145 } 146 147 final Intent credential = mKgm.createConfirmDeviceCredentialIntent(null, null, mUserId); 148 if (credential == null) { 149 return; 150 } 151 152 final ActivityOptions options = ActivityOptions.makeBasic(); 153 options.setLaunchTaskId(getTaskId()); 154 155 // Bring this activity back to the foreground after confirming credentials. 156 final PendingIntent target = PendingIntent.getActivity(this, /* request */ -1, getIntent(), 157 PendingIntent.FLAG_CANCEL_CURRENT | 158 PendingIntent.FLAG_ONE_SHOT | 159 PendingIntent.FLAG_IMMUTABLE, options.toBundle()); 160 161 credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender()); 162 try { 163 ActivityManager.getService().startConfirmDeviceCredentialIntent(credential); 164 } catch (RemoteException e) { 165 Log.e(TAG, "Failed to start confirm credential intent", e); 166 } 167 } 168} 169