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
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 444f0f0..078f9d7 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -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"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5fec647..af1fc59 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 0ef97152..218c1bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -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.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 @@
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 @@
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 @@
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();
@@ -242,6 +277,13 @@
}
@Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ if (showing) {
+ updateDisclosure();
+ }
+ }
+
+ @Override
public void onFingerprintHelp(int msgId, String helpString) {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 89defec..daa57c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -107,6 +107,8 @@
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 @@
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 @@
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 @@
return mLockIcon;
}
- public View getIndicationView() {
- return mIndicationText;
+ public View getIndicationArea() {
+ return mIndicationArea;
}
@Override
@@ -658,8 +666,8 @@
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);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 570d5d4..f16c834 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -1006,14 +1006,14 @@
});
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)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2a5fc6e..2b74c847 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -857,8 +857,7 @@
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);
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 6e17cf4..b03189c 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -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" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
new file mode 100644
index 0000000..639c8da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -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);
+ }
+}