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:
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user