Add enterprise disclosure to Keyguard screen

With this CL, a disclosure text is shown on the Keyguard screen when
a Device Owner is managing the device.

Bug: 32692748
Test: runtest --path frameworks/base/packages/SystemUI/tests

Change-Id: I7a48df7dc010c39b2db94fcd26b75313a7ceee08
This commit is contained in:
Bartosz Fabianowski
2016-12-01 10:36:18 +01:00
parent 52a0daed89
commit 5f045007e0
8 changed files with 250 additions and 21 deletions

View File

@@ -24,17 +24,36 @@
android:outlineProvider="none"
android:elevation="5dp" > <!-- Put it above the status bar header -->
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text"
<LinearLayout
android:id="@+id/keyguard_indication_area"
android:forceHasOverlappingRendering="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
android:layout_gravity="bottom|center_horizontal"
android:gravity="center_horizontal"
android:textStyle="italic"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceSmall"
android:accessibilityLiveRegion="polite" />
android:orientation="vertical">
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_enterprise_disclosure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textStyle="italic"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="gone" />
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textStyle="italic"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceSmall"
android:accessibilityLiveRegion="polite" />
</LinearLayout>
<FrameLayout
android:id="@+id/preview_container"

View File

@@ -840,6 +840,12 @@
<!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to unlock</string>
<!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
<string name="do_disclosure_generic">This device is managed</string>
<!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
<string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
<!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
<string name="phone_hint">Swipe from icon for phone</string>

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -36,6 +37,7 @@ import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.app.IBatteryStats;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -58,7 +60,9 @@ public class KeyguardIndicationController {
private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private final Context mContext;
private final ViewGroup mIndicationArea;
private final KeyguardIndicationTextView mTextView;
private final KeyguardIndicationTextView mDisclosure;
private final UserManager mUserManager;
private final IBatteryStats mBatteryInfo;
@@ -78,10 +82,16 @@ public class KeyguardIndicationController {
private int mChargingWattage;
private String mMessageToShowOnScreenOn;
public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView,
LockIcon lockIcon) {
private final DevicePolicyManager mDevicePolicyManager;
public KeyguardIndicationController(Context context, ViewGroup indicationArea,
LockIcon lockIcon) {
mContext = context;
mTextView = textView;
mIndicationArea = indicationArea;
mTextView = (KeyguardIndicationTextView) indicationArea.findViewById(
R.id.keyguard_indication_text);
mDisclosure = (KeyguardIndicationTextView) indicationArea.findViewById(
R.id.keyguard_indication_enterprise_disclosure);
mLockIcon = lockIcon;
Resources res = context.getResources();
@@ -92,14 +102,39 @@ public class KeyguardIndicationController {
mBatteryInfo = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitor);
context.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
new IntentFilter(Intent.ACTION_TIME_TICK), null, null);
updateDisclosure();
}
private void updateDisclosure() {
if (mDevicePolicyManager == null) {
return;
}
if (mDevicePolicyManager.isDeviceManaged()) {
final CharSequence organizationName =
mDevicePolicyManager.getDeviceOwnerOrganizationName();
if (organizationName != null) {
mDisclosure.switchIndication(mContext.getResources().getString(
R.string.do_disclosure_with_name, organizationName));
} else {
mDisclosure.switchIndication(R.string.do_disclosure_generic);
}
mDisclosure.setVisibility(View.VISIBLE);
} else {
mDisclosure.setVisibility(View.GONE);
}
}
public void setVisible(boolean visible) {
mVisible = visible;
mTextView.setVisibility(visible ? View.VISIBLE : View.GONE);
mIndicationArea.setVisibility(visible ? View.VISIBLE : View.GONE);
if (visible) {
hideTransientIndication();
updateIndication();
@@ -241,6 +276,13 @@ public class KeyguardIndicationController {
updateIndication();
}
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (showing) {
updateDisclosure();
}
}
@Override
public void onFingerprintHelp(int msgId, String helpString) {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);

View File

@@ -107,6 +107,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private KeyguardAffordanceView mRightAffordanceView;
private KeyguardAffordanceView mLeftAffordanceView;
private LockIcon mLockIcon;
private ViewGroup mIndicationArea;
private TextView mEnterpriseDisclosure;
private TextView mIndicationText;
private ViewGroup mPreviewContainer;
@@ -208,6 +210,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mRightAffordanceView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
mIndicationArea = (ViewGroup) findViewById(R.id.keyguard_indication_area);
mEnterpriseDisclosure = (TextView) findViewById(
R.id.keyguard_indication_enterprise_disclosure);
mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
watchForCameraPolicyChanges();
updateCameraVisibility();
@@ -252,13 +257,16 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
super.onConfigurationChanged(newConfig);
int indicationBottomMargin = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_margin_bottom);
MarginLayoutParams mlp = (MarginLayoutParams) mIndicationText.getLayoutParams();
MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
if (mlp.bottomMargin != indicationBottomMargin) {
mlp.bottomMargin = indicationBottomMargin;
mIndicationText.setLayoutParams(mlp);
mIndicationArea.setLayoutParams(mlp);
}
// Respect font size setting.
mEnterpriseDisclosure.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material));
mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material));
@@ -595,8 +603,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return mLockIcon;
}
public View getIndicationView() {
return mIndicationText;
public View getIndicationArea() {
return mIndicationArea;
}
@Override
@@ -658,8 +666,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
startFinishDozeAnimationElement(mRightAffordanceView, delay);
}
mIndicationText.setAlpha(0f);
mIndicationText.animate()
mIndicationArea.setAlpha(0f);
mIndicationArea.animate()
.alpha(1f)
.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);

