Support showing alignment hint based on aligniment state of dock

Bug: 141984730
Test: atest SystemUITests:KeyguardIndicationControllerTest
Change-Id: Ic0911683725a0e54406df06b948169c4dde94764
This commit is contained in:
Jerry Chang
2019-11-15 06:52:54 +08:00
parent 31e0679dd7
commit 6a8fb02aa7
6 changed files with 181 additions and 11 deletions

View File

@@ -986,6 +986,12 @@
<!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] --> <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
<string name="keyguard_retry">Swipe up to try again</string> <string name="keyguard_retry">Swipe up to try again</string>
<!-- Indication when device is slow charging due to misalignment on the dock. [CHAR LIMIT=60] -->
<string name="dock_alignment_slow_charging" product="default">Realign phone for faster charging</string>
<!-- Indication when device is not charging due to bad placement on the dock. [CHAR LIMIT=60] -->
<string name="dock_alignment_not_charging" product="default">Realign phone to charge wirelessly</string>
<!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] --> <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
<string name="do_disclosure_generic">This device is managed by your organization</string> <string name="do_disclosure_generic">This device is managed by your organization</string>

View File

@@ -17,12 +17,12 @@
package com.android.systemui.dock; package com.android.systemui.dock;
/** /**
* Allows an app to handle dock events * Allows an app to handle dock events.
*/ */
public interface DockManager { public interface DockManager {
/** /**
* Uninitialized / undocking dock states * Uninitialized / undocking dock states.
*/ */
int STATE_NONE = 0; int STATE_NONE = 0;
/** /**
@@ -30,24 +30,53 @@ public interface DockManager {
*/ */
int STATE_DOCKED = 1; int STATE_DOCKED = 1;
/** /**
* The state for docking without showing UI * The state for docking without showing UI.
*/ */
int STATE_DOCKED_HIDE = 2; int STATE_DOCKED_HIDE = 2;
/** /**
* Add a dock event listener into manager * Indicates there's no alignment issue.
*/
int ALIGN_STATE_GOOD = 0;
/**
* Indicates it's slightly not aligned with dock.
*/
int ALIGN_STATE_POOR = 1;
/**
* Indicates it's not aligned with dock.
*/
int ALIGN_STATE_TERRIBLE = 2;
/**
* Adds a dock event listener into manager.
* *
* @param callback A {@link DockEventListener} which want to add * @param callback A {@link DockEventListener} which want to add
*/ */
void addListener(DockEventListener callback); void addListener(DockEventListener callback);
/** /**
* Remove the added listener from dock manager * Removes the added listener from dock manager
* *
* @param callback A {@link DockEventListener} which want to remove * @param callback A {@link DockEventListener} which want to remove
*/ */
void removeListener(DockEventListener callback); void removeListener(DockEventListener callback);
/**
* Adds a alignment listener into manager.
*
* @param listener A {@link AlignmentStateListener} which want to add
*/
void addAlignmentStateListener(AlignmentStateListener listener);
/**
* Removes the added alignment listener from dock manager.
*
* @param listener A {@link AlignmentStateListener} which want to remove
*/
void removeAlignmentStateListener(AlignmentStateListener listener);
/** /**
* Returns true if the device is in docking state. * Returns true if the device is in docking state.
*/ */
@@ -58,11 +87,23 @@ public interface DockManager {
*/ */
boolean isHidden(); boolean isHidden();
/** Callback for receiving dock events */ /**
* Listens to dock events.
*/
interface DockEventListener { interface DockEventListener {
/** /**
* Override to handle dock events * Override to handle dock events.
*/ */
void onEvent(int event); void onEvent(int event);
} }
/**
* Listens to dock alignment state changed.
*/
interface AlignmentStateListener {
/**
* Override to handle alignment state changes.
*/
void onAlignmentStateChanged(int alignState);
}
} }

View File

@@ -34,6 +34,14 @@ public class DockManagerImpl implements DockManager {
public void removeListener(DockEventListener callback) { public void removeListener(DockEventListener callback) {
} }
@Override
public void addAlignmentStateListener(AlignmentStateListener listener) {
}
@Override
public void removeAlignmentStateListener(AlignmentStateListener listener) {
}
@Override @Override
public boolean isDocked() { public boolean isDocked() {
return false; return false;

View File

@@ -50,6 +50,7 @@ import com.android.settingslib.Utils;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView; import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -95,6 +96,7 @@ public class KeyguardIndicationController implements StateListener,
private final IBatteryStats mBatteryInfo; private final IBatteryStats mBatteryInfo;
private final SettableWakeLock mWakeLock; private final SettableWakeLock mWakeLock;
private final LockPatternUtils mLockPatternUtils; private final LockPatternUtils mLockPatternUtils;
private final DockManager mDockManager;
private final int mSlowThreshold; private final int mSlowThreshold;
private final int mFastThreshold; private final int mFastThreshold;
@@ -103,6 +105,7 @@ public class KeyguardIndicationController implements StateListener,
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private String mRestingIndication; private String mRestingIndication;
private String mAlignmentIndication;
private CharSequence mTransientIndication; private CharSequence mTransientIndication;
private ColorStateList mTransientTextColorState; private ColorStateList mTransientTextColorState;
private ColorStateList mInitialTextColorState; private ColorStateList mInitialTextColorState;
@@ -140,7 +143,8 @@ public class KeyguardIndicationController implements StateListener,
Dependency.get(AccessibilityController.class), Dependency.get(AccessibilityController.class),
Dependency.get(KeyguardStateController.class), Dependency.get(KeyguardStateController.class),
Dependency.get(StatusBarStateController.class), Dependency.get(StatusBarStateController.class),
Dependency.get(KeyguardUpdateMonitor.class)); Dependency.get(KeyguardUpdateMonitor.class),
Dependency.get(DockManager.class));
} }
/** /**
@@ -152,7 +156,8 @@ public class KeyguardIndicationController implements StateListener,
AccessibilityController accessibilityController, AccessibilityController accessibilityController,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController, StatusBarStateController statusBarStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor) { KeyguardUpdateMonitor keyguardUpdateMonitor,
DockManager dockManager) {
mContext = context; mContext = context;
mLockIcon = lockIcon; mLockIcon = lockIcon;
mShadeController = shadeController; mShadeController = shadeController;
@@ -160,6 +165,8 @@ public class KeyguardIndicationController implements StateListener,
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mStatusBarStateController = statusBarStateController; mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDockManager = dockManager;
mDockManager.addAlignmentStateListener(this::handleAlignStateChanged);
// lock icon is not used on all form factors. // lock icon is not used on all form factors.
if (mLockIcon != null) { if (mLockIcon != null) {
mLockIcon.setOnLongClickListener(this::handleLockLongClick); mLockIcon.setOnLongClickListener(this::handleLockLongClick);
@@ -211,6 +218,21 @@ public class KeyguardIndicationController implements StateListener,
mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
} }
private void handleAlignStateChanged(int alignState) {
String alignmentIndication = "";
if (alignState == DockManager.ALIGN_STATE_POOR) {
alignmentIndication =
mContext.getResources().getString(R.string.dock_alignment_slow_charging);
} else if (alignState == DockManager.ALIGN_STATE_TERRIBLE) {
alignmentIndication =
mContext.getResources().getString(R.string.dock_alignment_not_charging);
}
if (!alignmentIndication.equals(mAlignmentIndication)) {
mAlignmentIndication = alignmentIndication;
updateIndication(false);
}
}
/** /**
* Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this * Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this
* {@link KeyguardIndicationController}. * {@link KeyguardIndicationController}.
@@ -234,7 +256,7 @@ public class KeyguardIndicationController implements StateListener,
if (visible) { if (visible) {
// If this is called after an error message was already shown, we should not clear it. // If this is called after an error message was already shown, we should not clear it.
// Otherwise the error message won't be shown // Otherwise the error message won't be shown
if (!mHandler.hasMessages(MSG_HIDE_TRANSIENT)) { if (!mHandler.hasMessages(MSG_HIDE_TRANSIENT)) {
hideTransientIndication(); hideTransientIndication();
} }
updateIndication(false); updateIndication(false);
@@ -345,6 +367,9 @@ public class KeyguardIndicationController implements StateListener,
mTextView.setTextColor(Color.WHITE); mTextView.setTextColor(Color.WHITE);
if (!TextUtils.isEmpty(mTransientIndication)) { if (!TextUtils.isEmpty(mTransientIndication)) {
mTextView.switchIndication(mTransientIndication); mTextView.switchIndication(mTransientIndication);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
mTextView.setTextColor(Utils.getColorError(mContext));
} else if (mPowerPluggedIn) { } else if (mPowerPluggedIn) {
String indication = computePowerIndication(); String indication = computePowerIndication();
if (animate) { if (animate) {
@@ -373,6 +398,9 @@ public class KeyguardIndicationController implements StateListener,
&& mKeyguardUpdateMonitor.getUserHasTrust(userId)) { && mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
mTextView.switchIndication(trustGrantedIndication); mTextView.switchIndication(trustGrantedIndication);
mTextView.setTextColor(mInitialTextColorState); mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
mTextView.setTextColor(Utils.getColorError(mContext));
} else if (mPowerPluggedIn) { } else if (mPowerPluggedIn) {
String indication = computePowerIndication(); String indication = computePowerIndication();
if (DEBUG_CHARGING_SPEED) { if (DEBUG_CHARGING_SPEED) {

View File

@@ -21,6 +21,7 @@ package com.android.systemui.dock;
*/ */
public class DockManagerFake implements DockManager { public class DockManagerFake implements DockManager {
DockEventListener mCallback; DockEventListener mCallback;
AlignmentStateListener mAlignmentListener;
@Override @Override
public void addListener(DockEventListener callback) { public void addListener(DockEventListener callback) {
@@ -32,6 +33,16 @@ public class DockManagerFake implements DockManager {
this.mCallback = null; this.mCallback = null;
} }
@Override
public void addAlignmentStateListener(AlignmentStateListener listener) {
mAlignmentListener = listener;
}
@Override
public void removeAlignmentStateListener(AlignmentStateListener listener) {
mAlignmentListener = listener;
}
@Override @Override
public boolean isDocked() { public boolean isDocked() {
return false; return false;

View File

@@ -48,8 +48,10 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView; import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockIcon;
@@ -63,6 +65,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -92,6 +95,10 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
@Mock
private DockManager mDockManager;
@Captor
private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener;
private KeyguardIndicationTextView mTextView; private KeyguardIndicationTextView mTextView;
private KeyguardIndicationController mController; private KeyguardIndicationController mController;
@@ -123,10 +130,79 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
} }
mController = new KeyguardIndicationController(mContext, mIndicationArea, mLockIcon, mController = new KeyguardIndicationController(mContext, mIndicationArea, mLockIcon,
mLockPatternUtils, mWakeLock, mShadeController, mAccessibilityController, mLockPatternUtils, mWakeLock, mShadeController, mAccessibilityController,
mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor); mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
mDockManager);
mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
} }
@Test
public void createController_addsAlignmentListener() {
createController();
verify(mDockManager).addAlignmentStateListener(
any(DockManager.AlignmentStateListener.class));
}
@Test
public void onAlignmentStateChanged_showsSlowChargingIndication() {
createController();
verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture());
mController.setVisible(true);
mAlignmentListener.getValue().onAlignmentStateChanged(
DockManager.ALIGN_STATE_POOR);
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_slow_charging));
assertThat(mTextView.getCurrentTextColor()).isEqualTo(
Utils.getColorError(mContext).getDefaultColor());
}
@Test
public void onAlignmentStateChanged_showsNotChargingIndication() {
createController();
verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture());
mController.setVisible(true);
mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_TERRIBLE);
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_not_charging));
assertThat(mTextView.getCurrentTextColor()).isEqualTo(
Utils.getColorError(mContext).getDefaultColor());
}
@Test
public void onAlignmentStateChanged_whileDozing_showsSlowChargingIndication() {
createController();
verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture());
mController.setVisible(true);
mController.setDozing(true);
mAlignmentListener.getValue().onAlignmentStateChanged(
DockManager.ALIGN_STATE_POOR);
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_slow_charging));
assertThat(mTextView.getCurrentTextColor()).isEqualTo(
Utils.getColorError(mContext).getDefaultColor());
}
@Test
public void onAlignmentStateChanged_whileDozing_showsNotChargingIndication() {
createController();
verify(mDockManager).addAlignmentStateListener(mAlignmentListener.capture());
mController.setVisible(true);
mController.setDozing(true);
mAlignmentListener.getValue().onAlignmentStateChanged(DockManager.ALIGN_STATE_TERRIBLE);
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_not_charging));
assertThat(mTextView.getCurrentTextColor()).isEqualTo(
Utils.getColorError(mContext).getDefaultColor());
}
@Test @Test
public void transientIndication_holdsWakeLock_whenDozing() { public void transientIndication_holdsWakeLock_whenDozing() {
createController(); createController();