summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robin Lee <rgl@google.com> 2017-01-19 17:09:28 +0000
committer Robin Lee <rgl@google.com> 2017-02-13 23:22:34 +0000
commit3c82d3d5bfea9b6483ad0264e6956eb5a00a2a4a (patch)
tree786fd05e66063c3a582ad2b9befbc8294f420f81
parentf9a55d42d2e2adbf5895d04e4790debb145508ed (diff)
Theme work lock activity with the task primaryColor
This involves adding another system RPC, getTaskDescription(taskId) gated on MANAGE_ACTIVITY_STACKS permission. Bug: 31001762 Test: runtest -x frameworks/base/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java Change-Id: Ieb996f7fab5bc79737df570e35733551118118d3
-rw-r--r--core/java/android/app/IActivityManager.aidl1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java111
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java14
6 files changed, 187 insertions, 32 deletions
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index c842f788feda..ca17e18ae2e1 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -210,6 +210,7 @@ interface IActivityManager {
boolean killPids(in int[] pids, in String reason, boolean secure);
List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags);
ActivityManager.TaskThumbnail getTaskThumbnail(int taskId);
+ ActivityManager.TaskDescription getTaskDescription(int taskId);
// Retrieve running application processes in the system
List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
// Get device configuration
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 23eaed9007ac..32b5862e2b6b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard;
import static android.app.ActivityManager.TaskDescription;
-import static android.app.ActivityManager.StackId;
import android.annotation.ColorInt;
import android.annotation.UserIdInt;
@@ -32,13 +31,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
-import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Bouncer between work activities and the activity used to confirm credentials before unlocking
* a managed profile.
@@ -51,52 +51,39 @@ public class WorkLockActivity extends Activity {
private static final String TAG = "WorkLockActivity";
/**
- * ID of the locked user that this activity blocks access to.
+ * Contains a {@link TaskDescription} for the activity being covered.
*/
- @UserIdInt
- private int mUserId;
-
+ static final String EXTRA_TASK_DESCRIPTION =
+ "com.android.systemui.keyguard.extra.TASK_DESCRIPTION";
+
/**
- * {@see KeyguardManager}
+ * Cached keyguard manager instance populated by {@link #getKeyguardManager}.
+ * @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);
+ registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL,
+ new IntentFilter(Intent.ACTION_DEVICE_LOCKED_CHANGED), /* 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)) {
+ if (!getKeyguardManager().isDeviceLocked(getTargetUserId())) {
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);
+ blankView.setBackgroundColor(getPrimaryColor());
setContentView(blankView);
}
@@ -127,26 +114,28 @@ public class WorkLockActivity extends Activity {
@Override
public void setTaskDescription(TaskDescription taskDescription) {
- // Use the previous activity's task description.
+ // Leave unset so we 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)) {
+ final int targetUserId = getTargetUserId();
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, targetUserId);
+ if (userId == targetUserId && !getKeyguardManager().isDeviceLocked(targetUserId)) {
finish();
}
}
};
private void showConfirmCredentialActivity() {
- if (isFinishing() || !mKgm.isDeviceLocked(mUserId)) {
+ if (isFinishing() || !getKeyguardManager().isDeviceLocked(getTargetUserId())) {
// Don't show the confirm credentials screen if we are already unlocked / unlocking.
return;
}
- final Intent credential = mKgm.createConfirmDeviceCredentialIntent(null, null, mUserId);
+ final Intent credential = getKeyguardManager()
+ .createConfirmDeviceCredentialIntent(null, null, getTargetUserId());
if (credential == null) {
return;
}
@@ -181,4 +170,32 @@ public class WorkLockActivity extends Activity {
final View view = getWindow().getDecorView();
return ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight());
}
+
+ private KeyguardManager getKeyguardManager() {
+ if (mKgm == null) {
+ mKgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ }
+ return mKgm;
+ }
+
+ @VisibleForTesting
+ @UserIdInt
+ final int getTargetUserId() {
+ return getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+ }
+
+ @VisibleForTesting
+ @ColorInt
+ final int getPrimaryColor() {
+ final TaskDescription taskDescription = (TaskDescription)
+ getIntent().getExtra(EXTRA_TASK_DESCRIPTION);
+ if (taskDescription != null && Color.alpha(taskDescription.getPrimaryColor()) == 255) {
+ return taskDescription.getPrimaryColor();
+ } else {
+ // No task description. Use an organization color set by the policy controller.
+ final DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
+ getSystemService(Context.DEVICE_POLICY_SERVICE);
+ return devicePolicyManager.getOrganizationColorForUser(getTargetUserId());
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index e6483f6332ba..a49c4820aafd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -31,17 +31,21 @@ import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
public class WorkLockActivityController {
private final Context mContext;
+ final SystemServicesProxy mSsp;
public WorkLockActivityController(Context context) {
mContext = context;
+ mSsp = SystemServicesProxy.getInstance(context);
+
EventBus.getDefault().register(this);
- SystemServicesProxy.getInstance(context).registerTaskStackListener(mLockListener);
+ mSsp.registerTaskStackListener(mLockListener);
}
private void startWorkChallengeInTask(int taskId, int userId) {
Intent intent = new Intent(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER)
.setComponent(new ComponentName(mContext, WorkLockActivity.class))
.putExtra(Intent.EXTRA_USER_ID, userId)
+ .putExtra(WorkLockActivity.EXTRA_TASK_DESCRIPTION, mSsp.getTaskDescription(taskId))
.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 49074a6f535d..eae1b8155486 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -868,6 +868,14 @@ public class SystemServicesProxy {
return null;
}
+ public ActivityManager.TaskDescription getTaskDescription(int taskId) {
+ try {
+ return mIam.getTaskDescription(taskId);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
/**
* Returns the given icon for a user, badging if necessary.
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
new file mode 100644
index 000000000000..9b868dbff714
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.annotation.ColorInt;
+import android.annotation.UserIdInt;
+import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Looper;
+
+import com.android.systemui.keyguard.WorkLockActivity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * runtest systemui -c com.android.systemui.keyguard.WorkLockActivityTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WorkLockActivityTest {
+ private static final @UserIdInt int USER_ID = 270;
+ private static final String TASK_LABEL = "task label";
+
+ private @Mock DevicePolicyManager mDevicePolicyManager;
+ private @Mock KeyguardManager mKeyguardManager;
+ private @Mock Context mContext;
+
+ private WorkLockActivity mActivity;
+
+ private static class WorkLockActivityTestable extends WorkLockActivity {
+ WorkLockActivityTestable(Context baseContext) {
+ super();
+ attachBaseContext(baseContext);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getSystemService(eq(Context.DEVICE_POLICY_SERVICE)))
+ .thenReturn(mDevicePolicyManager);
+ when(mContext.getSystemService(eq(Context.KEYGUARD_SERVICE)))
+ .thenReturn(mKeyguardManager);
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ mActivity = new WorkLockActivityTestable(mContext);
+ }
+
+ @Test
+ public void testBackgroundAlwaysOpaque() throws Exception {
+ final @ColorInt int orgColor = Color.rgb(250, 199, 67);
+ when(mDevicePolicyManager.getOrganizationColorForUser(eq(USER_ID))).thenReturn(orgColor);
+
+ final @ColorInt int opaqueColor= Color.rgb(164, 198, 57);
+ final @ColorInt int transparentColor = Color.argb(0, 0, 0, 0);
+ TaskDescription opaque = new TaskDescription(null, null, opaqueColor);
+ TaskDescription transparent = new TaskDescription(null, null, transparentColor);
+
+ // When a task description is provided with a suitable (opaque) primaryColor, it should be
+ // used as the scrim's background color.
+ mActivity.setIntent(new Intent()
+ .putExtra(Intent.EXTRA_USER_ID, USER_ID)
+ .putExtra(WorkLockActivity.EXTRA_TASK_DESCRIPTION, opaque));
+ assertEquals(opaqueColor, mActivity.getPrimaryColor());
+
+ // When a task description is provided but has no primaryColor / the primaryColor is
+ // transparent, the organization color should be used instead.
+ mActivity.setIntent(new Intent()
+ .putExtra(Intent.EXTRA_USER_ID, USER_ID)
+ .putExtra(WorkLockActivity.EXTRA_TASK_DESCRIPTION, transparent));
+ assertEquals(orgColor, mActivity.getPrimaryColor());
+
+ // When no task description is provided at all, it should be treated like a transparent
+ // description and the organization color shown instead.
+ mActivity.setIntent(new Intent()
+ .putExtra(Intent.EXTRA_USER_ID, USER_ID));
+ assertEquals(orgColor, mActivity.getPrimaryColor());
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 93fb9114beba..c03c562307a6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9580,6 +9580,20 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public ActivityManager.TaskDescription getTaskDescription(int id) {
+ synchronized (this) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "getTaskDescription()");
+ final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
+ id, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
+ if (tr != null) {
+ return tr.lastTaskDescription;
+ }
+ }
+ return null;
+ }
+
+ @Override
public int addAppTask(IBinder activityToken, Intent intent,
ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
final int callingUid = Binder.getCallingUid();