View File

@@ -1006,14 +1006,14 @@ public abstract class PanelView extends FrameLayout {
});
animator.start();
mHeightAnimator = animator;
mKeyguardBottomArea.getIndicationView().animate()
mKeyguardBottomArea.getIndicationArea().animate()
.translationY(-mHintDistance)
.setDuration(250)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.withEndAction(new Runnable() {
@Override
public void run() {
mKeyguardBottomArea.getIndicationView().animate()
mKeyguardBottomArea.getIndicationArea().animate()
.translationY(0)
.setDuration(450)
.setInterpolator(mBounceInterpolator)

View File

@@ -857,8 +857,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text),
(ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);

View File

@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
<application>
<uses-library android:name="android.test.runner" />

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2016 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.statusbar;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.SubscriptionManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.view.ViewGroup;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KeyguardIndicationControllerTest extends SysuiTestCase {
private final String ORGANIZATION_NAME = "organization";
private final String DISCLOSURE_WITH_ORGANIZATION_NAME = "managed by organization";
private Context mContext = mock(Context.class);
private DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
private ViewGroup mIndicationArea = mock(ViewGroup.class);
private KeyguardIndicationTextView mDisclosure = mock(KeyguardIndicationTextView.class);
private KeyguardIndicationController mController;
@Before
public void setUp() throws Exception {
final Resources resources = mock(Resources.class);
when(mContext.getResources()).thenReturn(resources);
when(mContext.getContentResolver()).thenReturn(mock(ContentResolver.class));
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(
mock(SubscriptionManager.class));
when(mContext.getSystemService(Context.TRUST_SERVICE)).thenReturn(
mock(TrustManager.class));
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
mDevicePolicyManager);
when(resources.getString(R.string.do_disclosure_with_name, ORGANIZATION_NAME))
.thenReturn(DISCLOSURE_WITH_ORGANIZATION_NAME);
when(mIndicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure))
.thenReturn(mDisclosure);
}
private void createController() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
mController = new KeyguardIndicationController(mContext, mIndicationArea, null);
}
@Test
public void unmanaged() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
createController();
verify(mDisclosure).setVisibility(View.GONE);
verifyNoMoreInteractions(mDisclosure);
}
@Test
public void managedNoOwnerName() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
createController();
verify(mDisclosure).setVisibility(View.VISIBLE);
verify(mDisclosure).switchIndication(R.string.do_disclosure_generic);
verifyNoMoreInteractions(mDisclosure);
}
@Test
public void managedOwnerName() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME);
createController();
verify(mDisclosure).setVisibility(View.VISIBLE);
verify(mDisclosure).switchIndication(DISCLOSURE_WITH_ORGANIZATION_NAME);
verifyNoMoreInteractions(mDisclosure);
}
@Test
public void updateOnTheFly() {
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
createController();
final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
reset(mDisclosure);
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
monitor.onKeyguardVisibilityChanged(true);
verify(mDisclosure).setVisibility(View.VISIBLE);
verify(mDisclosure).switchIndication(R.string.do_disclosure_generic);
verifyNoMoreInteractions(mDisclosure);
reset(mDisclosure);
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(ORGANIZATION_NAME);
monitor.onKeyguardVisibilityChanged(false);
monitor.onKeyguardVisibilityChanged(true);
verify(mDisclosure).setVisibility(View.VISIBLE);
verify(mDisclosure).switchIndication(DISCLOSURE_WITH_ORGANIZATION_NAME);
verifyNoMoreInteractions(mDisclosure);
reset(mDisclosure);
when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
monitor.onKeyguardVisibilityChanged(false);
monitor.onKeyguardVisibilityChanged(true);
verify(mDisclosure).setVisibility(View.GONE);
verifyNoMoreInteractions(mDisclosure);
}
}