[DO NOT MERGE] Controls Lockscreen affordance
Place a button on the lockscreen similar to the wallet affordance. Only enable the button if: 1. User has enabled the setting 2. Device control services are enabled 3. The user has favorited at least 1 control Fixes: 194435266 Test: manual Change-Id: Idc755656e2d3b7df77bf95d06f076b63349ece9a
This commit is contained in:
@@ -82,18 +82,32 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/wallet_button"
|
||||
android:layout_height="@dimen/keyguard_affordance_wallet_height"
|
||||
android:layout_width="@dimen/keyguard_affordance_wallet_width"
|
||||
android:layout_height="@dimen/keyguard_affordance_fixed_height"
|
||||
android:layout_width="@dimen/keyguard_affordance_fixed_width"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:src="@drawable/ic_wallet_lockscreen"
|
||||
android:background="@drawable/wallet_lockscreen_bg"
|
||||
android:background="@drawable/keyguard_bottom_affordance_bg"
|
||||
android:layout_marginEnd="@dimen/keyguard_affordance_horizontal_offset"
|
||||
android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
|
||||
android:contentDescription="@string/accessibility_wallet_button"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/controls_button"
|
||||
android:layout_height="@dimen/keyguard_affordance_fixed_height"
|
||||
android:layout_width="@dimen/keyguard_affordance_fixed_width"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:src="@drawable/ic_device_light"
|
||||
android:background="@drawable/keyguard_bottom_affordance_bg"
|
||||
android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset"
|
||||
android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
|
||||
android:contentDescription="@string/quick_controls_title"
|
||||
android:visibility="gone" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/overlay_container"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -906,8 +906,8 @@
|
||||
<dimen name="keyguard_affordance_height">48dp</dimen>
|
||||
<dimen name="keyguard_affordance_width">48dp</dimen>
|
||||
|
||||
<dimen name="keyguard_affordance_wallet_height">48dp</dimen>
|
||||
<dimen name="keyguard_affordance_wallet_width">48dp</dimen>
|
||||
<dimen name="keyguard_affordance_fixed_height">48dp</dimen>
|
||||
<dimen name="keyguard_affordance_fixed_width">48dp</dimen>
|
||||
|
||||
<dimen name="keyguard_affordance_horizontal_offset">32dp</dimen>
|
||||
<dimen name="keyguard_affordance_vertical_offset">32dp</dimen>
|
||||
|
||||
@@ -764,6 +764,8 @@
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
<item name="android:windowAnimationStyle">@null</item>
|
||||
<item name="android:statusBarColor">@android:color/black</item>
|
||||
<!-- Setting a placeholder will avoid using the SystemUI icon on the splash screen -->
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_blank</item>
|
||||
<item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
|
||||
</style>
|
||||
|
||||
@@ -898,5 +900,7 @@
|
||||
<style name="Wallet.Theme" parent="@android:style/Theme.DeviceDefault">
|
||||
<item name="android:colorBackground">@android:color/system_neutral1_900</item>
|
||||
<item name="android:itemBackground">@android:color/system_neutral1_800</item>
|
||||
<!-- Setting a placeholder will avoid using the SystemUI icon on the splash screen. -->
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_blank</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
|
||||
import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE;
|
||||
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
|
||||
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
|
||||
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
|
||||
@@ -40,6 +41,7 @@ import android.content.ServiceConnection;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
@@ -81,6 +83,11 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.assist.AssistManager;
|
||||
import com.android.systemui.camera.CameraIntents;
|
||||
import com.android.systemui.controls.ControlsServiceInfo;
|
||||
import com.android.systemui.controls.dagger.ControlsComponent;
|
||||
import com.android.systemui.controls.management.ControlsListingController;
|
||||
import com.android.systemui.controls.ui.ControlsActivity;
|
||||
import com.android.systemui.controls.ui.ControlsUiController;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.plugins.IntentButtonProvider;
|
||||
@@ -98,6 +105,8 @@ import com.android.systemui.tuner.TunerService;
|
||||
import com.android.systemui.wallet.controller.QuickAccessWalletController;
|
||||
import com.android.systemui.wallet.ui.WalletActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
|
||||
* text.
|
||||
@@ -133,9 +142,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
private KeyguardAffordanceView mLeftAffordanceView;
|
||||
|
||||
private ImageView mWalletButton;
|
||||
private ImageView mControlsButton;
|
||||
private boolean mHasCard = false;
|
||||
private WalletCardRetriever mCardRetriever = new WalletCardRetriever();
|
||||
private QuickAccessWalletController mQuickAccessWalletController;
|
||||
private ControlsComponent mControlsComponent;
|
||||
private boolean mControlServicesAvailable = false;
|
||||
|
||||
private ViewGroup mIndicationArea;
|
||||
private TextView mIndicationText;
|
||||
@@ -188,6 +200,19 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
private ActivityIntentHelper mActivityIntentHelper;
|
||||
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
private ControlsListingController.ControlsListingCallback mListingCallback =
|
||||
new ControlsListingController.ControlsListingCallback() {
|
||||
public void onServicesUpdated(List<ControlsServiceInfo> serviceInfos) {
|
||||
boolean available = !serviceInfos.isEmpty();
|
||||
|
||||
if (available != mControlServicesAvailable) {
|
||||
mControlServicesAvailable = available;
|
||||
updateControlsVisibility();
|
||||
updateAffordanceColors();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public KeyguardBottomAreaView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -253,6 +278,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mRightAffordanceView = findViewById(R.id.camera_button);
|
||||
mLeftAffordanceView = findViewById(R.id.left_button);
|
||||
mWalletButton = findViewById(R.id.wallet_button);
|
||||
mControlsButton = findViewById(R.id.controls_button);
|
||||
mIndicationArea = findViewById(R.id.keyguard_indication_area);
|
||||
mIndicationText = findViewById(R.id.keyguard_indication_text);
|
||||
mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom);
|
||||
@@ -276,6 +302,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mIndicationPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_indication_area_padding);
|
||||
updateWalletVisibility();
|
||||
updateControlsVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,6 +355,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mQuickAccessWalletController.unregisterWalletChangeObservers(
|
||||
WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE);
|
||||
}
|
||||
|
||||
if (mControlsComponent != null) {
|
||||
mControlsComponent.getControlsListingController().ifPresent(
|
||||
c -> c.removeCallback(mListingCallback));
|
||||
}
|
||||
}
|
||||
|
||||
private void initAccessibility() {
|
||||
@@ -369,13 +401,20 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
updateLeftAffordanceIcon();
|
||||
|
||||
lp = mWalletButton.getLayoutParams();
|
||||
lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
|
||||
lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_wallet_width);
|
||||
lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width);
|
||||
lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height);
|
||||
mWalletButton.setLayoutParams(lp);
|
||||
|
||||
lp = mControlsButton.getLayoutParams();
|
||||
lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width);
|
||||
lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height);
|
||||
mControlsButton.setLayoutParams(lp);
|
||||
|
||||
mIndicationPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_indication_area_padding);
|
||||
|
||||
updateWalletVisibility();
|
||||
updateAffordanceColors();
|
||||
}
|
||||
|
||||
private void updateRightAffordanceIcon() {
|
||||
@@ -454,22 +493,38 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
|| !mQuickAccessWalletController.isWalletEnabled()
|
||||
|| !mHasCard) {
|
||||
mWalletButton.setVisibility(GONE);
|
||||
mIndicationArea.setPadding(0, 0, 0, 0);
|
||||
} else {
|
||||
Drawable tileIcon = mQuickAccessWalletController.getWalletClient().getTileIcon();
|
||||
if (tileIcon != null) {
|
||||
mWalletButton.setImageDrawable(tileIcon);
|
||||
|
||||
if (mControlsButton.getVisibility() == GONE) {
|
||||
mIndicationArea.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
mWalletButton.getDrawable().setTint(
|
||||
Utils.getColorAttr(
|
||||
mContext,
|
||||
com.android.internal.R.attr.textColorPrimary).getDefaultColor());
|
||||
} else {
|
||||
mWalletButton.setVisibility(VISIBLE);
|
||||
mWalletButton.setOnClickListener(this::onWalletClick);
|
||||
mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateControlsVisibility() {
|
||||
if (mControlsComponent == null) return;
|
||||
|
||||
boolean hasFavorites = mControlsComponent.getControlsController()
|
||||
.map(c -> c.getFavorites().size() > 0)
|
||||
.orElse(false);
|
||||
if (mDozing
|
||||
|| !hasFavorites
|
||||
|| !mControlServicesAvailable
|
||||
|| mControlsComponent.getVisibility() != AVAILABLE) {
|
||||
mControlsButton.setVisibility(GONE);
|
||||
if (mWalletButton.getVisibility() == GONE) {
|
||||
mIndicationArea.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
mControlsButton.setVisibility(VISIBLE);
|
||||
mControlsButton.setOnClickListener(this::onControlsClick);
|
||||
mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLeftVoiceAssist() {
|
||||
return mLeftIsVoiceAssist;
|
||||
}
|
||||
@@ -751,6 +806,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
if (mWalletButton.getVisibility() == View.VISIBLE) {
|
||||
startFinishDozeAnimationElement(mWalletButton, delay);
|
||||
}
|
||||
if (mControlsButton.getVisibility() == View.VISIBLE) {
|
||||
startFinishDozeAnimationElement(mControlsButton, delay);
|
||||
}
|
||||
if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
|
||||
startFinishDozeAnimationElement(mLeftAffordanceView, delay);
|
||||
delay += DOZE_ANIMATION_STAGGER_DELAY;
|
||||
@@ -824,6 +882,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
updateCameraVisibility();
|
||||
updateLeftAffordanceIcon();
|
||||
updateWalletVisibility();
|
||||
updateControlsVisibility();
|
||||
|
||||
if (dozing) {
|
||||
mOverlayContainer.setVisibility(INVISIBLE);
|
||||
@@ -857,6 +916,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mRightAffordanceView.setAlpha(alpha);
|
||||
mIndicationArea.setAlpha(alpha);
|
||||
mWalletButton.setAlpha(alpha);
|
||||
mControlsButton.setAlpha(alpha);
|
||||
}
|
||||
|
||||
private class DefaultLeftButton implements IntentButton {
|
||||
@@ -950,6 +1010,32 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mQuickAccessWalletController.queryWalletCards(mCardRetriever);
|
||||
|
||||
updateWalletVisibility();
|
||||
updateAffordanceColors();
|
||||
}
|
||||
|
||||
private void updateAffordanceColors() {
|
||||
int iconColor = Utils.getColorAttrDefaultColor(
|
||||
mContext,
|
||||
com.android.internal.R.attr.textColorPrimary);
|
||||
mWalletButton.getDrawable().setTint(iconColor);
|
||||
mControlsButton.getDrawable().setTint(iconColor);
|
||||
|
||||
ColorStateList bgColor = Utils.getColorAttr(
|
||||
mContext,
|
||||
com.android.internal.R.attr.colorSurface);
|
||||
mWalletButton.setBackgroundTintList(bgColor);
|
||||
mControlsButton.setBackgroundTintList(bgColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize controls via the ControlsComponent
|
||||
*/
|
||||
public void initControls(ControlsComponent controlsComponent) {
|
||||
mControlsComponent = controlsComponent;
|
||||
mControlsComponent.getControlsListingController().ifPresent(
|
||||
c -> c.addCallback(mListingCallback));
|
||||
|
||||
updateAffordanceColors();
|
||||
}
|
||||
|
||||
private void onWalletClick(View v) {
|
||||
@@ -974,19 +1060,41 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
}
|
||||
}
|
||||
|
||||
private void onControlsClick(View v) {
|
||||
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(mContext, ControlsActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(ControlsUiController.EXTRA_ANIMATE, true);
|
||||
|
||||
if (mControlsComponent.getVisibility() == AVAILABLE) {
|
||||
mContext.startActivity(intent);
|
||||
} else {
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */);
|
||||
}
|
||||
}
|
||||
|
||||
private class WalletCardRetriever implements
|
||||
QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
|
||||
|
||||
@Override
|
||||
public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
|
||||
mHasCard = !response.getWalletCards().isEmpty();
|
||||
Drawable tileIcon = mQuickAccessWalletController.getWalletClient().getTileIcon();
|
||||
if (tileIcon != null) {
|
||||
mWalletButton.setImageDrawable(tileIcon);
|
||||
}
|
||||
updateWalletVisibility();
|
||||
updateAffordanceColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
|
||||
mHasCard = false;
|
||||
updateWalletVisibility();
|
||||
updateAffordanceColors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.biometrics.AuthController;
|
||||
import com.android.systemui.classifier.Classifier;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.controls.dagger.ControlsComponent;
|
||||
import com.android.systemui.dagger.qualifiers.DisplayId;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.doze.DozeLog;
|
||||
@@ -321,6 +322,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final ScrimController mScrimController;
|
||||
private final PrivacyDotViewController mPrivacyDotViewController;
|
||||
private final QuickAccessWalletController mQuickAccessWalletController;
|
||||
private final ControlsComponent mControlsComponent;
|
||||
private final NotificationRemoteInputManager mRemoteInputManager;
|
||||
|
||||
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
|
||||
@@ -717,7 +719,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
@Main Executor uiExecutor,
|
||||
SecureSettings secureSettings,
|
||||
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
|
||||
NotificationRemoteInputManager remoteInputManager) {
|
||||
NotificationRemoteInputManager remoteInputManager,
|
||||
ControlsComponent controlsComponent) {
|
||||
super(view, falsingManager, dozeLog, keyguardStateController,
|
||||
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
|
||||
statusBarKeyguardViewManager, latencyTracker, flingAnimationUtilsBuilder.get(),
|
||||
@@ -727,6 +730,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardMediaController = keyguardMediaController;
|
||||
mPrivacyDotViewController = privacyDotViewController;
|
||||
mQuickAccessWalletController = quickAccessWalletController;
|
||||
mControlsComponent = controlsComponent;
|
||||
mMetricsLogger = metricsLogger;
|
||||
mActivityManager = activityManager;
|
||||
mConfigurationController = configurationController;
|
||||
@@ -1177,6 +1181,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
|
||||
mKeyguardBottomArea.setFalsingManager(mFalsingManager);
|
||||
mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
|
||||
mKeyguardBottomArea.initControls(mControlsComponent);
|
||||
}
|
||||
|
||||
private void updateMaxDisplayedNotifications(boolean recompute) {
|
||||
|
||||
@@ -85,6 +85,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.biometrics.AuthController;
|
||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||
import com.android.systemui.classifier.FalsingManagerFake;
|
||||
import com.android.systemui.controls.dagger.ControlsComponent;
|
||||
import com.android.systemui.doze.DozeLog;
|
||||
import com.android.systemui.fragments.FragmentHostManager;
|
||||
import com.android.systemui.fragments.FragmentService;
|
||||
@@ -298,6 +299,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
private RemoteInputController mRemoteInputController;
|
||||
@Mock
|
||||
private RecordingController mRecordingController;
|
||||
@Mock
|
||||
private ControlsComponent mControlsComponent;
|
||||
|
||||
private SysuiStatusBarStateController mStatusBarStateController;
|
||||
private NotificationPanelViewController mNotificationPanelViewController;
|
||||
@@ -440,7 +443,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
new FakeExecutor(new FakeSystemClock()),
|
||||
mSecureSettings,
|
||||
mUnlockedScreenOffAnimationController,
|
||||
mNotificationRemoteInputManager);
|
||||
mNotificationRemoteInputManager,
|
||||
mControlsComponent);
|
||||
mNotificationPanelViewController.initDependencies(
|
||||
mStatusBar,
|
||||
mNotificationShelfController);
|
||||
|
||||
Reference in New Issue
Block a user