Loading core/java/android/app/IActivityManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java +48 −31 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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); } Loading Loading @@ -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; } Loading Loading @@ -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()); } } } packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java +5 −1 Original line number Diff line number Diff line Loading @@ -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); Loading packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * 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()); } } Loading
core/java/android/app/IActivityManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java +48 −31 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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); } Loading Loading @@ -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; } Loading Loading @@ -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()); } } }
packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java +5 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * 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()); } }