blob: c7514a90dce32765620d8a455842f3bf70c183b0 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.keyguard;
import static android.app.ActivityManager.TaskDescription;
import android.annotation.ColorInt;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
/**
* Bouncer between work activities and the activity used to confirm credentials before unlocking
* a managed profile.
* <p>
* Shows a solid color when started, based on the organization color of the user it is supposed to
* be blocking. Once focused, it switches to a screen to confirm credentials and auto-dismisses if
* credentials are accepted.
*/
public class WorkLockActivity extends Activity {
private static final String TAG = "WorkLockActivity";
/**
* ID of the locked user that this activity blocks access to.
*/
@UserIdInt
private int mUserId;
/**
* {@see KeyguardManager}
*/
private KeyguardManager mKgm;
/**
* {@see DevicePolicyManager}
*/
private DevicePolicyManager mDpm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mKgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
final IntentFilter lockFilter = new IntentFilter();
lockFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL, lockFilter,
/* permission */ null, /* scheduler */ null);
// Once the receiver is registered, check whether anything happened between now and the time
// when this activity was launched. If it did and the user is unlocked now, just quit.
if (!mKgm.isDeviceLocked(mUserId)) {
finish();
return;
}
// Get the organization color; this is a 24-bit integer provided by a DPC, guaranteed to
// be completely opaque.
final @ColorInt int color = mDpm.getOrganizationColorForUser(mUserId);
// Draw captions overlaid on the content view, so the whole window is one solid color.
setOverlayWithDecorCaptionEnabled(true);
// Blank out the activity. When it is on-screen it will look like a Recents thumbnail with
// redaction switched on.
final View blankView = new View(this);
blankView.setBackgroundColor(color);
setContentView(blankView);
}
/**
* Respond to focus events by showing the prompt to confirm credentials.
* <p>
* We don't have anything particularly interesting to show here (just a solid-colored page) so
* there is no sense in sitting in the foreground doing nothing.
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
showConfirmCredentialActivity();
}
}
@Override
public void onDestroy() {
unregisterReceiver(mLockEventReceiver);
super.onDestroy();
}
@Override
public void onBackPressed() {
// Ignore back presses.
return;
}
@Override
public void setTaskDescription(TaskDescription taskDescription) {
// Use the previous activity's task description.
}
private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, mUserId);
if (userId == mUserId && !mKgm.isDeviceLocked(mUserId)) {
finish();
}
}
};
private void showConfirmCredentialActivity() {
if (isFinishing() || !mKgm.isDeviceLocked(mUserId)) {
// Don't show the confirm credentials screen if we are already unlocked / unlocking.
return;
}
final Intent credential = mKgm.createConfirmDeviceCredentialIntent(null, null, mUserId);
if (credential == null) {
return;
}
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchTaskId(getTaskId());
// Bring this activity back to the foreground after confirming credentials.
final PendingIntent target = PendingIntent.getActivity(this, /* request */ -1, getIntent(),
PendingIntent.FLAG_CANCEL_CURRENT |
PendingIntent.FLAG_ONE_SHOT |
PendingIntent.FLAG_IMMUTABLE, options.toBundle());
credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
try {
ActivityManager.getService().startConfirmDeviceCredentialIntent(credential);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start confirm credential intent", e);
}
}
}