Merge "Adding privacy indicators to split shade header" into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f5fe79dedc
@@ -83,6 +83,17 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
systemui:textAppearance="@style/TextAppearance.QS.Status" />
|
systemui:textAppearance="@style/TextAppearance.QS.Status" />
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/privacy_container"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:paddingStart="16dp">
|
||||||
|
|
||||||
|
<include layout="@layout/ongoing_privacy_chip" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package com.android.systemui.qs
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.android.internal.R
|
||||||
|
import com.android.internal.logging.UiEventLogger
|
||||||
|
import com.android.systemui.privacy.OngoingPrivacyChip
|
||||||
|
import com.android.systemui.privacy.PrivacyChipEvent
|
||||||
|
import com.android.systemui.privacy.PrivacyDialogController
|
||||||
|
import com.android.systemui.privacy.PrivacyItem
|
||||||
|
import com.android.systemui.privacy.PrivacyItemController
|
||||||
|
import com.android.systemui.privacy.logging.PrivacyLogger
|
||||||
|
import com.android.systemui.statusbar.phone.StatusIconContainer
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface ChipVisibilityListener {
|
||||||
|
fun onChipVisibilityRefreshed(visible: Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls privacy icons/chip residing in QS header which show up when app is using camera,
|
||||||
|
* microphone or location.
|
||||||
|
* Manages their visibility depending on privacy signals coming from [PrivacyItemController].
|
||||||
|
*
|
||||||
|
* Unlike typical controller extending [com.android.systemui.util.ViewController] this view doesn't
|
||||||
|
* observe its attachment state because depending on where it is used, it might be never detached.
|
||||||
|
* Instead, parent controller should use [onParentVisible] and [onParentInvisible] to "activate" or
|
||||||
|
* "deactivate" this controller.
|
||||||
|
*/
|
||||||
|
class HeaderPrivacyIconsController @Inject constructor(
|
||||||
|
private val privacyItemController: PrivacyItemController,
|
||||||
|
private val uiEventLogger: UiEventLogger,
|
||||||
|
private val privacyChip: OngoingPrivacyChip,
|
||||||
|
private val privacyDialogController: PrivacyDialogController,
|
||||||
|
private val privacyLogger: PrivacyLogger,
|
||||||
|
private val iconContainer: StatusIconContainer
|
||||||
|
) {
|
||||||
|
|
||||||
|
var chipVisibilityListener: ChipVisibilityListener? = null
|
||||||
|
private var listening = false
|
||||||
|
private var micCameraIndicatorsEnabled = false
|
||||||
|
private var locationIndicatorsEnabled = false
|
||||||
|
private var privacyChipLogged = false
|
||||||
|
private val cameraSlot = privacyChip.resources.getString(R.string.status_bar_camera)
|
||||||
|
private val micSlot = privacyChip.resources.getString(R.string.status_bar_microphone)
|
||||||
|
private val locationSlot = privacyChip.resources.getString(R.string.status_bar_location)
|
||||||
|
|
||||||
|
private val picCallback: PrivacyItemController.Callback =
|
||||||
|
object : PrivacyItemController.Callback {
|
||||||
|
override fun onPrivacyItemsChanged(privacyItems: List<PrivacyItem>) {
|
||||||
|
privacyChip.privacyList = privacyItems
|
||||||
|
setChipVisibility(privacyItems.isNotEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFlagMicCameraChanged(flag: Boolean) {
|
||||||
|
if (micCameraIndicatorsEnabled != flag) {
|
||||||
|
micCameraIndicatorsEnabled = flag
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFlagLocationChanged(flag: Boolean) {
|
||||||
|
if (locationIndicatorsEnabled != flag) {
|
||||||
|
locationIndicatorsEnabled = flag
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun update() {
|
||||||
|
updatePrivacyIconSlots()
|
||||||
|
setChipVisibility(privacyChip.privacyList.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getChipEnabled() = micCameraIndicatorsEnabled || locationIndicatorsEnabled
|
||||||
|
|
||||||
|
fun onParentVisible() {
|
||||||
|
privacyChip.setOnClickListener {
|
||||||
|
// If the privacy chip is visible, it means there were some indicators
|
||||||
|
uiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK)
|
||||||
|
privacyDialogController.showDialog(privacyChip.context)
|
||||||
|
}
|
||||||
|
setChipVisibility(privacyChip.visibility == View.VISIBLE)
|
||||||
|
micCameraIndicatorsEnabled = privacyItemController.micCameraAvailable
|
||||||
|
locationIndicatorsEnabled = privacyItemController.locationAvailable
|
||||||
|
|
||||||
|
// Ignore privacy icons because they show in the space above QQS
|
||||||
|
updatePrivacyIconSlots()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onParentInvisible() {
|
||||||
|
chipVisibilityListener = null
|
||||||
|
privacyChip.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startListening() {
|
||||||
|
listening = true
|
||||||
|
// Get the most up to date info
|
||||||
|
micCameraIndicatorsEnabled = privacyItemController.micCameraAvailable
|
||||||
|
locationIndicatorsEnabled = privacyItemController.locationAvailable
|
||||||
|
privacyItemController.addCallback(picCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopListening() {
|
||||||
|
listening = false
|
||||||
|
privacyItemController.removeCallback(picCallback)
|
||||||
|
privacyChipLogged = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setChipVisibility(visible: Boolean) {
|
||||||
|
if (visible && getChipEnabled()) {
|
||||||
|
privacyLogger.logChipVisible(true)
|
||||||
|
// Makes sure that the chip is logged as viewed at most once each time QS is opened
|
||||||
|
// mListening makes sure that the callback didn't return after the user closed QS
|
||||||
|
if (!privacyChipLogged && listening) {
|
||||||
|
privacyChipLogged = true
|
||||||
|
uiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
privacyLogger.logChipVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
privacyChip.visibility = if (visible) View.VISIBLE else View.GONE
|
||||||
|
chipVisibilityListener?.onChipVisibilityRefreshed(visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updatePrivacyIconSlots() {
|
||||||
|
if (getChipEnabled()) {
|
||||||
|
if (micCameraIndicatorsEnabled) {
|
||||||
|
iconContainer.addIgnoredSlot(cameraSlot)
|
||||||
|
iconContainer.addIgnoredSlot(micSlot)
|
||||||
|
} else {
|
||||||
|
iconContainer.removeIgnoredSlot(cameraSlot)
|
||||||
|
iconContainer.removeIgnoredSlot(micSlot)
|
||||||
|
}
|
||||||
|
if (locationIndicatorsEnabled) {
|
||||||
|
iconContainer.addIgnoredSlot(locationSlot)
|
||||||
|
} else {
|
||||||
|
iconContainer.removeIgnoredSlot(locationSlot)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iconContainer.removeIgnoredSlot(cameraSlot)
|
||||||
|
iconContainer.removeIgnoredSlot(micSlot)
|
||||||
|
iconContainer.removeIgnoredSlot(locationSlot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -373,7 +373,6 @@ public class QuickStatusBarHeader extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setChipVisibility(boolean visibility) {
|
void setChipVisibility(boolean visibility) {
|
||||||
mPrivacyChip.setVisibility(visibility ? View.VISIBLE : View.GONE);
|
|
||||||
if (visibility) {
|
if (visibility) {
|
||||||
// Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible
|
// Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible
|
||||||
mIconsAlphaAnimator = mIconsAlphaAnimatorFixed;
|
mIconsAlphaAnimator = mIconsAlphaAnimatorFixed;
|
||||||
|
|||||||
@@ -17,26 +17,14 @@
|
|||||||
package com.android.systemui.qs;
|
package com.android.systemui.qs;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.android.internal.colorextraction.ColorExtractor;
|
import com.android.internal.colorextraction.ColorExtractor;
|
||||||
import com.android.internal.logging.UiEventLogger;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.battery.BatteryMeterViewController;
|
import com.android.systemui.battery.BatteryMeterViewController;
|
||||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||||
import com.android.systemui.demomode.DemoMode;
|
import com.android.systemui.demomode.DemoMode;
|
||||||
import com.android.systemui.demomode.DemoModeController;
|
import com.android.systemui.demomode.DemoModeController;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
|
||||||
import com.android.systemui.privacy.OngoingPrivacyChip;
|
|
||||||
import com.android.systemui.privacy.PrivacyChipEvent;
|
|
||||||
import com.android.systemui.privacy.PrivacyDialogController;
|
|
||||||
import com.android.systemui.privacy.PrivacyItem;
|
|
||||||
import com.android.systemui.privacy.PrivacyItemController;
|
|
||||||
import com.android.systemui.privacy.logging.PrivacyLogger;
|
|
||||||
import com.android.systemui.qs.carrier.QSCarrierGroupController;
|
import com.android.systemui.qs.carrier.QSCarrierGroupController;
|
||||||
import com.android.systemui.qs.dagger.QSScope;
|
import com.android.systemui.qs.dagger.QSScope;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
|
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
|
||||||
@@ -54,23 +42,17 @@ import javax.inject.Inject;
|
|||||||
* Controller for {@link QuickStatusBarHeader}.
|
* Controller for {@link QuickStatusBarHeader}.
|
||||||
*/
|
*/
|
||||||
@QSScope
|
@QSScope
|
||||||
class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
|
class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> implements
|
||||||
private static final String TAG = "QuickStatusBarHeader";
|
ChipVisibilityListener {
|
||||||
|
|
||||||
private final PrivacyItemController mPrivacyItemController;
|
|
||||||
private final ActivityStarter mActivityStarter;
|
|
||||||
private final UiEventLogger mUiEventLogger;
|
|
||||||
private final QSCarrierGroupController mQSCarrierGroupController;
|
private final QSCarrierGroupController mQSCarrierGroupController;
|
||||||
private final QuickQSPanelController mQuickQSPanelController;
|
private final QuickQSPanelController mQuickQSPanelController;
|
||||||
private final OngoingPrivacyChip mPrivacyChip;
|
|
||||||
private final Clock mClockView;
|
private final Clock mClockView;
|
||||||
private final StatusBarIconController mStatusBarIconController;
|
private final StatusBarIconController mStatusBarIconController;
|
||||||
private final DemoModeController mDemoModeController;
|
private final DemoModeController mDemoModeController;
|
||||||
private final StatusIconContainer mIconContainer;
|
private final StatusIconContainer mIconContainer;
|
||||||
private final StatusBarIconController.TintedIconManager mIconManager;
|
private final StatusBarIconController.TintedIconManager mIconManager;
|
||||||
private final DemoMode mDemoModeReceiver;
|
private final DemoMode mDemoModeReceiver;
|
||||||
private final PrivacyLogger mPrivacyLogger;
|
|
||||||
private final PrivacyDialogController mPrivacyDialogController;
|
|
||||||
private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
|
private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
|
||||||
private final BatteryMeterViewController mBatteryMeterViewController;
|
private final BatteryMeterViewController mBatteryMeterViewController;
|
||||||
private final FeatureFlags mFeatureFlags;
|
private final FeatureFlags mFeatureFlags;
|
||||||
@@ -78,83 +60,31 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
|
|
||||||
private final VariableDateViewController mVariableDateViewControllerDateView;
|
private final VariableDateViewController mVariableDateViewControllerDateView;
|
||||||
private final VariableDateViewController mVariableDateViewControllerClockDateView;
|
private final VariableDateViewController mVariableDateViewControllerClockDateView;
|
||||||
|
private final HeaderPrivacyIconsController mPrivacyIconsController;
|
||||||
|
|
||||||
private boolean mListening;
|
private boolean mListening;
|
||||||
private boolean mMicCameraIndicatorsEnabled;
|
|
||||||
private boolean mLocationIndicatorsEnabled;
|
|
||||||
private boolean mPrivacyChipLogged;
|
|
||||||
private final String mCameraSlot;
|
|
||||||
private final String mMicSlot;
|
|
||||||
private final String mLocationSlot;
|
|
||||||
|
|
||||||
private SysuiColorExtractor mColorExtractor;
|
private SysuiColorExtractor mColorExtractor;
|
||||||
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
||||||
|
|
||||||
private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
|
|
||||||
@Override
|
|
||||||
public void onPrivacyItemsChanged(@NonNull List<PrivacyItem> privacyItems) {
|
|
||||||
mPrivacyChip.setPrivacyList(privacyItems);
|
|
||||||
setChipVisibility(!privacyItems.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFlagMicCameraChanged(boolean flag) {
|
|
||||||
if (mMicCameraIndicatorsEnabled != flag) {
|
|
||||||
mMicCameraIndicatorsEnabled = flag;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFlagLocationChanged(boolean flag) {
|
|
||||||
if (mLocationIndicatorsEnabled != flag) {
|
|
||||||
mLocationIndicatorsEnabled = flag;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update() {
|
|
||||||
updatePrivacyIconSlots();
|
|
||||||
setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private View.OnClickListener mOnClickListener = new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v == mPrivacyChip) {
|
|
||||||
// If the privacy chip is visible, it means there were some indicators
|
|
||||||
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
|
|
||||||
mPrivacyDialogController.showDialog(getContext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
QuickStatusBarHeaderController(QuickStatusBarHeader view,
|
QuickStatusBarHeaderController(QuickStatusBarHeader view,
|
||||||
PrivacyItemController privacyItemController,
|
HeaderPrivacyIconsController headerPrivacyIconsController,
|
||||||
ActivityStarter activityStarter, UiEventLogger uiEventLogger,
|
|
||||||
StatusBarIconController statusBarIconController,
|
StatusBarIconController statusBarIconController,
|
||||||
DemoModeController demoModeController,
|
DemoModeController demoModeController,
|
||||||
QuickQSPanelController quickQSPanelController,
|
QuickQSPanelController quickQSPanelController,
|
||||||
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
|
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
|
||||||
PrivacyLogger privacyLogger,
|
|
||||||
SysuiColorExtractor colorExtractor,
|
SysuiColorExtractor colorExtractor,
|
||||||
PrivacyDialogController privacyDialogController,
|
|
||||||
QSExpansionPathInterpolator qsExpansionPathInterpolator,
|
QSExpansionPathInterpolator qsExpansionPathInterpolator,
|
||||||
BatteryMeterViewController batteryMeterViewController,
|
BatteryMeterViewController batteryMeterViewController,
|
||||||
FeatureFlags featureFlags,
|
FeatureFlags featureFlags,
|
||||||
VariableDateViewController.Factory variableDateViewControllerFactory,
|
VariableDateViewController.Factory variableDateViewControllerFactory,
|
||||||
StatusBarContentInsetsProvider statusBarContentInsetsProvider) {
|
StatusBarContentInsetsProvider statusBarContentInsetsProvider) {
|
||||||
super(view);
|
super(view);
|
||||||
mPrivacyItemController = privacyItemController;
|
mPrivacyIconsController = headerPrivacyIconsController;
|
||||||
mActivityStarter = activityStarter;
|
|
||||||
mUiEventLogger = uiEventLogger;
|
|
||||||
mStatusBarIconController = statusBarIconController;
|
mStatusBarIconController = statusBarIconController;
|
||||||
mDemoModeController = demoModeController;
|
mDemoModeController = demoModeController;
|
||||||
mQuickQSPanelController = quickQSPanelController;
|
mQuickQSPanelController = quickQSPanelController;
|
||||||
mPrivacyLogger = privacyLogger;
|
|
||||||
mPrivacyDialogController = privacyDialogController;
|
|
||||||
mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
|
mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
|
||||||
mBatteryMeterViewController = batteryMeterViewController;
|
mBatteryMeterViewController = batteryMeterViewController;
|
||||||
mFeatureFlags = featureFlags;
|
mFeatureFlags = featureFlags;
|
||||||
@@ -163,8 +93,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
|
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
|
||||||
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
|
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
mPrivacyChip = mView.findViewById(R.id.privacy_chip);
|
|
||||||
mClockView = mView.findViewById(R.id.clock);
|
mClockView = mView.findViewById(R.id.clock);
|
||||||
mIconContainer = mView.findViewById(R.id.statusIcons);
|
mIconContainer = mView.findViewById(R.id.statusIcons);
|
||||||
mVariableDateViewControllerDateView = variableDateViewControllerFactory.create(
|
mVariableDateViewControllerDateView = variableDateViewControllerFactory.create(
|
||||||
@@ -183,10 +111,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
};
|
};
|
||||||
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
|
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
|
||||||
|
|
||||||
mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera);
|
|
||||||
mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone);
|
|
||||||
mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location);
|
|
||||||
|
|
||||||
// Don't need to worry about tuner settings for this icon
|
// Don't need to worry about tuner settings for this icon
|
||||||
mBatteryMeterViewController.ignoreTunerUpdates();
|
mBatteryMeterViewController.ignoreTunerUpdates();
|
||||||
}
|
}
|
||||||
@@ -198,20 +122,13 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onViewAttached() {
|
protected void onViewAttached() {
|
||||||
mPrivacyChip.setOnClickListener(mOnClickListener);
|
mPrivacyIconsController.onParentVisible();
|
||||||
|
mPrivacyIconsController.setChipVisibilityListener(this);
|
||||||
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
|
|
||||||
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
|
|
||||||
|
|
||||||
// Ignore privacy icons because they show in the space above QQS
|
|
||||||
updatePrivacyIconSlots();
|
|
||||||
mIconContainer.addIgnoredSlot(
|
mIconContainer.addIgnoredSlot(
|
||||||
getResources().getString(com.android.internal.R.string.status_bar_managed_profile));
|
getResources().getString(com.android.internal.R.string.status_bar_managed_profile));
|
||||||
mIconContainer.setShouldRestrictIcons(false);
|
mIconContainer.setShouldRestrictIcons(false);
|
||||||
mStatusBarIconController.addIconGroup(mIconManager);
|
mStatusBarIconController.addIconGroup(mIconManager);
|
||||||
|
|
||||||
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
|
|
||||||
|
|
||||||
mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
|
mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
|
||||||
mQSCarrierGroupController
|
mQSCarrierGroupController
|
||||||
.setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
|
.setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
|
||||||
@@ -241,7 +158,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
@Override
|
@Override
|
||||||
protected void onViewDetached() {
|
protected void onViewDetached() {
|
||||||
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
|
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
|
||||||
mPrivacyChip.setOnClickListener(null);
|
mPrivacyIconsController.onParentInvisible();
|
||||||
mStatusBarIconController.removeIconGroup(mIconManager);
|
mStatusBarIconController.removeIconGroup(mIconManager);
|
||||||
mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
|
mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
|
||||||
mDemoModeController.removeCallback(mDemoModeReceiver);
|
mDemoModeController.removeCallback(mDemoModeReceiver);
|
||||||
@@ -266,54 +183,15 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (listening) {
|
if (listening) {
|
||||||
// Get the most up to date info
|
mPrivacyIconsController.startListening();
|
||||||
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
|
|
||||||
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
|
|
||||||
mPrivacyItemController.addCallback(mPICCallback);
|
|
||||||
} else {
|
} else {
|
||||||
mPrivacyItemController.removeCallback(mPICCallback);
|
mPrivacyIconsController.stopListening();
|
||||||
mPrivacyChipLogged = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setChipVisibility(boolean chipVisible) {
|
@Override
|
||||||
if (chipVisible && getChipEnabled()) {
|
public void onChipVisibilityRefreshed(boolean visible) {
|
||||||
mPrivacyLogger.logChipVisible(true);
|
mView.setChipVisibility(visible);
|
||||||
// Makes sure that the chip is logged as viewed at most once each time QS is opened
|
|
||||||
// mListening makes sure that the callback didn't return after the user closed QS
|
|
||||||
if (!mPrivacyChipLogged && mListening) {
|
|
||||||
mPrivacyChipLogged = true;
|
|
||||||
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mPrivacyLogger.logChipVisible(false);
|
|
||||||
}
|
|
||||||
mView.setChipVisibility(chipVisible);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePrivacyIconSlots() {
|
|
||||||
if (getChipEnabled()) {
|
|
||||||
if (mMicCameraIndicatorsEnabled) {
|
|
||||||
mIconContainer.addIgnoredSlot(mCameraSlot);
|
|
||||||
mIconContainer.addIgnoredSlot(mMicSlot);
|
|
||||||
} else {
|
|
||||||
mIconContainer.removeIgnoredSlot(mCameraSlot);
|
|
||||||
mIconContainer.removeIgnoredSlot(mMicSlot);
|
|
||||||
}
|
|
||||||
if (mLocationIndicatorsEnabled) {
|
|
||||||
mIconContainer.addIgnoredSlot(mLocationSlot);
|
|
||||||
} else {
|
|
||||||
mIconContainer.removeIgnoredSlot(mLocationSlot);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mIconContainer.removeIgnoredSlot(mCameraSlot);
|
|
||||||
mIconContainer.removeIgnoredSlot(mMicSlot);
|
|
||||||
mIconContainer.removeIgnoredSlot(mLocationSlot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getChipEnabled() {
|
|
||||||
return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContentMargins(int marginStart, int marginEnd) {
|
public void setContentMargins(int marginStart, int marginEnd) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.battery.BatteryMeterView;
|
import com.android.systemui.battery.BatteryMeterView;
|
||||||
import com.android.systemui.dagger.qualifiers.RootView;
|
import com.android.systemui.dagger.qualifiers.RootView;
|
||||||
import com.android.systemui.plugins.qs.QS;
|
import com.android.systemui.plugins.qs.QS;
|
||||||
|
import com.android.systemui.privacy.OngoingPrivacyChip;
|
||||||
import com.android.systemui.qs.FooterActionsController;
|
import com.android.systemui.qs.FooterActionsController;
|
||||||
import com.android.systemui.qs.FooterActionsController.ExpansionState;
|
import com.android.systemui.qs.FooterActionsController.ExpansionState;
|
||||||
import com.android.systemui.qs.FooterActionsControllerBuilder;
|
import com.android.systemui.qs.FooterActionsControllerBuilder;
|
||||||
@@ -39,6 +40,7 @@ import com.android.systemui.qs.QSPanel;
|
|||||||
import com.android.systemui.qs.QuickQSPanel;
|
import com.android.systemui.qs.QuickQSPanel;
|
||||||
import com.android.systemui.qs.QuickStatusBarHeader;
|
import com.android.systemui.qs.QuickStatusBarHeader;
|
||||||
import com.android.systemui.qs.customize.QSCustomizer;
|
import com.android.systemui.qs.customize.QSCustomizer;
|
||||||
|
import com.android.systemui.statusbar.phone.StatusIconContainer;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
@@ -189,4 +191,18 @@ public interface QSFragmentModule {
|
|||||||
static boolean providesQSUsingMediaPlayer(Context context) {
|
static boolean providesQSUsingMediaPlayer(Context context) {
|
||||||
return useQsMediaPlayer(context);
|
return useQsMediaPlayer(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Provides
|
||||||
|
@QSScope
|
||||||
|
static OngoingPrivacyChip providesPrivacyChip(QuickStatusBarHeader qsHeader) {
|
||||||
|
return qsHeader.findViewById(R.id.privacy_chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Provides
|
||||||
|
@QSScope
|
||||||
|
static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
|
||||||
|
return qsHeader.findViewById(R.id.statusIcons);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ import com.android.systemui.animation.ShadeInterpolation
|
|||||||
import com.android.systemui.battery.BatteryMeterView
|
import com.android.systemui.battery.BatteryMeterView
|
||||||
import com.android.systemui.battery.BatteryMeterViewController
|
import com.android.systemui.battery.BatteryMeterViewController
|
||||||
import com.android.systemui.flags.FeatureFlags
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.qs.HeaderPrivacyIconsController
|
||||||
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
||||||
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
|
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
|
||||||
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER
|
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER
|
||||||
@@ -34,6 +35,7 @@ import javax.inject.Named
|
|||||||
class SplitShadeHeaderController @Inject constructor(
|
class SplitShadeHeaderController @Inject constructor(
|
||||||
@Named(SPLIT_SHADE_HEADER) private val statusBar: View,
|
@Named(SPLIT_SHADE_HEADER) private val statusBar: View,
|
||||||
private val statusBarIconController: StatusBarIconController,
|
private val statusBarIconController: StatusBarIconController,
|
||||||
|
private val privacyIconsController: HeaderPrivacyIconsController,
|
||||||
qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
|
qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
|
||||||
featureFlags: FeatureFlags,
|
featureFlags: FeatureFlags,
|
||||||
@Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController
|
@Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController
|
||||||
@@ -63,8 +65,7 @@ class SplitShadeHeaderController @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
field = value
|
field = value
|
||||||
updateVisibility()
|
onShadeExpandedChanged()
|
||||||
updatePosition()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var splitShadeMode = false
|
var splitShadeMode = false
|
||||||
@@ -73,8 +74,7 @@ class SplitShadeHeaderController @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
field = value
|
field = value
|
||||||
updateVisibility()
|
onSplitShadeModeChanged()
|
||||||
updateConstraints()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var shadeExpandedFraction = -1f
|
var shadeExpandedFraction = -1f
|
||||||
@@ -124,6 +124,26 @@ class SplitShadeHeaderController @Inject constructor(
|
|||||||
updateConstraints()
|
updateConstraints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onShadeExpandedChanged() {
|
||||||
|
if (shadeExpanded) {
|
||||||
|
privacyIconsController.startListening()
|
||||||
|
} else {
|
||||||
|
privacyIconsController.stopListening()
|
||||||
|
}
|
||||||
|
updateVisibility()
|
||||||
|
updatePosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onSplitShadeModeChanged() {
|
||||||
|
if (splitShadeMode) {
|
||||||
|
privacyIconsController.onParentVisible()
|
||||||
|
} else {
|
||||||
|
privacyIconsController.onParentInvisible()
|
||||||
|
}
|
||||||
|
updateVisibility()
|
||||||
|
updateConstraints()
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateVisibility() {
|
private fun updateVisibility() {
|
||||||
val visibility = if (!splitShadeMode && !combinedHeaders) {
|
val visibility = if (!splitShadeMode && !combinedHeaders) {
|
||||||
View.GONE
|
View.GONE
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
|
|||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.privacy.OngoingPrivacyChip;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.NotificationShelf;
|
import com.android.systemui.statusbar.NotificationShelf;
|
||||||
import com.android.systemui.statusbar.NotificationShelfController;
|
import com.android.systemui.statusbar.NotificationShelfController;
|
||||||
@@ -49,6 +50,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
|
|||||||
import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
|
import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
|
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
|
||||||
|
import com.android.systemui.statusbar.phone.StatusIconContainer;
|
||||||
import com.android.systemui.statusbar.phone.TapAgainView;
|
import com.android.systemui.statusbar.phone.TapAgainView;
|
||||||
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
|
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
|
||||||
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
|
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
|
||||||
@@ -170,6 +172,21 @@ public abstract class StatusBarViewModule {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Provides
|
||||||
|
@StatusBarComponent.StatusBarScope
|
||||||
|
public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip(
|
||||||
|
@Named(SPLIT_SHADE_HEADER) View header) {
|
||||||
|
return header.findViewById(R.id.privacy_chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Provides
|
||||||
|
@StatusBarComponent.StatusBarScope
|
||||||
|
static StatusIconContainer providesStatusIconContainer(@Named(SPLIT_SHADE_HEADER) View header) {
|
||||||
|
return header.findViewById(R.id.statusIcons);
|
||||||
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
@Provides
|
@Provides
|
||||||
@StatusBarComponent.StatusBarScope
|
@StatusBarComponent.StatusBarScope
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package com.android.systemui.qs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.view.View
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.internal.logging.UiEventLogger
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.privacy.OngoingPrivacyChip
|
||||||
|
import com.android.systemui.privacy.PrivacyDialogController
|
||||||
|
import com.android.systemui.privacy.PrivacyItemController
|
||||||
|
import com.android.systemui.privacy.logging.PrivacyLogger
|
||||||
|
import com.android.systemui.statusbar.phone.StatusIconContainer
|
||||||
|
import com.android.systemui.util.mockito.any
|
||||||
|
import com.android.systemui.util.mockito.argumentCaptor
|
||||||
|
import com.android.systemui.util.mockito.capture
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class HeaderPrivacyIconsControllerTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var privacyItemController: PrivacyItemController
|
||||||
|
@Mock
|
||||||
|
private lateinit var uiEventLogger: UiEventLogger
|
||||||
|
@Mock
|
||||||
|
private lateinit var privacyChip: OngoingPrivacyChip
|
||||||
|
@Mock
|
||||||
|
private lateinit var privacyDialogController: PrivacyDialogController
|
||||||
|
@Mock
|
||||||
|
private lateinit var privacyLogger: PrivacyLogger
|
||||||
|
@Mock
|
||||||
|
private lateinit var iconContainer: StatusIconContainer
|
||||||
|
|
||||||
|
private lateinit var cameraSlotName: String
|
||||||
|
private lateinit var microphoneSlotName: String
|
||||||
|
private lateinit var locationSlotName: String
|
||||||
|
|
||||||
|
private lateinit var controller: HeaderPrivacyIconsController
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
whenever(privacyChip.context).thenReturn(context)
|
||||||
|
whenever(privacyChip.resources).thenReturn(context.resources)
|
||||||
|
|
||||||
|
cameraSlotName = context.getString(com.android.internal.R.string.status_bar_camera)
|
||||||
|
microphoneSlotName = context.getString(com.android.internal.R.string.status_bar_microphone)
|
||||||
|
locationSlotName = context.getString(com.android.internal.R.string.status_bar_location)
|
||||||
|
|
||||||
|
controller = HeaderPrivacyIconsController(
|
||||||
|
privacyItemController,
|
||||||
|
uiEventLogger,
|
||||||
|
privacyChip,
|
||||||
|
privacyDialogController,
|
||||||
|
privacyLogger,
|
||||||
|
iconContainer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIgnoredSlotsOnParentVisible_noIndicators() {
|
||||||
|
setPrivacyController(micCamera = false, location = false)
|
||||||
|
|
||||||
|
controller.onParentVisible()
|
||||||
|
|
||||||
|
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
|
||||||
|
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
|
||||||
|
verify(iconContainer).removeIgnoredSlot(locationSlotName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIgnoredSlotsOnParentVisible_onlyMicCamera() {
|
||||||
|
setPrivacyController(micCamera = true, location = false)
|
||||||
|
|
||||||
|
controller.onParentVisible()
|
||||||
|
|
||||||
|
verify(iconContainer).addIgnoredSlot(cameraSlotName)
|
||||||
|
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
|
||||||
|
verify(iconContainer).removeIgnoredSlot(locationSlotName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIgnoredSlotsOnParentVisible_onlyLocation() {
|
||||||
|
setPrivacyController(micCamera = false, location = true)
|
||||||
|
|
||||||
|
controller.onParentVisible()
|
||||||
|
|
||||||
|
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
|
||||||
|
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
|
||||||
|
verify(iconContainer).addIgnoredSlot(locationSlotName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIgnoredSlotsOnParentVisible_locationMicCamera() {
|
||||||
|
setPrivacyController(micCamera = true, location = true)
|
||||||
|
|
||||||
|
controller.onParentVisible()
|
||||||
|
|
||||||
|
verify(iconContainer).addIgnoredSlot(cameraSlotName)
|
||||||
|
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
|
||||||
|
verify(iconContainer).addIgnoredSlot(locationSlotName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPrivacyChipClicked() {
|
||||||
|
controller.onParentVisible()
|
||||||
|
|
||||||
|
val captor = argumentCaptor<View.OnClickListener>()
|
||||||
|
verify(privacyChip).setOnClickListener(capture(captor))
|
||||||
|
|
||||||
|
captor.value.onClick(privacyChip)
|
||||||
|
|
||||||
|
verify(privacyDialogController).showDialog(any(Context::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPrivacyController(micCamera: Boolean, location: Boolean) {
|
||||||
|
whenever(privacyItemController.micCameraAvailable).thenReturn(micCamera)
|
||||||
|
whenever(privacyItemController.locationAvailable).thenReturn(location)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,18 +20,12 @@ import android.content.Context
|
|||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.internal.logging.UiEventLogger
|
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.battery.BatteryMeterViewController
|
import com.android.systemui.battery.BatteryMeterViewController
|
||||||
import com.android.systemui.colorextraction.SysuiColorExtractor
|
import com.android.systemui.colorextraction.SysuiColorExtractor
|
||||||
import com.android.systemui.demomode.DemoModeController
|
import com.android.systemui.demomode.DemoModeController
|
||||||
import com.android.systemui.flags.FeatureFlags
|
import com.android.systemui.flags.FeatureFlags
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
|
||||||
import com.android.systemui.privacy.OngoingPrivacyChip
|
|
||||||
import com.android.systemui.privacy.PrivacyDialogController
|
|
||||||
import com.android.systemui.privacy.PrivacyItemController
|
|
||||||
import com.android.systemui.privacy.logging.PrivacyLogger
|
|
||||||
import com.android.systemui.qs.carrier.QSCarrierGroup
|
import com.android.systemui.qs.carrier.QSCarrierGroup
|
||||||
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
||||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
|
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
|
||||||
@@ -51,10 +45,10 @@ import org.junit.runner.RunWith
|
|||||||
import org.mockito.Answers
|
import org.mockito.Answers
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.Mockito.anyBoolean
|
import org.mockito.Mockito.anyBoolean
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mockito.`when`
|
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -64,11 +58,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var view: QuickStatusBarHeader
|
private lateinit var view: QuickStatusBarHeader
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var privacyItemController: PrivacyItemController
|
private lateinit var privacyIconsController: HeaderPrivacyIconsController
|
||||||
@Mock
|
|
||||||
private lateinit var activityStarter: ActivityStarter
|
|
||||||
@Mock
|
|
||||||
private lateinit var uiEventLogger: UiEventLogger
|
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var statusBarIconController: StatusBarIconController
|
private lateinit var statusBarIconController: StatusBarIconController
|
||||||
@Mock
|
@Mock
|
||||||
@@ -80,18 +70,12 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var qsCarrierGroupController: QSCarrierGroupController
|
private lateinit var qsCarrierGroupController: QSCarrierGroupController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var privacyLogger: PrivacyLogger
|
|
||||||
@Mock
|
|
||||||
private lateinit var colorExtractor: SysuiColorExtractor
|
private lateinit var colorExtractor: SysuiColorExtractor
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var iconContainer: StatusIconContainer
|
private lateinit var iconContainer: StatusIconContainer
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var qsCarrierGroup: QSCarrierGroup
|
private lateinit var qsCarrierGroup: QSCarrierGroup
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var privacyChip: OngoingPrivacyChip
|
|
||||||
@Mock
|
|
||||||
private lateinit var privacyDialogController: PrivacyDialogController
|
|
||||||
@Mock
|
|
||||||
private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
|
private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var variableDateViewController: VariableDateViewController
|
private lateinit var variableDateViewController: VariableDateViewController
|
||||||
@@ -114,10 +98,6 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
private lateinit var controller: QuickStatusBarHeaderController
|
private lateinit var controller: QuickStatusBarHeaderController
|
||||||
|
|
||||||
private lateinit var cameraSlotName: String
|
|
||||||
private lateinit var microphoneSlotName: String
|
|
||||||
private lateinit var locationSlotName: String
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
@@ -130,25 +110,14 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
`when`(view.isAttachedToWindow).thenReturn(true)
|
`when`(view.isAttachedToWindow).thenReturn(true)
|
||||||
`when`(view.context).thenReturn(context)
|
`when`(view.context).thenReturn(context)
|
||||||
|
|
||||||
cameraSlotName = mContext.resources.getString(
|
|
||||||
com.android.internal.R.string.status_bar_camera)
|
|
||||||
microphoneSlotName = mContext.resources.getString(
|
|
||||||
com.android.internal.R.string.status_bar_microphone)
|
|
||||||
locationSlotName = mContext.resources.getString(
|
|
||||||
com.android.internal.R.string.status_bar_location)
|
|
||||||
|
|
||||||
controller = QuickStatusBarHeaderController(
|
controller = QuickStatusBarHeaderController(
|
||||||
view,
|
view,
|
||||||
privacyItemController,
|
privacyIconsController,
|
||||||
activityStarter,
|
|
||||||
uiEventLogger,
|
|
||||||
statusBarIconController,
|
statusBarIconController,
|
||||||
demoModeController,
|
demoModeController,
|
||||||
quickQSPanelController,
|
quickQSPanelController,
|
||||||
qsCarrierGroupControllerBuilder,
|
qsCarrierGroupControllerBuilder,
|
||||||
privacyLogger,
|
|
||||||
colorExtractor,
|
colorExtractor,
|
||||||
privacyDialogController,
|
|
||||||
qsExpansionPathInterpolator,
|
qsExpansionPathInterpolator,
|
||||||
batteryMeterViewController,
|
batteryMeterViewController,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
@@ -167,62 +136,6 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
assertThat(clock.isClickable).isFalse()
|
assertThat(clock.isClickable).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testIgnoredSlotsOnAttached_noIndicators() {
|
|
||||||
setPrivacyController(micCamera = false, location = false)
|
|
||||||
|
|
||||||
controller.init()
|
|
||||||
|
|
||||||
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
|
|
||||||
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
|
|
||||||
verify(iconContainer).removeIgnoredSlot(locationSlotName)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testIgnoredSlotsOnAttached_onlyMicCamera() {
|
|
||||||
setPrivacyController(micCamera = true, location = false)
|
|
||||||
|
|
||||||
controller.init()
|
|
||||||
|
|
||||||
verify(iconContainer).addIgnoredSlot(cameraSlotName)
|
|
||||||
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
|
|
||||||
verify(iconContainer).removeIgnoredSlot(locationSlotName)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testIgnoredSlotsOnAttached_onlyLocation() {
|
|
||||||
setPrivacyController(micCamera = false, location = true)
|
|
||||||
|
|
||||||
controller.init()
|
|
||||||
|
|
||||||
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
|
|
||||||
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
|
|
||||||
verify(iconContainer).addIgnoredSlot(locationSlotName)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testIgnoredSlotsOnAttached_locationMicCamera() {
|
|
||||||
setPrivacyController(micCamera = true, location = true)
|
|
||||||
|
|
||||||
controller.init()
|
|
||||||
|
|
||||||
verify(iconContainer).addIgnoredSlot(cameraSlotName)
|
|
||||||
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
|
|
||||||
verify(iconContainer).addIgnoredSlot(locationSlotName)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testPrivacyChipClicked() {
|
|
||||||
controller.init()
|
|
||||||
|
|
||||||
val captor = argumentCaptor<View.OnClickListener>()
|
|
||||||
verify(privacyChip).setOnClickListener(capture(captor))
|
|
||||||
|
|
||||||
captor.value.onClick(privacyChip)
|
|
||||||
|
|
||||||
verify(privacyDialogController).showDialog(any(Context::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSingleCarrierListenerAttachedOnInit() {
|
fun testSingleCarrierListenerAttachedOnInit() {
|
||||||
controller.init()
|
controller.init()
|
||||||
@@ -292,14 +205,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
|||||||
`when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
|
`when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
|
||||||
`when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
|
`when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
|
||||||
`when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer)
|
`when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer)
|
||||||
`when`(view.findViewById<OngoingPrivacyChip>(R.id.privacy_chip)).thenReturn(privacyChip)
|
|
||||||
`when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
|
`when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
|
||||||
`when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView)
|
`when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView)
|
||||||
`when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView)
|
`when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setPrivacyController(micCamera: Boolean, location: Boolean) {
|
|
||||||
`when`(privacyItemController.micCameraAvailable).thenReturn(micCamera)
|
|
||||||
`when`(privacyItemController.locationAvailable).thenReturn(location)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.android.systemui.animation.ShadeInterpolation
|
|||||||
import com.android.systemui.battery.BatteryMeterView
|
import com.android.systemui.battery.BatteryMeterView
|
||||||
import com.android.systemui.battery.BatteryMeterViewController
|
import com.android.systemui.battery.BatteryMeterViewController
|
||||||
import com.android.systemui.flags.FeatureFlags
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.qs.HeaderPrivacyIconsController
|
||||||
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -34,6 +35,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var featureFlags: FeatureFlags
|
@Mock private lateinit var featureFlags: FeatureFlags
|
||||||
@Mock private lateinit var batteryMeterView: BatteryMeterView
|
@Mock private lateinit var batteryMeterView: BatteryMeterView
|
||||||
@Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
|
@Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
|
||||||
|
@Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
|
||||||
|
|
||||||
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
||||||
var viewVisibility = View.GONE
|
var viewVisibility = View.GONE
|
||||||
@@ -56,8 +58,14 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
|
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
|
||||||
whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false)
|
whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false)
|
||||||
splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
|
splitShadeHeaderController = SplitShadeHeaderController(
|
||||||
qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
|
view,
|
||||||
|
statusBarIconController,
|
||||||
|
privacyIconsController,
|
||||||
|
qsCarrierGroupControllerBuilder,
|
||||||
|
featureFlags,
|
||||||
|
batteryMeterViewController
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user