Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cb86732 authored by Robin Lee's avatar Robin Lee Committed by Android (Google) Code Review
Browse files

Merge "Theme work lock activity with the task primaryColor"

parents 492a058d 3c82d3d5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+48 −31
Original line number Diff line number Diff line
@@ -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());
        }
    }
}
+5 −1
Original line number Diff line number Diff line
@@ -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);

+8 −0
Original line number Diff line number Diff line
@@ -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.
     */
+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