Refactor ToggleSliderView
ToggleSliderView logic is refactored into a separate controller. A
factory that creates the controller inflates the correct view so the
behavior is transparent to consumers.
The new prototype for brightness slider is here.
Allows to switch between regular brightness slider and thick one:
`adb shell settings put secure sysui_thick_brightness X`
where X is one of:
0 - regular brightness slider
1 - thick brightness slider with mirror
2 - thick brightness slider without mirror
After changing restart device or sysui:
`adb shell am crash com.android.systemui`
Test: manual
Test: atest SystemUITest
Change-Id: Ica7b31d6880c3be831d3f99115945b330ba3d618
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 39a6ed1..3de0fbd 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -669,7 +669,7 @@
</activity>
<activity
- android:name=".settings.BrightnessDialog"
+ android:name=".settings.brightness.BrightnessDialog"
android:label="@string/quick_settings_brightness_dialog_title"
android:theme="@*android:style/Theme.DeviceDefault.QuickSettings.Dialog"
android:finishOnCloseSystemDialogs="true"
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
new file mode 100644
index 0000000..ca56ec1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingMode="stack">
+ <item android:id="@android:id/progress"
+ android:gravity="center_vertical|fill_horizontal">
+ <clip
+ android:drawable="@drawable/brightness_progress_full_drawable"
+ android:clipOrientation="horizontal"
+ android:gravity="left"
+ />
+ </item>
+ <item android:id="@android:id/background"
+ android:gravity="center_vertical|fill_horizontal">
+ <shape android:shape="rectangle"
+ android:tint="?android:attr/colorControlNormal">
+ <size android:height="48dp" />
+ <solid android:color="@color/white_disabled" />
+ <corners android:radius="24dp" />
+ </shape>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
new file mode 100644
index 0000000..a38b8b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle"
+ android:tint="?android:attr/colorControlActivated">
+ <size android:height="48dp" />
+ <solid android:color="@android:color/white" />
+ <corners android:radius="24dp"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_brightness.xml b/packages/SystemUI/res/drawable/ic_brightness.xml
new file mode 100644
index 0000000..f443332
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_brightness.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:pathData="M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z"
+ />
+
+ <path
+ android:pathData=" M20,8.69 V4h-4.69L12,0.69L8.69,4H4v4.69L0.69,12L4,15.31V20h4.69L12,23.31L15.31,20H20v-4.69L23.31,12L20,8.69z M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z M12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S14.76,7 12,7z"
+ android:fillColor="#FFFFFF" />
+</vector>
diff --git a/packages/SystemUI/res/layout/brightness_mirror.xml b/packages/SystemUI/res/layout/brightness_mirror.xml
index e3440b5..8b47ab9 100644
--- a/packages/SystemUI/res/layout/brightness_mirror.xml
+++ b/packages/SystemUI/res/layout/brightness_mirror.xml
@@ -21,12 +21,5 @@
android:layout_height="@dimen/brightness_mirror_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:visibility="invisible">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginLeft="@dimen/notification_side_paddings"
- android:layout_marginRight="@dimen/notification_side_paddings"
- android:background="@drawable/brightness_mirror_background">
- <include layout="@layout/quick_settings_brightness_dialog" />
- </FrameLayout>
+
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 12127f5..11814a1 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -20,7 +20,7 @@
android:layout_gravity="center_vertical"
style="@style/BrightnessDialogContainer">
- <com.android.systemui.settings.ToggleSliderView
+ <com.android.systemui.settings.brightness.BrightnessSliderView
android:id="@+id/brightness_slider"
android:layout_width="0dp"
android:layout_height="48dp"
@@ -28,6 +28,54 @@
android:layout_weight="1"
android:contentDescription="@string/accessibility_brightness"
android:importantForAccessibility="no"
- systemui:text="@string/status_bar_settings_auto_brightness_label" />
+ systemui:text="@string/status_bar_settings_auto_brightness_label" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <CheckBox
+ android:id="@+id/toggle"
+ android:layout_width="48dp"
+ android:layout_height="0dp"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:button="@null"
+ android:background="@*android:drawable/switch_track_material"
+ android:visibility="gone"
+ />
+ <com.android.systemui.settings.brightness.ToggleSeekBar
+ android:id="@+id/slider"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/toggle"
+ android:layout_centerVertical="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:thumb="@drawable/ic_brightness_thumb"
+ android:progressDrawable="@drawable/brightness_progress_drawable"
+ android:splitTrack="false"
+ />
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@id/toggle"
+ android:layout_alignEnd="@id/toggle"
+ android:layout_centerVertical="true"
+ android:gravity="center"
+ android:paddingTop="26dp"
+ android:textColor="#666666"
+ android:textSize="12sp"
+ android:visibility="gone"
+ />
+
+ </RelativeLayout>
+ </com.android.systemui.settings.brightness.BrightnessSliderView>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
new file mode 100644
index 0000000..e08b44a
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_gravity="center"
+ style="@style/BrightnessDialogContainer">
+
+ <com.android.systemui.settings.brightness.BrightnessSliderView
+ android:id="@+id/brightness_slider"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/brightness_mirror_height"
+ android:layout_gravity="center_vertical"
+ android:contentDescription="@string/accessibility_brightness"
+ android:importantForAccessibility="no" >
+
+ <com.android.systemui.settings.brightness.ToggleSeekBar
+ android:id="@+id/slider"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:minHeight="48dp"
+ android:thumb="@null"
+ android:background="@null"
+ android:progressDrawable="@drawable/brightness_progress_drawable_thick"
+ android:splitTrack="false"
+ />
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginLeft="48dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/ic_brightness"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="visible"
+ />
+ </com.android.systemui.settings.brightness.BrightnessSliderView>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
deleted file mode 100644
index 942f3dd..0000000
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2010 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.
--->
-
-<!-- android:background="@drawable/status_bar_closed_default_background" -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <CheckBox
- android:id="@+id/toggle"
- android:layout_width="48dp"
- android:layout_height="0dp"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_alignParentBottom="true"
- android:button="@null"
- android:background="@*android:drawable/switch_track_material"
- android:visibility="gone"
- />
- <com.android.systemui.settings.ToggleSeekBar
- android:id="@+id/slider"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_toEndOf="@id/toggle"
- android:layout_centerVertical="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentEnd="true"
- android:paddingStart="20dp"
- android:paddingEnd="20dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
- android:thumb="@drawable/ic_brightness_thumb"
- android:progressDrawable="@drawable/brightness_progress_drawable"
- android:splitTrack="false"
- />
- <TextView
- android:id="@+id/label"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_alignStart="@id/toggle"
- android:layout_alignEnd="@id/toggle"
- android:layout_centerVertical="true"
- android:gravity="center"
- android:paddingTop="26dp"
- android:textColor="#666666"
- android:textSize="12sp"
- android:visibility="gone"
- />
-</merge>
diff --git a/packages/SystemUI/res/values-h740dp-port/dimens.xml b/packages/SystemUI/res/values-h740dp-port/dimens.xml
index 966066f..4a23ee6 100644
--- a/packages/SystemUI/res/values-h740dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-h740dp-port/dimens.xml
@@ -19,9 +19,9 @@
<dimen name="qs_tile_margin_vertical">24dp</dimen>
<!-- The height of the qs customize header. Should be
- (qs_panel_padding_top (48dp) + brightness_mirror_height (48dp) + qs_tile_margin_top (18dp)) -
+ (qs_panel_padding_top (48dp) + brightness_mirror_height (56dp) + qs_tile_margin_top (18dp)) -
(Toolbar_minWidth (56dp) + qs_tile_margin_top_bottom (12dp))
-->
- <dimen name="qs_customize_header_min_height">46dp</dimen>
+ <dimen name="qs_customize_header_min_height">54dp</dimen>
<dimen name="qs_tile_margin_top">18dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index e45f4eb..51d7b8e 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -22,8 +22,6 @@
<dimen name="docked_divider_handle_width">2dp</dimen>
<dimen name="docked_divider_handle_height">16dp</dimen>
- <dimen name="brightness_mirror_height">40dp</dimen>
-
<dimen name="qs_tile_margin_top">8dp</dimen>
<dimen name="qs_tile_margin_vertical">0dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a2e9f39..b209218 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -427,7 +427,7 @@
<dimen name="notification_panel_width">@dimen/match_parent</dimen>
- <dimen name="brightness_mirror_height">48dp</dimen>
+ <dimen name="brightness_mirror_height">56dp</dimen>
<!-- The width of the panel that holds the quick settings. -->
<dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
@@ -493,10 +493,10 @@
<dimen name="qs_tile_margin_top_bottom">12dp</dimen>
<dimen name="qs_tile_margin_top_bottom_negative">-12dp</dimen>
<!-- The height of the qs customize header. Should be
- (qs_panel_padding_top (48dp) + brightness_mirror_height (48dp) + qs_tile_margin_top (0dp)) -
+ (qs_panel_padding_top (48dp) + brightness_mirror_height (56dp) + qs_tile_margin_top (0dp)) -
(Toolbar_minWidth (56dp) + qs_tile_margin_top_bottom (12dp))
-->
- <dimen name="qs_customize_header_min_height">28dp</dimen>
+ <dimen name="qs_customize_header_min_height">36dp</dimen>
<dimen name="qs_tile_margin_top">0dp</dimen>
<dimen name="qs_tile_icon_background_stroke_width">-1dp</dimen>
<dimen name="qs_tile_background_size">44dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index d13e194..13ff3f5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -21,7 +21,7 @@
import com.android.systemui.ForegroundServicesDialog;
import com.android.systemui.keyguard.WorkLockActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
-import com.android.systemui.settings.BrightnessDialog;
+import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.tuner.TunerActivity;
import com.android.systemui.usb.UsbDebuggingActivity;
import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 758e0c5..08f38a8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -47,9 +47,8 @@
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.ToggleSliderView;
+import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.animation.DisappearParameters;
@@ -62,7 +61,7 @@
import javax.inject.Named;
/** View that represents the quick settings tile panel (when expanded/pulled down). **/
-public class QSPanel extends LinearLayout implements Tunable, BrightnessMirrorListener {
+public class QSPanel extends LinearLayout implements Tunable {
public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
public static final String QS_SHOW_HEADER = "qs_show_header";
@@ -75,10 +74,12 @@
/**
* The index where the content starts that needs to be moved between parents
*/
- private final int mMovableContentStartIndex;
+ private int mMovableContentStartIndex;
@Nullable
protected View mBrightnessView;
+ @Nullable
+ protected BrightnessSlider mToggleSliderController;
private final H mHandler = new H();
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -153,7 +154,6 @@
setOrientation(VERTICAL);
- addViewsAboveTiles();
mMovableContentStartIndex = getChildCount();
mRegularTileLayout = createRegularTileLayout();
mTileLayout = mRegularTileLayout;
@@ -191,10 +191,19 @@
}
}
- protected void addViewsAboveTiles() {
- mBrightnessView = LayoutInflater.from(mContext).inflate(
- R.layout.quick_settings_brightness_dialog, this, false);
- addView(mBrightnessView);
+ /**
+ * Add brightness view above the tile layout.
+ *
+ * Used to add the brightness slider after construction.
+ */
+ public void setBrightnessView(@NonNull View view) {
+ if (mBrightnessView != null) {
+ removeView(mBrightnessView);
+ mMovableContentStartIndex--;
+ }
+ addView(view, 0);
+ mBrightnessView = view;
+ mMovableContentStartIndex++;
}
/** */
@@ -321,22 +330,6 @@
}
}
- public void setBrightnessMirror(BrightnessMirrorController c) {
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.removeCallback(this);
- }
- mBrightnessMirrorController = c;
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.addCallback(this);
- }
- updateBrightnessMirror();
- }
-
- @Override
- public void onBrightnessMirrorReinflated(View brightnessMirror) {
- updateBrightnessMirror();
- }
-
@Nullable
View getBrightnessView() {
return mBrightnessView;
@@ -415,8 +408,6 @@
super.onConfigurationChanged(newConfig);
mOnConfigurationChangedListeners.forEach(
listener -> listener.onConfigurationChange(newConfig));
-
- updateBrightnessMirror();
}
@Override
@@ -578,16 +569,6 @@
}
}
- public void updateBrightnessMirror() {
- if (mBrightnessMirrorController != null) {
- ToggleSliderView brightnessSlider = findViewById(R.id.brightness_slider);
- ToggleSliderView mirrorSlider = mBrightnessMirrorController.getMirror()
- .findViewById(R.id.brightness_slider);
- brightnessSlider.setMirror(mirrorSlider);
- brightnessSlider.setMirrorController(mBrightnessMirrorController);
- }
- }
-
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mQSLogger.logPanelExpanded(expanded, getDumpableTag());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index eef7e39..addaf7e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -26,14 +26,14 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.settings.brightness.BrightnessController;
+import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -50,6 +50,8 @@
private final TunerService mTunerService;
private final QSCustomizerController mQsCustomizerController;
private final BrightnessController mBrightnessController;
+ private final BrightnessSlider.Factory mBrightnessSliderFactory;
+ private final BrightnessSlider mBrightnessSlider;
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@@ -60,29 +62,39 @@
if (mView.isListening()) {
refreshAllTiles();
}
+ updateBrightnessMirror();
}
};
private BrightnessMirrorController mBrightnessMirrorController;
+ private final BrightnessMirrorController.BrightnessMirrorListener mBrightnessMirrorListener =
+ mirror -> updateBrightnessMirror();
+
@Inject
QSPanelController(QSPanel view, QSSecurityFooter qsSecurityFooter, TunerService tunerService,
QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
QSTileRevealController.Factory qsTileRevealControllerFactory,
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
- BrightnessController.Factory brightnessControllerFactory) {
+ BrightnessController.Factory brightnessControllerFactory,
+ BrightnessSlider.Factory brightnessSliderFactory) {
super(view, qstileHost, qsCustomizerController, qsTileRevealControllerFactory,
metricsLogger, uiEventLogger, dumpManager);
mQsSecurityFooter = qsSecurityFooter;
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
mQsSecurityFooter.setHostEnvironment(qstileHost);
- mBrightnessController = brightnessControllerFactory.create(
- mView.findViewById(R.id.brightness_slider));
+ mBrightnessSliderFactory = brightnessSliderFactory;
+
+ mBrightnessSlider = mBrightnessSliderFactory.create(getContext(), mView);
+ mView.setBrightnessView(mBrightnessSlider.getRootView());
+
+ mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
}
@Override
public void onInit() {
mQsCustomizerController.init();
+ mBrightnessSlider.init();
}
@Override
@@ -97,7 +109,7 @@
mView.setSecurityFooter(mQsSecurityFooter.getView());
switchTileLayout(true);
if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.addCallback(mView);
+ mBrightnessMirrorController.addCallback(mBrightnessMirrorListener);
}
}
@@ -106,7 +118,7 @@
mTunerService.removeTunable(mView);
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.removeCallback(mView);
+ mBrightnessMirrorController.removeCallback(mBrightnessMirrorListener);
}
super.onViewDetached();
}
@@ -154,7 +166,20 @@
/** */
public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
mBrightnessMirrorController = brightnessMirrorController;
- mView.setBrightnessMirror(brightnessMirrorController);
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.removeCallback(mBrightnessMirrorListener);
+ }
+ mBrightnessMirrorController = brightnessMirrorController;
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.addCallback(mBrightnessMirrorListener);
+ }
+ updateBrightnessMirror();
+ }
+
+ private void updateBrightnessMirror() {
+ if (mBrightnessMirrorController != null) {
+ mBrightnessSlider.setMirrorControllerAndMirror(mBrightnessMirrorController);
+ }
}
/** Get the QSTileHost this panel uses. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 9c421b0..dde9a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -75,8 +75,8 @@
}
@Override
- protected void addViewsAboveTiles() {
- // Nothing to add above the tiles
+ public void setBrightnessView(View view) {
+ // Don't add brightness view
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
deleted file mode 100644
index 90744a6..0000000
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2013 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.settings;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.RelativeLayout;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
-
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-
-public class ToggleSliderView extends RelativeLayout implements ToggleSlider {
- private Listener mListener;
- private boolean mTracking;
-
- private CompoundButton mToggle;
- private ToggleSeekBar mSlider;
- private TextView mLabel;
-
- private ToggleSliderView mMirror;
- private BrightnessMirrorController mMirrorController;
-
- public ToggleSliderView(Context context) {
- this(context, null);
- }
-
- public ToggleSliderView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ToggleSliderView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- View.inflate(context, R.layout.status_bar_toggle_slider, this);
-
- final Resources res = context.getResources();
- final TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.ToggleSliderView, defStyle, 0);
-
- mToggle = findViewById(R.id.toggle);
- mToggle.setOnCheckedChangeListener(mCheckListener);
-
- mSlider = findViewById(R.id.slider);
- mSlider.setOnSeekBarChangeListener(mSeekListener);
-
- mLabel = findViewById(R.id.label);
- mLabel.setText(a.getString(R.styleable.ToggleSliderView_text));
-
- mSlider.setAccessibilityLabel(getContentDescription().toString());
-
- a.recycle();
- }
-
- public void setMirror(ToggleSliderView toggleSlider) {
- mMirror = toggleSlider;
- if (mMirror != null) {
- mMirror.setChecked(mToggle.isChecked());
- mMirror.setMax(mSlider.getMax());
- mMirror.setValue(mSlider.getProgress());
- }
- }
-
- public void setMirrorController(BrightnessMirrorController c) {
- mMirrorController = c;
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (mListener != null) {
- mListener.onInit(this);
- }
- }
-
- public void setEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
- mToggle.setEnabled(admin == null);
- mSlider.setEnabled(admin == null);
- mSlider.setEnforcedAdmin(admin);
- }
-
- public void setOnChangedListener(Listener l) {
- mListener = l;
- }
-
- @Override
- public void setChecked(boolean checked) {
- mToggle.setChecked(checked);
- }
-
- @Override
- public boolean isChecked() {
- return mToggle.isChecked();
- }
-
- @Override
- public void setMax(int max) {
- mSlider.setMax(max);
- if (mMirror != null) {
- mMirror.setMax(max);
- }
- }
-
- @Override
- public void setValue(int value) {
- mSlider.setProgress(value);
- if (mMirror != null) {
- mMirror.setValue(value);
- }
- }
-
- @Override
- public int getValue() {
- return mSlider.getProgress();
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mMirror != null) {
- MotionEvent copy = ev.copy();
- mMirror.dispatchTouchEvent(copy);
- copy.recycle();
- }
- return super.dispatchTouchEvent(ev);
- }
-
- private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton toggle, boolean checked) {
- mSlider.setEnabled(!checked);
-
- if (mListener != null) {
- mListener.onChanged(
- ToggleSliderView.this, mTracking, checked, mSlider.getProgress(), false);
- }
-
- if (mMirror != null) {
- mMirror.mToggle.setChecked(checked);
- }
- }
- };
-
- private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (mListener != null) {
- mListener.onChanged(
- ToggleSliderView.this, mTracking, mToggle.isChecked(), progress, false);
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mTracking = true;
-
- if (mListener != null) {
- mListener.onChanged(ToggleSliderView.this, mTracking, mToggle.isChecked(),
- mSlider.getProgress(), false);
- }
-
- mToggle.setChecked(false);
-
- if (mMirrorController != null) {
- mMirrorController.showMirror();
- mMirrorController.setLocation((View) getParent());
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- mTracking = false;
-
- if (mListener != null) {
- mListener.onChanged(ToggleSliderView.this, mTracking, mToggle.isChecked(),
- mSlider.getProgress(), true);
- }
-
- if (mMirrorController != null) {
- mMirrorController.hideMirror();
- }
- }
- };
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 72034f8..be10c26 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.settings;
+package com.android.systemui.settings.brightness;
import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
import static com.android.settingslib.display.BrightnessUtils.convertGammaToLinearFloat;
@@ -47,6 +47,7 @@
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.Dependency;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
@@ -100,13 +101,14 @@
private ValueAnimator mSliderAnimator;
public interface BrightnessStateChangeCallback {
- public void onBrightnessLevelChanged();
+ /** Indicates that some of the brightness settings have changed */
+ void onBrightnessLevelChanged();
}
/** ContentObserver to watch brightness */
private class BrightnessObserver extends ContentObserver {
- public BrightnessObserver(Handler handler) {
+ BrightnessObserver(Handler handler) {
super(handler);
}
@@ -339,11 +341,6 @@
return mChangeCallbacks.remove(cb);
}
- @Override
- public void onInit(ToggleSlider control) {
- // Do nothing
- }
-
public void registerCallbacks() {
mBackgroundHandler.post(mStartListeningRunnable);
}
@@ -355,7 +352,7 @@
}
@Override
- public void onChanged(ToggleSlider toggleSlider, boolean tracking, boolean automatic,
+ public void onChanged(boolean tracking, boolean automatic,
int value, boolean stopTracking) {
if (mExternalChange) return;
@@ -409,7 +406,7 @@
mBackgroundHandler.post(new Runnable() {
@Override
public void run() {
- ((ToggleSliderView)mControl).setEnforcedAdmin(
+ mControl.setEnforcedAdmin(
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
UserManager.DISALLOW_CONFIG_BRIGHTNESS,
mUserTracker.getCurrentUserId()));
@@ -493,4 +490,5 @@
return new BrightnessController(mContext, toggleSlider, mBroadcastDispatcher);
}
}
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java
new file mode 100644
index 0000000..a151fd0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 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.settings.brightness;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.util.settings.SecureSettings;
+
+import javax.inject.Inject;
+
+/**
+ * Settings for prototyping thick brightness slider
+ */
+@SysUISingleton
+public class BrightnessControllerSettings {
+
+ private static final String THICK_BRIGHTNESS_SLIDER = "sysui_thick_brighthness";
+ private final boolean mUseThickSlider;
+ private final boolean mUseMirrorOnThickSlider;
+
+ @Inject
+ public BrightnessControllerSettings(SecureSettings settings) {
+ mUseThickSlider = settings.getInt(THICK_BRIGHTNESS_SLIDER, 0) != 0;
+ mUseMirrorOnThickSlider = settings.getInt(THICK_BRIGHTNESS_SLIDER, 0) != 2;
+ }
+
+ // Changing this setting between zero and non-zero may crash systemui down the line. Better to
+ // restart systemui after changing it.
+ /** */
+ boolean useThickSlider() {
+ return mUseThickSlider;
+ }
+
+ /** */
+ boolean useMirrorOnThickSlider() {
+ return mUseMirrorOnThickSlider;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 70c2531..1961bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,20 +14,17 @@
* limitations under the License.
*/
-package com.android.systemui.settings;
+package com.android.systemui.settings.brightness;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import javax.inject.Inject;
@@ -36,11 +33,15 @@
public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
+ private final BrightnessSlider.Factory mToggleSliderFactory;
private final BroadcastDispatcher mBroadcastDispatcher;
@Inject
- public BrightnessDialog(BroadcastDispatcher broadcastDispatcher) {
+ public BrightnessDialog(
+ BroadcastDispatcher broadcastDispatcher,
+ BrightnessSlider.Factory factory) {
mBroadcastDispatcher = broadcastDispatcher;
+ mToggleSliderFactory = factory;
}
@@ -50,16 +51,21 @@
final Window window = getWindow();
- window.setGravity(Gravity.TOP);
+ window.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.requestFeature(Window.FEATURE_NO_TITLE);
- View v = LayoutInflater.from(this).inflate(
- R.layout.quick_settings_brightness_dialog, null);
- setContentView(v);
+ // Calling this creates the decor View, so setLayout takes proper effect
+ // (see Dialog#onWindowAttributesChanged)
+ window.getDecorView();
+ window.setLayout(
+ WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
- final ToggleSliderView slider = findViewById(R.id.brightness_slider);
- mBrightnessController = new BrightnessController(this, slider, mBroadcastDispatcher);
+
+ BrightnessSlider controller = mToggleSliderFactory.create(this, null);
+ controller.init();
+ setContentView(controller.getRootView());
+ mBrightnessController = new BrightnessController(this, controller, mBroadcastDispatcher);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
new file mode 100644
index 0000000..6c4f808
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2020 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.settings.brightness;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.SeekBar;
+
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+/**
+ * {@code ViewController} for a {@code BrightnessSliderView}
+ *
+ * This class allows to control the views of a {@code BrightnessSliderViewView} and get callbacks
+ * when the views change value. It also propagates and manipulates another {@link ToggleSlider} as a
+ * mirror.
+ *
+ * @see BrightnessMirrorController
+ */
+public class BrightnessSlider
+ extends ViewController<View>
+ implements ToggleSlider {
+
+ private Listener mListener;
+ private ToggleSlider mMirror;
+ private final BrightnessSliderView mBrightnessSliderView;
+ private BrightnessMirrorController mMirrorController;
+ private boolean mTracking;
+ private final boolean mUseMirror;
+
+ BrightnessSlider(
+ View rootView,
+ BrightnessSliderView brightnessSliderView,
+ boolean useMirror
+ ) {
+ super(rootView);
+ mBrightnessSliderView = brightnessSliderView;
+ mUseMirror = useMirror;
+ }
+
+ /**
+ * Returns a top level view in the hierarchy that can be attached where necessary
+ */
+ public View getRootView() {
+ return mView;
+ }
+
+ private void enableSlider(boolean enable) {
+ mBrightnessSliderView.enableSlider(enable);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ mBrightnessSliderView.setOnSeekBarChangeListener(mSeekListener);
+ mBrightnessSliderView.setOnCheckedChangeListener(mCheckListener);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mBrightnessSliderView.setOnSeekBarChangeListener(null);
+ mBrightnessSliderView.setOnCheckedChangeListener(null);
+ mBrightnessSliderView.setOnDispatchTouchEventListener(null);
+ }
+
+ @Override
+ public boolean mirrorTouchEvent(MotionEvent ev) {
+ if (mMirror != null) {
+ return copyEventToMirror(ev);
+ } else {
+ // We are the mirror, so we have to dispatch the event
+ return mBrightnessSliderView.dispatchTouchEvent(ev);
+ }
+ }
+
+ private boolean copyEventToMirror(MotionEvent ev) {
+ MotionEvent copy = ev.copy();
+ boolean out = mMirror.mirrorTouchEvent(copy);
+ copy.recycle();
+ return out;
+ }
+
+ @Override
+ public void setEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
+ mBrightnessSliderView.setEnforcedAdmin(admin);
+ }
+
+ private void setMirror(ToggleSlider toggleSlider) {
+ mMirror = toggleSlider;
+ if (mMirror != null) {
+ mMirror.setChecked(mBrightnessSliderView.isChecked());
+ mMirror.setMax(mBrightnessSliderView.getMax());
+ mMirror.setValue(mBrightnessSliderView.getValue());
+ mBrightnessSliderView.setOnDispatchTouchEventListener(this::mirrorTouchEvent);
+ } else {
+ // If there's no mirror, we may be the ones dispatching, events but we should not mirror
+ // them
+ mBrightnessSliderView.setOnDispatchTouchEventListener(null);
+ }
+ }
+
+ /**
+ * This will set the mirror from the controller using
+ * {@link BrightnessMirrorController#getToggleSlider} as a side-effect.
+ * @param c
+ */
+ @Override
+ public void setMirrorControllerAndMirror(BrightnessMirrorController c) {
+ if (!mUseMirror) return;
+ mMirrorController = c;
+ if (c != null) {
+ setMirror(c.getToggleSlider());
+ } else {
+ // If there's no mirror, we may be the ones dispatching, events but we should not mirror
+ // them
+ mBrightnessSliderView.setOnDispatchTouchEventListener(null);
+ }
+ }
+
+ @Override
+ public void setOnChangedListener(Listener l) {
+ mListener = l;
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ mBrightnessSliderView.setChecked(checked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mBrightnessSliderView.isChecked();
+ }
+
+ @Override
+ public void setMax(int max) {
+ mBrightnessSliderView.setMax(max);
+ if (mMirror != null) {
+ mMirror.setMax(max);
+ }
+ }
+
+ @Override
+ public int getMax() {
+ return mBrightnessSliderView.getMax();
+ }
+
+ @Override
+ public void setValue(int value) {
+ mBrightnessSliderView.setValue(value);
+ if (mMirror != null) {
+ mMirror.setValue(value);
+ }
+ }
+
+ @Override
+ public int getValue() {
+ return mBrightnessSliderView.getValue();
+ }
+
+ private final SeekBar.OnSeekBarChangeListener mSeekListener =
+ new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (mListener != null) {
+ mListener.onChanged(mTracking, isChecked(), progress, false);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mTracking = true;
+
+ if (mListener != null) {
+ mListener.onChanged(mTracking, isChecked(),
+ getValue(), false);
+ }
+
+ setChecked(false);
+
+ if (mMirrorController != null) {
+ mMirrorController.showMirror();
+ mMirrorController.setLocation((View) mBrightnessSliderView.getParent());
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mTracking = false;
+
+ if (mListener != null) {
+ mListener.onChanged(mTracking, isChecked(),
+ getValue(), true);
+ }
+
+ if (mMirrorController != null) {
+ mMirrorController.hideMirror();
+ }
+ }
+ };
+
+ private final CompoundButton.OnCheckedChangeListener mCheckListener =
+ new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton toggle, boolean checked) {
+ enableSlider(!checked);
+
+ if (mListener != null) {
+ mListener.onChanged(mTracking, checked, getValue(), false);
+ }
+
+ if (mMirror != null) {
+ mMirror.setChecked(checked);
+ }
+ }
+ };
+
+ /**
+ * Creates a {@link BrightnessSlider} with its associated view.
+ *
+ * The views inflated are determined by {@link BrightnessControllerSettings#useThickSlider()}.
+ */
+ public static class Factory {
+
+ BrightnessControllerSettings mSettings;
+
+ @Inject
+ public Factory(BrightnessControllerSettings settings) {
+ mSettings = settings;
+ }
+
+ /**
+ * Creates the view hierarchy and controller
+ *
+ * @param context a {@link Context} to inflate the hierarchy
+ * @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated
+ * hierarchy will not be attached
+ */
+ public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {
+ int layout = getLayout();
+ ViewGroup root = (ViewGroup) LayoutInflater.from(context)
+ .inflate(layout, viewRoot, false);
+ return fromTree(root, mSettings.useMirrorOnThickSlider());
+ }
+
+ private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) {
+ BrightnessSliderView v = root.requireViewById(R.id.brightness_slider);
+ return new BrightnessSlider(root, v, useMirror);
+ }
+
+ /** Get the layout to inflate based on what slider to use */
+ public int getLayout() {
+ return mSettings.useThickSlider()
+ ? R.layout.quick_settings_brightness_dialog_thick
+ : R.layout.quick_settings_brightness_dialog;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
new file mode 100644
index 0000000..cbf4e88
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2020 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.settings.brightness;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.FrameLayout;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.R;
+
+/**
+ * {@code FrameLayout} used to show and manipulate a {@link ToggleSeekBar}.
+ *
+ * It can additionally control a {@link CompoundButton} and display a label. For the class to work,
+ * add children before inflation with the following ids:
+ * <ul>
+ * <li>{@code @id/slider} of type {@link ToggleSeekBar}</li>
+ * <li>{@code @id/toggle} of type {@link CompoundButton} (optional)</li>
+ * <li>{@code @id/label} of type {@link TextView} (optional)</li>
+ * </ul>
+ */
+public class BrightnessSliderView extends FrameLayout {
+
+ @Nullable
+ private CompoundButton mToggle;
+ @NonNull
+ private ToggleSeekBar mSlider;
+ @Nullable
+ private TextView mLabel;
+ private final CharSequence mText;
+ private DispatchTouchEventListener mListener;
+
+ public BrightnessSliderView(Context context) {
+ this(context, null);
+ }
+
+ public BrightnessSliderView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BrightnessSliderView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ToggleSliderView, defStyle, 0);
+ mText = a.getString(R.styleable.ToggleSliderView_text);
+
+ a.recycle();
+ }
+
+ // Inflated from quick_settings_brightness_dialog or quick_settings_brightness_dialog_thick
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mToggle = findViewById(R.id.toggle);
+
+ mSlider = requireViewById(R.id.slider);
+
+ mLabel = findViewById(R.id.label);
+ if (mLabel != null) {
+ mLabel.setText(mText);
+ }
+ mSlider.setAccessibilityLabel(getContentDescription().toString());
+ }
+
+ /**
+ * Attaches a listener to relay touch events.
+ * @param listener use {@code null} to remove listener
+ */
+ public void setOnDispatchTouchEventListener(
+ DispatchTouchEventListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (mListener != null) {
+ mListener.onDispatchTouchEvent(ev);
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
+ /**
+ * Attaches a listener to the {@link ToggleSeekBar} in the view so changes can be observed
+ * @param seekListener use {@code null} to remove listener
+ */
+ public void setOnSeekBarChangeListener(OnSeekBarChangeListener seekListener) {
+ mSlider.setOnSeekBarChangeListener(seekListener);
+ }
+
+ /**
+ * Attaches a listener to the {@link CompoundButton} in the view (if present) so changes to its
+ * state can be observed
+ * @param checkListener use {@code null} to remove listener
+ */
+ public void setOnCheckedChangeListener(OnCheckedChangeListener checkListener) {
+ if (mToggle != null) {
+ mToggle.setOnCheckedChangeListener(checkListener);
+ }
+ }
+
+ /**
+ * Enforces admin rules for toggling auto-brightness and changing value of brightness
+ * @param admin
+ * @see ToggleSeekBar#setEnforcedAdmin
+ */
+ public void setEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
+ if (mToggle != null) {
+ mToggle.setEnabled(admin == null);
+ }
+ mSlider.setEnabled(admin == null);
+ mSlider.setEnforcedAdmin(admin);
+ }
+
+ /**
+ * Enables or disables the slider
+ * @param enable
+ */
+ public void enableSlider(boolean enable) {
+ mSlider.setEnabled(enable);
+ }
+
+ /**
+ * Sets the state of the {@link CompoundButton} if present
+ * @param checked
+ */
+ public void setChecked(boolean checked) {
+ if (mToggle != null) {
+ mToggle.setChecked(checked);
+ }
+ }
+
+ /**
+ * @return the state of the {@link CompoundButton} if present, or {@code true} if not.
+ */
+ public boolean isChecked() {
+ if (mToggle != null) {
+ return mToggle.isChecked();
+ }
+ return true;
+ }
+
+ /**
+ * @return the maximum value of the {@link ToggleSeekBar}.
+ */
+ public int getMax() {
+ return mSlider.getMax();
+ }
+
+ /**
+ * Sets the maximum value of the {@link ToggleSeekBar}.
+ * @param max
+ */
+ public void setMax(int max) {
+ mSlider.setMax(max);
+ }
+
+ /**
+ * Sets the current value of the {@link ToggleSeekBar}.
+ * @param value
+ */
+ public void setValue(int value) {
+ mSlider.setProgress(value);
+ }
+
+ /**
+ * @return the current value of the {@link ToggleSeekBar}
+ */
+ public int getValue() {
+ return mSlider.getProgress();
+ }
+
+ /**
+ * Interface to attach a listener for {@link View#dispatchTouchEvent}.
+ */
+ @FunctionalInterface
+ interface DispatchTouchEventListener {
+ boolean onDispatchTouchEvent(MotionEvent ev);
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSeekBar.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSeekBar.java
index 8ed4c75..a5a0ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSeekBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.settings;
+package com.android.systemui.settings.brightness;
import android.content.Context;
import android.content.Intent;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
similarity index 60%
rename from packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index 135f89d..71e4818 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,22 +11,31 @@
* 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
+ * limitations under the License.
*/
-package com.android.systemui.settings;
+package com.android.systemui.settings.brightness;
+
+import android.view.MotionEvent;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
public interface ToggleSlider {
interface Listener {
- void onInit(ToggleSlider control);
- void onChanged(ToggleSlider slider, boolean tracking, boolean automatic, int value,
+ void onChanged(boolean tracking, boolean automatic, int value,
boolean stopTracking);
}
+ void setEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin);
+ void setMirrorControllerAndMirror(BrightnessMirrorController c);
+ boolean mirrorTouchEvent(MotionEvent ev);
+
void setOnChangedListener(Listener l);
default void setChecked(boolean checked) {}
default boolean isChecked() { return false; }
void setMax(int max);
+ int getMax();
void setValue(int value);
int getValue();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5c7f54b..486d9da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -172,6 +172,7 @@
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.AutoHideUiElement;
@@ -428,6 +429,7 @@
private final NotificationViewHierarchyManager mViewHierarchyManager;
private final KeyguardViewMediator mKeyguardViewMediator;
protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+ private final BrightnessSlider.Factory mBrightnessSliderFactory;
// for disabling the status bar
private int mDisabled1 = 0;
@@ -740,7 +742,8 @@
DemoModeController demoModeController,
Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
- NotificationIconAreaController notificationIconAreaController) {
+ NotificationIconAreaController notificationIconAreaController,
+ BrightnessSlider.Factory brightnessSliderFactory) {
super(context);
mNotificationsController = notificationsController;
mLightBarController = lightBarController;
@@ -817,6 +820,7 @@
mDismissCallbackRegistry = dismissCallbackRegistry;
mDemoModeController = demoModeController;
mNotificationIconAreaController = notificationIconAreaController;
+ mBrightnessSliderFactory = brightnessSliderFactory;
mBubbleExpandListener =
(isExpanding, key) -> {
@@ -1194,6 +1198,7 @@
mNotificationShadeWindowView,
mNotificationPanelViewController,
mNotificationShadeDepthControllerLazy.get(),
+ mBrightnessSliderFactory,
(visible) -> {
mBrightnessMirrorVisible = visible;
updateScrimController();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 13d5bf5..f6631ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -43,6 +43,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -198,7 +199,8 @@
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
DismissCallbackRegistry dismissCallbackRegistry,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
- NotificationIconAreaController notificationIconAreaController) {
+ NotificationIconAreaController notificationIconAreaController,
+ BrightnessSlider.Factory brightnessSliderFactory) {
return new StatusBar(
context,
notificationsController,
@@ -276,6 +278,7 @@
demoModeController,
notificationShadeDepthController,
statusBarTouchableRegionManager,
- notificationIconAreaController);
+ notificationIconAreaController,
+ brightnessSliderFactory);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index a0b03e1..07d3f01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -17,13 +17,18 @@
package com.android.systemui.statusbar.policy;
import android.annotation.NonNull;
+import android.content.Context;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
@@ -42,15 +47,20 @@
private final NotificationPanelViewController mNotificationPanel;
private final NotificationShadeDepthController mDepthController;
private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
+ private final BrightnessSlider.Factory mToggleSliderFactory;
+ private BrightnessSlider mToggleSliderController;
private final int[] mInt2Cache = new int[2];
- private View mBrightnessMirror;
+ private FrameLayout mBrightnessMirror;
public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
NotificationPanelViewController notificationPanelViewController,
NotificationShadeDepthController notificationShadeDepthController,
+ BrightnessSlider.Factory factory,
@NonNull Consumer<Boolean> visibilityCallback) {
mStatusBarWindow = statusBarWindow;
+ mToggleSliderFactory = factory;
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
+ mToggleSliderController = setMirrorLayout();
mNotificationPanel = notificationPanelViewController;
mDepthController = notificationShadeDepthController;
mNotificationPanel.setPanelAlphaEndAction(() -> {
@@ -88,8 +98,8 @@
mBrightnessMirror.setTranslationY(originalY - mirrorY);
}
- public View getMirror() {
- return mBrightnessMirror;
+ public ToggleSlider getToggleSlider() {
+ return mToggleSliderController;
}
public void updateResources() {
@@ -110,11 +120,33 @@
reinflate();
}
+ private BrightnessSlider setMirrorLayout() {
+ Context context = mBrightnessMirror.getContext();
+ BrightnessSlider controller = mToggleSliderFactory.create(context, mBrightnessMirror);
+ controller.init();
+ Drawable mirrorBackground = context.getDrawable(R.drawable.brightness_mirror_background);
+
+ View rootView = controller.getRootView();
+ rootView.setBackground(mirrorBackground);
+
+ ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) rootView.getLayoutParams();
+ lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ int margin = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_side_paddings);
+ lp.leftMargin = margin;
+ lp.rightMargin = margin;
+ mBrightnessMirror.addView(rootView, lp);
+
+ return controller;
+ }
+
private void reinflate() {
int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
mStatusBarWindow.removeView(mBrightnessMirror);
- mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
- R.layout.brightness_mirror, mStatusBarWindow, false);
+ mBrightnessMirror = (FrameLayout) LayoutInflater.from(mBrightnessMirror.getContext())
+ .inflate(R.layout.brightness_mirror, mStatusBarWindow, false);
+ mToggleSliderController = setMirrorLayout();
mStatusBarWindow.addView(mBrightnessMirror, index);
for (int i = 0; i < mBrightnessMirrorListeners.size(); i++) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index bce376a..f57e3c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -37,8 +37,9 @@
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.settings.BrightnessController;
-import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.settings.brightness.BrightnessController;
+import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.tuner.TunerService;
import org.junit.Before;
@@ -79,6 +80,10 @@
@Mock
private BrightnessController mBrightnessController;
@Mock
+ private BrightnessSlider.Factory mToggleSliderViewControllerFactory;
+ @Mock
+ private BrightnessSlider mBrightnessSlider;
+ @Mock
QSTileImpl mQSTile;
@Mock
QSTileView mQSTileView;
@@ -98,13 +103,16 @@
when(mQSPanel.createRegularTileLayout()).thenReturn(mPagedTileLayout);
when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+ when(mToggleSliderViewControllerFactory.create(any(), any()))
+ .thenReturn(mBrightnessSlider);
when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
.thenReturn(mBrightnessController);
when(mQSTileRevealControllerFactory.create(any())).thenReturn(mQSTileRevealController);
mController = new QSPanelController(mQSPanel, mQSSecurityFooter, mTunerService,
mQSTileHost, mQSCustomizerController, mQSTileRevealControllerFactory, mDumpManager,
- mMetricsLogger, mUiEventLogger, mBrightnessControllerFactory);
+ mMetricsLogger, mUiEventLogger, mBrightnessControllerFactory,
+ mToggleSliderViewControllerFactory);
mController.init();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
new file mode 100644
index 0000000..0cc2072
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2020 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.settings.brightness
+
+import android.testing.AndroidTestingRunner
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.CompoundButton
+import android.widget.SeekBar
+import androidx.test.filters.SmallTest
+import com.android.settingslib.RestrictedLockUtils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.BrightnessMirrorController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.isNull
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.notNull
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BrightnessSliderTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var rootView: View
+ @Mock
+ private lateinit var brightnessSliderView: BrightnessSliderView
+ @Mock
+ private lateinit var enforcedAdmin: RestrictedLockUtils.EnforcedAdmin
+ @Mock
+ private lateinit var mirrorController: BrightnessMirrorController
+ @Mock
+ private lateinit var mirror: ToggleSlider
+ @Mock
+ private lateinit var motionEvent: MotionEvent
+ @Mock
+ private lateinit var listener: ToggleSlider.Listener
+
+ @Captor
+ private lateinit var seekBarChangeCaptor: ArgumentCaptor<SeekBar.OnSeekBarChangeListener>
+ @Mock
+ private lateinit var seekBar: SeekBar
+ @Captor
+ private lateinit var checkedChangeCaptor: ArgumentCaptor<CompoundButton.OnCheckedChangeListener>
+ @Mock
+ private lateinit var compoundButton: CompoundButton
+
+ private lateinit var mController: BrightnessSlider
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(mirrorController.toggleSlider).thenReturn(mirror)
+ whenever(motionEvent.copy()).thenReturn(motionEvent)
+
+ mController = BrightnessSlider(rootView, brightnessSliderView, true)
+ mController.init()
+ mController.setOnChangedListener(listener)
+ }
+
+ @After
+ fun tearDown() {
+ mController.onViewDetached()
+ }
+
+ @Test
+ fun testListenersAddedOnAttach() {
+ mController.onViewAttached()
+
+ verify(brightnessSliderView).setOnCheckedChangeListener(notNull())
+ verify(brightnessSliderView).setOnSeekBarChangeListener(notNull())
+ }
+
+ @Test
+ fun testAllListenersRemovedOnDettach() {
+ mController.onViewAttached()
+ mController.onViewDetached()
+
+ verify(brightnessSliderView).setOnSeekBarChangeListener(isNull())
+ verify(brightnessSliderView).setOnCheckedChangeListener(isNull())
+ verify(brightnessSliderView).setOnDispatchTouchEventListener(isNull())
+ }
+
+ @Test
+ fun testEnforceAdminRelayed() {
+ mController.setEnforcedAdmin(enforcedAdmin)
+ verify(brightnessSliderView).setEnforcedAdmin(enforcedAdmin)
+ }
+
+ @Test
+ fun testNullMirrorControllerNotTrackingTouch() {
+ mController.setMirrorControllerAndMirror(null)
+
+ verify(brightnessSliderView, never()).max
+ verify(brightnessSliderView, never()).value
+ verify(brightnessSliderView, never()).isChecked
+ verify(brightnessSliderView).setOnDispatchTouchEventListener(isNull())
+ }
+
+ @Test
+ fun testNullMirrorNotTrackingTouch() {
+ whenever(mirrorController.toggleSlider).thenReturn(null)
+
+ mController.setMirrorControllerAndMirror(mirrorController)
+
+ verify(brightnessSliderView, never()).max
+ verify(brightnessSliderView, never()).value
+ verify(brightnessSliderView, never()).isChecked
+ verify(brightnessSliderView).setOnDispatchTouchEventListener(isNull())
+ }
+
+ @Test
+ fun testSettingMirrorControllerReliesValuesAndSetsTouchTracking() {
+ val maxValue = 100
+ val progress = 30
+ val checked = true
+ whenever(brightnessSliderView.max).thenReturn(maxValue)
+ whenever(brightnessSliderView.value).thenReturn(progress)
+ whenever(brightnessSliderView.isChecked).thenReturn(checked)
+
+ mController.setMirrorControllerAndMirror(mirrorController)
+
+ verify(mirror).max = maxValue
+ verify(mirror).isChecked = checked
+ verify(mirror).value = progress
+ verify(brightnessSliderView).setOnDispatchTouchEventListener(notNull())
+ }
+
+ @Test
+ fun testSettingMirrorWhenNotUseMirrorIsNoOp() {
+ val otherController = BrightnessSlider(rootView, brightnessSliderView, false)
+ otherController.init()
+
+ otherController.setMirrorControllerAndMirror(mirrorController)
+
+ verify(brightnessSliderView, never()).max
+ verify(brightnessSliderView, never()).value
+ verify(brightnessSliderView, never()).isChecked
+ verify(brightnessSliderView, never()).setOnDispatchTouchEventListener(
+ any(BrightnessSliderView.DispatchTouchEventListener::class.java))
+ }
+
+ @Test
+ fun testSetCheckedRelayed_true() {
+ mController.isChecked = true
+ verify(brightnessSliderView).isChecked = true
+ }
+
+ @Test
+ fun testSetCheckedRelayed_false() {
+ mController.isChecked = false
+ verify(brightnessSliderView).isChecked = false
+ }
+
+ @Test
+ fun testGetChecked() {
+ whenever(brightnessSliderView.isChecked).thenReturn(true)
+
+ assertThat(mController.isChecked).isTrue()
+
+ whenever(brightnessSliderView.isChecked).thenReturn(false)
+
+ assertThat(mController.isChecked).isFalse()
+ }
+
+ @Test
+ fun testSetMaxRelayed() {
+ mController.max = 120
+ verify(brightnessSliderView).max = 120
+ }
+
+ @Test
+ fun testGetMax() {
+ whenever(brightnessSliderView.max).thenReturn(40)
+
+ assertThat(mController.max).isEqualTo(40)
+ }
+
+ @Test
+ fun testSetValue() {
+ mController.value = 30
+ verify(brightnessSliderView).value = 30
+ }
+
+ @Test
+ fun testGetValue() {
+ whenever(brightnessSliderView.value).thenReturn(20)
+
+ assertThat(mController.value).isEqualTo(20)
+ }
+
+ @Test
+ fun testMirrorEventWithMirror() {
+ mController.setMirrorControllerAndMirror(mirrorController)
+
+ mController.mirrorTouchEvent(motionEvent)
+
+ verify(mirror).mirrorTouchEvent(motionEvent)
+ verify(brightnessSliderView, never()).dispatchTouchEvent(any(MotionEvent::class.java))
+ }
+
+ @Test
+ fun testMirrorEventWithoutMirror_dispatchToView() {
+ mController.mirrorTouchEvent(motionEvent)
+
+ verify(brightnessSliderView).dispatchTouchEvent(motionEvent)
+ }
+
+ @Test
+ fun testSeekBarProgressChanged() {
+ mController.onViewAttached()
+ whenever(brightnessSliderView.isChecked).thenReturn(true)
+
+ verify(brightnessSliderView).setOnSeekBarChangeListener(capture(seekBarChangeCaptor))
+
+ seekBarChangeCaptor.value.onProgressChanged(seekBar, 23, true)
+
+ verify(listener).onChanged(anyBoolean(), eq(true), eq(23), eq(false))
+ }
+
+ @Test
+ fun testSeekBarTrackingStarted() {
+ val parent = mock(ViewGroup::class.java)
+ whenever(brightnessSliderView.value).thenReturn(42)
+ whenever(brightnessSliderView.parent).thenReturn(parent)
+ whenever(brightnessSliderView.isChecked).thenReturn(true)
+
+ mController.onViewAttached()
+ mController.setMirrorControllerAndMirror(mirrorController)
+ verify(brightnessSliderView).setOnSeekBarChangeListener(capture(seekBarChangeCaptor))
+
+ seekBarChangeCaptor.value.onStartTrackingTouch(seekBar)
+
+ verify(listener).onChanged(eq(true), eq(true), eq(42), eq(false))
+ verify(mirrorController).showMirror()
+ verify(mirrorController).setLocation(parent)
+ }
+
+ @Test
+ fun testSeekBarTrackingStopped() {
+ whenever(brightnessSliderView.value).thenReturn(23)
+ whenever(brightnessSliderView.isChecked).thenReturn(true)
+
+ mController.onViewAttached()
+ mController.setMirrorControllerAndMirror(mirrorController)
+ verify(brightnessSliderView).setOnSeekBarChangeListener(capture(seekBarChangeCaptor))
+
+ seekBarChangeCaptor.value.onStopTrackingTouch(seekBar)
+
+ verify(listener).onChanged(eq(false), eq(true), eq(23), eq(true))
+ verify(mirrorController).hideMirror()
+ }
+
+ @Test
+ fun testButtonCheckedChanged_false() {
+ val checked = false
+
+ mController.onViewAttached()
+ mController.setMirrorControllerAndMirror(mirrorController)
+ verify(brightnessSliderView).setOnCheckedChangeListener(capture(checkedChangeCaptor))
+
+ checkedChangeCaptor.value.onCheckedChanged(compoundButton, checked)
+
+ verify(brightnessSliderView).enableSlider(!checked)
+ verify(listener).onChanged(anyBoolean(), eq(checked), anyInt(), eq(false))
+ // Called once with false when the mirror is set
+ verify(mirror, times(2)).isChecked = checked
+ }
+
+ @Test
+ fun testButtonCheckedChanged_true() {
+ val checked = true
+
+ mController.onViewAttached()
+ mController.setMirrorControllerAndMirror(mirrorController)
+ verify(brightnessSliderView).setOnCheckedChangeListener(capture(checkedChangeCaptor))
+
+ checkedChangeCaptor.value.onCheckedChanged(compoundButton, checked)
+
+ verify(brightnessSliderView).enableSlider(!checked)
+ verify(listener).onChanged(anyBoolean(), eq(checked), anyInt(), eq(false))
+ verify(mirror).isChecked = checked
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 2f9b601..710122d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -97,6 +97,7 @@
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -260,6 +261,7 @@
@Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
@Mock private DemoModeController mDemoModeController;
@Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
+ @Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
private ShadeController mShadeController;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private InitController mInitController = new InitController();
@@ -419,7 +421,8 @@
mDemoModeController,
mNotificationShadeDepthControllerLazy,
mStatusBarTouchableRegionManager,
- mNotificationIconAreaController);
+ mNotificationIconAreaController,
+ mBrightnessSliderFactory);
when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
mLockIconContainer);