Remove QSDetail

Also remove related classes, calls, and resources that were used by QSDetail
and are no longer needed.

Test: atest SystemUITests
Test: TileService cts tests
Test: adb shell cmd statusbar expand-settings
Fixes: 198796184

Change-Id: Ib5c54f197d03794aca35d0305e3e62c7daedb23a
This commit is contained in:
Fabian Kozynski
2022-02-10 13:38:24 -05:00
parent 5479e1e07b
commit c292eff31f
67 changed files with 79 additions and 4739 deletions

View File

@@ -1,103 +0,0 @@
/*
* Copyright (C) 2017 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.plugins.qs;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.plugins.annotations.ProvidesInterface;
@ProvidesInterface(version = DetailAdapter.VERSION)
public interface DetailAdapter {
public static final int VERSION = 1;
CharSequence getTitle();
Boolean getToggleState();
default boolean getToggleEnabled() {
return true;
}
View createDetailView(Context context, View convertView, ViewGroup parent);
/**
* @return intent for opening more settings related to this detail panel. If null, the more
* settings button will not be shown
*/
Intent getSettingsIntent();
/**
* @return resource id of the string to use for opening the settings intent. If
* {@code Resources.ID_NULL}, then use the default string:
* {@code com.android.systemui.R.string.quick_settings_more_settings}
*/
default int getSettingsText() {
return Resources.ID_NULL;
}
/**
* @return resource id of the string to use for closing the detail panel. If
* {@code Resources.ID_NULL}, then use the default string:
* {@code com.android.systemui.R.string.quick_settings_done}
*/
default int getDoneText() {
return Resources.ID_NULL;
}
void setToggleState(boolean state);
int getMetricsCategory();
/**
* Indicates whether the detail view wants to have its header (back button, title and
* toggle) shown.
*/
default boolean hasHeader() {
return true;
}
/**
* Indicates whether the detail view wants to animate when shown. This has no affect over the
* closing animation. Detail panels will always animate when closed.
*/
default boolean shouldAnimate() {
return true;
}
/**
* @return true if the callback handled the event and wants to keep the detail panel open, false
* otherwise. Returning false will close the panel.
*/
default boolean onDoneButtonClicked() {
return false;
}
default UiEventLogger.UiEventEnum openDetailEvent() {
return INVALID;
}
default UiEventLogger.UiEventEnum closeDetailEvent() {
return INVALID;
}
default UiEventLogger.UiEventEnum moreSettingsEvent() {
return INVALID;
}
UiEventLogger.UiEventEnum INVALID = () -> 0;
}

View File

@@ -35,14 +35,12 @@ import java.util.function.Supplier;
@ProvidesInterface(version = QSTile.VERSION)
@DependsOn(target = QSIconView.class)
@DependsOn(target = DetailAdapter.class)
@DependsOn(target = Callback.class)
@DependsOn(target = Icon.class)
@DependsOn(target = State.class)
public interface QSTile {
int VERSION = 2;
int VERSION = 3;
DetailAdapter getDetailAdapter();
String getTileSpec();
boolean isAvailable();
@@ -117,12 +115,9 @@ public interface QSTile {
}
@ProvidesInterface(version = Callback.VERSION)
public interface Callback {
public static final int VERSION = 1;
interface Callback {
static final int VERSION = 2;
void onStateChanged(State state);
void onShowDetail(boolean show);
void onToggleStateChanged(boolean state);
void onScanStateChanged(boolean state);
}
@ProvidesInterface(version = Icon.VERSION)

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- I really don't want to define this, but the View that uses this asset uses both the
light and dark accent colors. -->
<item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
</selector>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- I really don't want to define this, but the View that uses this asset uses both the
light and dark accent colors. -->
<item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_dark" />
</selector>

View File

@@ -1,33 +0,0 @@
<!--
Copyright (C) 2014 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.
-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<inset>
<shape>
<solid android:color="@android:color/transparent"/>
<corners android:radius="@dimen/qs_footer_action_corner_radius" />
</shape>
</inset>
</item>
<item>
<inset>
<shape>
<solid android:color="?android:attr/colorBackgroundFloating"/>
<corners android:radius="@dimen/qs_footer_action_corner_radius" />
</shape>
</inset>
</item>
</transition>

View File

@@ -1,62 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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.
-->
<!-- Extends LinearLayout -->
<com.android.systemui.qs.QSDetail
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qs_detail_background"
android:layout_marginTop="@dimen/qs_detail_margin_top"
android:clickable="true"
android:orientation="vertical"
android:paddingBottom="8dp"
android:visibility="invisible"
android:elevation="4dp"
android:importantForAccessibility="no" >
<include
android:id="@+id/qs_detail_header"
layout="@layout/qs_detail_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/qs_detail_header_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0"
android:background="@color/qs_detail_progress_track"
android:src="@drawable/indeterminate_anim"
android:scaleType="fitXY"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</ScrollView>
<include layout="@layout/qs_detail_buttons" />
</com.android.systemui.qs.QSDetail>

View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="8dp"
android:gravity="end">
<TextView
android:id="@android:id/button2"
style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:minHeight="48dp"
android:minWidth="132dp"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true" />
<TextView
android:id="@android:id/button1"
style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:minWidth="88dp"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true"/>
</LinearLayout>

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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.
-->
<com.android.keyguard.AlphaOptimizedLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/qs_detail_header_padding"
android:paddingTop="@dimen/qs_detail_header_padding"
android:paddingBottom="@dimen/qs_detail_items_padding_top"
android:paddingEnd="@dimen/qs_panel_padding"
android:background="@drawable/btn_borderless_rect"
android:orientation="vertical"
android:gravity="center">
<com.android.systemui.ResizingSpace
android:layout_width="match_parent"
android:layout_height="@dimen/qs_detail_header_margin_top" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@android:id/title"
android:paddingStart="@dimen/qs_detail_header_text_padding"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textDirection="locale"
android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
<ImageView
android:id="@+id/settings"
android:layout_width="@dimen/qs_detail_image_width"
android:layout_height="@dimen/qs_detail_image_height"
android:background="?android:attr/selectableItemBackground"
android:padding="@dimen/qs_detail_image_padding"
android:src="@drawable/ic_settings"
android:visibility="gone"/>
<ViewStub
android:id="@+id/toggle_stub"
android:inflatedId="@+id/toggle"
android:layout="@layout/qs_detail_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</com.android.keyguard.AlphaOptimizedLinearLayout>

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/qs_detail_item_height"
android:background="@drawable/btn_borderless_rect"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/qs_detail_item_icon_width"
android:layout_height="@dimen/qs_detail_item_icon_size"
android:layout_marginStart="@dimen/qs_detail_item_icon_marginStart"
android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd"
android:tint="?android:attr/textColorPrimary"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textDirection="locale"
android:ellipsize="end"
android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
<TextView
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textDirection="locale"
android:layout_marginTop="2dp"
android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
</LinearLayout>
<ImageView
android:id="@android:id/icon2"
style="@style/QSBorderlessButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:clickable="true"
android:focusable="true"
android:scaleType="center"
android:contentDescription="@*android:string/media_route_controller_disconnect"
android:tint="?android:attr/textColorPrimary" />
</LinearLayout>

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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.
-->
<!-- extends FrameLayout -->
<com.android.systemui.qs.QSDetailItems
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/qs_detail_padding_start"
android:paddingEnd="16dp">
<com.android.systemui.qs.AutoSizingList
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
sysui:itemHeight="@dimen/qs_detail_item_height"
style="@style/AutoSizingList"/>
<LinearLayout
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@android:id/icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:tint="?android:attr/textColorSecondary" />
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
</LinearLayout>
</com.android.systemui.qs.QSDetailItems>

View File

@@ -1,23 +0,0 @@
<!--
~ Copyright (C) 2019 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.
-->
<Switch
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:textAppearance="@style/TextAppearance.QS.DetailHeader" />

View File

@@ -47,10 +47,6 @@
<include layout="@layout/quick_status_bar_expanded_header" />
<include
android:id="@+id/qs_detail"
layout="@layout/qs_detail" />
<ViewStub
android:id="@+id/container_stub"
android:inflatedId="@+id/qs_footer_actions"

View File

@@ -52,7 +52,7 @@
android:gravity="center_horizontal" />
<ImageView
android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_detail_item_secondary_text_size"
android:layout_width="@dimen/qs_tile_text_size"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:src="@drawable/ic_info"

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- extends LinearLayout -->
<com.android.systemui.tuner.TunerZenModePanel
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tuner_zen_mode_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:visibility="gone"
android:orientation="vertical" >
<View
android:id="@+id/zen_embedded_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="12dp"
android:layout_marginTop="8dp"
android:background="@color/qs_tile_divider" />
<include
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:id="@+id/tuner_zen_switch"
layout="@layout/qs_detail_header" />
<include layout="@layout/zen_mode_panel" />
<include
android:id="@+id/tuner_zen_buttons"
layout="@layout/qs_detail_buttons" />
</com.android.systemui.tuner.TunerZenModePanel>

View File

@@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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.
-->
<!-- extends LinearLayout -->
<com.android.systemui.volume.ZenModePanel xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/zen_mode_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false" >
<LinearLayout
android:id="@+id/edit_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorPrimary"
android:clipChildren="false"
android:orientation="vertical">
<com.android.systemui.volume.SegmentedButtons
android:id="@+id/zen_buttons"
android:background="@drawable/segmented_buttons_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" />
<RelativeLayout
android:id="@+id/zen_introduction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="@drawable/zen_introduction_message_background"
android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
<ImageView
android:id="@+id/zen_introduction_confirm"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:layout_alignParentEnd="true"
android:background="@drawable/btn_borderless_rect"
android:clickable="true"
android:contentDescription="@string/accessibility_desc_close"
android:scaleType="center"
android:src="@drawable/ic_close_white_rounded" />
<TextView
android:id="@+id/zen_introduction_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginStart="24dp"
android:textDirection="locale"
android:lineSpacingMultiplier="1.20029"
android:layout_toStartOf="@id/zen_introduction_confirm"
android:textAppearance="@style/TextAppearance.QS.Introduction" />
<TextView
android:id="@+id/zen_introduction_customize"
style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="12dp"
android:layout_below="@id/zen_introduction_message"
android:clickable="true"
android:focusable="true"
android:text="@string/zen_priority_customize_button"
android:textAppearance="@style/TextAppearance.QS.DetailButton.White" />
<View
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_below="@id/zen_introduction_message"
android:layout_alignParentEnd="true" />
</RelativeLayout>
<com.android.settingslib.notification.ZenRadioLayout
android:id="@+id/zen_conditions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="4dp"
android:layout_marginStart="4dp"
android:paddingBottom="@dimen/zen_mode_condition_detail_bottom_padding"
android:orientation="horizontal" >
<RadioGroup
android:id="@+id/zen_radio_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/zen_radio_buttons_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"/>
</com.android.settingslib.notification.ZenRadioLayout>
<TextView
android:id="@+id/zen_alarm_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="16dp"
android:textDirection="locale"
android:lineSpacingMultiplier="1.20029"
android:textAppearance="@style/TextAppearance.QS.Warning" />
</LinearLayout>
<LinearLayout
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="?android:attr/colorPrimary"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@android:id/icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:alpha="?android:attr/disabledAlpha"
android:tint="?android:attr/colorForeground" />
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
</LinearLayout>
<LinearLayout
android:id="@+id/auto_rule"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorPrimary"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:orientation="vertical">
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"/>
</LinearLayout>
</com.android.systemui.volume.ZenModePanel>

View File

@@ -38,11 +38,6 @@
<dimen name="qs_footer_padding">14dp</dimen>
<dimen name="qs_security_footer_background_inset">12dp</dimen>
<dimen name="battery_detail_graph_space_top">9dp</dimen>
<dimen name="battery_detail_graph_space_bottom">9dp</dimen>
<dimen name="qs_detail_header_margin_top">14dp</dimen>
<dimen name="volume_tool_tip_top_margin">12dp</dimen>
<dimen name="volume_row_slider_height">128dp</dimen>

View File

@@ -20,8 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
<dimen name="qs_detail_items_padding_top">16dp</dimen>
<!-- Global actions grid -->
<dimen name="global_actions_grid_vertical_padding">8dp</dimen>
<dimen name="global_actions_grid_horizontal_padding">4dp</dimen>

View File

@@ -65,9 +65,6 @@
<dimen name="qs_security_footer_single_line_height">48dp</dimen>
<dimen name="qs_security_footer_background_inset">0dp</dimen>
<!-- When split shade is used, this panel should be aligned to the top -->
<dimen name="qs_detail_margin_top">0dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">472dp</dimen>
</resources>

View File

@@ -114,13 +114,6 @@
<attr name="hybridNotificationTextStyle" format="reference" />
</declare-styleable>
<declare-styleable name="AutoSizingList">
<!-- Whether AutoSizingList will show only as many items as fit on screen and
remove extra items instead of scrolling. -->
<attr name="enableAutoSizing" format="boolean" />
<attr name="itemHeight" format="dimension" />
</declare-styleable>
<declare-styleable name="PluginInflateContainer">
<attr name="viewType" format="string" />
</declare-styleable>

View File

@@ -500,26 +500,10 @@
<dimen name="qs_panel_elevation">4dp</dimen>
<dimen name="qs_panel_padding_bottom">@dimen/new_footer_height</dimen>
<dimen name="qs_panel_padding_top">48dp</dimen>
<dimen name="qs_detail_header_padding">0dp</dimen>
<dimen name="qs_detail_image_width">56dp</dimen>
<dimen name="qs_detail_image_height">56dp</dimen>
<dimen name="qs_detail_image_padding">16dp</dimen>
<dimen name="qs_detail_item_height">48dp</dimen>
<dimen name="qs_detail_header_text_size">20sp</dimen>
<dimen name="qs_detail_button_text_size">14sp</dimen>
<dimen name="qs_detail_item_primary_text_size">16sp</dimen>
<dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
<dimen name="qs_detail_empty_text_size">14sp</dimen>
<dimen name="qs_detail_header_margin_top">28dp</dimen>
<dimen name="qs_detail_header_text_padding">16dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
<dimen name="qs_detail_padding_start">16dp</dimen>
<dimen name="qs_detail_items_padding_top">4dp</dimen>
<dimen name="qs_detail_item_icon_size">24dp</dimen>
<dimen name="qs_detail_item_icon_width">32dp</dimen>
<dimen name="qs_detail_item_icon_marginStart">0dp</dimen>
<dimen name="qs_detail_item_icon_marginEnd">20dp</dimen>
<dimen name="qs_header_mobile_icon_size">@dimen/status_bar_icon_drawing_size</dimen>
<dimen name="qs_header_carrier_separator_width">6dp</dimen>
<dimen name="qs_carrier_margin_width">4dp</dimen>
@@ -533,9 +517,6 @@
<dimen name="qs_security_footer_background_inset">0dp</dimen>
<dimen name="qs_security_footer_corner_radius">28dp</dimen>
<!-- Desired qs icon overlay size. -->
<dimen name="qs_detail_icon_overlay_size">24dp</dimen>
<dimen name="segmented_button_spacing">0dp</dimen>
<dimen name="borderless_button_radius">2dp</dimen>
@@ -547,8 +528,6 @@
<!-- Padding between subtitles and the following text in the QSFooter dialog -->
<dimen name="qs_footer_dialog_subtitle_padding">20dp</dimen>
<dimen name="qs_detail_margin_top">@*android:dimen/quick_qs_offset_height</dimen>
<!-- Zen mode panel: spacing between two-line condition upper and lower lines -->
<dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>

View File

@@ -609,8 +609,6 @@
<string name="quick_settings_inversion_label">Color inversion</string>
<!-- QuickSettings: Label for the toggle that controls whether display color correction is enabled. [CHAR LIMIT=NONE] -->
<string name="quick_settings_color_correction_label">Color correction</string>
<!-- QuickSettings: Control panel: Label for button that navigates to settings. [CHAR LIMIT=NONE] -->
<string name="quick_settings_more_settings">More settings</string>
<!-- QuickSettings: Control panel: Label for button that navigates to user settings. [CHAR LIMIT=NONE] -->
<string name="quick_settings_more_user_settings">User settings</string>
<!-- QuickSettings: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
@@ -1213,9 +1211,6 @@
<!-- Alarm template for far alarms [CHAR LIMIT=25] -->
<string name="alarm_template_far">on <xliff:g id="when" example="Fri 7:00 AM">%1$s</xliff:g></string>
<!-- Accessibility label for Quick Settings detail screens [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_detail">Quick Settings, <xliff:g id="title" example="Wi-Fi">%s</xliff:g>.</string>
<!-- Accessibility label for hotspot icon [CHAR LIMIT=NONE] -->
<string name="accessibility_status_bar_hotspot">Hotspot</string>
@@ -1730,11 +1725,6 @@
<!-- Content description for no internet connection [CHAR LIMIT=NONE] -->
<string name="data_connection_no_internet">No internet</string>
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_details">Open details.</string>
<!-- accessibility label for quick settings items that are currently disabled. Must have a reason [CHAR LIMIT=NONE] -->
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_settings">Open <xliff:g name="page" example="Bluetooth">%s</xliff:g> settings.</string>

View File

@@ -96,17 +96,12 @@
<item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
</style>
<style name="TextAppearance.QS.DetailHeader">
<item name="android:textSize">@dimen/qs_detail_header_text_size</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
</style>
<style name="TextAppearance.QS.DetailItemPrimary">
<item name="android:textSize">@dimen/qs_detail_item_primary_text_size</item>
<item name="android:textSize">@dimen/qs_tile_text_size</item>
</style>
<style name="TextAppearance.QS.DetailItemSecondary">
<item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
<item name="android:textSize">@dimen/qs_tile_text_size</item>
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
@@ -120,23 +115,6 @@
<item name="android:textColor">?android:attr/colorError</item>
</style>
<style name="TextAppearance.QS.DetailButton">
<item name="android:textSize">@dimen/qs_detail_button_text_size</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textAllCaps">true</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
<item name="android:gravity">center</item>
</style>
<style name="TextAppearance.QS.DetailButton.White">
<item name="android:textColor">@color/zen_introduction</item>
</style>
<style name="TextAppearance.QS.DetailEmpty">
<item name="android:textSize">@dimen/qs_detail_empty_text_size</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.QS.SegmentedButton">
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
@@ -167,7 +145,7 @@
</style>
<style name="TextAppearance.QS.UserSwitcher">
<item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
<item name="android:textSize">@dimen/qs_tile_text_size</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
@@ -433,9 +411,6 @@
<item name="numColumns">3</item>
</style>
<style name="AutoSizingList">
<item name="enableAutoSizing">true</item>
</style>
<style name="Theme.SystemUI.MediaProjectionAlertDialog">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>

View File

@@ -95,6 +95,10 @@ public class Flags {
/***************************************/
// 500 - quick settings
/**
* @deprecated Not needed anymore
*/
@Deprecated
public static final BooleanFlag NEW_USER_SWITCHER =
new BooleanFlag(500, true);

View File

@@ -1,132 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.qs;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import com.android.systemui.R;
/**
* Similar to a ListView, but it will show only as many items as fit on screen and
* bind those instead of scrolling.
*/
public class AutoSizingList extends LinearLayout {
private static final String TAG = "AutoSizingList";
private final int mItemSize;
private final Handler mHandler;
@Nullable
private ListAdapter mAdapter;
private int mCount;
private boolean mEnableAutoSizing;
public AutoSizingList(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mHandler = new Handler();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoSizingList);
mItemSize = a.getDimensionPixelSize(R.styleable.AutoSizingList_itemHeight, 0);
mEnableAutoSizing = a.getBoolean(R.styleable.AutoSizingList_enableAutoSizing, true);
a.recycle();
}
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mDataObserver);
}
mAdapter = adapter;
if (adapter != null) {
adapter.registerDataSetObserver(mDataObserver);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
if (requestedHeight != 0) {
int count = getItemCount(requestedHeight);
if (mCount != count) {
postRebindChildren();
mCount = count;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int getItemCount(int requestedHeight) {
int desiredCount = getDesiredCount();
return mEnableAutoSizing ? Math.min(requestedHeight / mItemSize, desiredCount)
: desiredCount;
}
private int getDesiredCount() {
return mAdapter != null ? mAdapter.getCount() : 0;
}
private void postRebindChildren() {
mHandler.post(mBindChildren);
}
private void rebindChildren() {
if (mAdapter == null) {
return;
}
for (int i = 0; i < mCount; i++) {
View v = i < getChildCount() ? getChildAt(i) : null;
View newView = mAdapter.getView(i, v, this);
if (newView != v) {
if (v != null) {
removeView(v);
}
addView(newView, i);
}
}
// Ditch extra views.
while (getChildCount() > mCount) {
removeViewAt(getChildCount() - 1);
}
}
private final Runnable mBindChildren = new Runnable() {
@Override
public void run() {
rebindChildren();
}
};
private final DataSetObserver mDataObserver = new DataSetObserver() {
@Override
public void onChanged() {
if (mCount > getDesiredCount()) {
mCount = getDesiredCount();
}
postRebindChildren();
}
@Override
public void onInvalidated() {
postRebindChildren();
}
};
}

View File

@@ -44,7 +44,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
private final float[] mFancyClippingRadii = new float[] {0, 0, 0, 0, 0, 0, 0, 0};
private final Path mFancyClippingPath = new Path();
private int mHeightOverride = -1;
private View mQSDetail;
private QuickStatusBarHeader mHeader;
private float mQsExpansion;
private QSCustomizer mQSCustomizer;
@@ -63,7 +62,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
protected void onFinishInflate() {
super.onFinishInflate();
mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
mQSDetail = findViewById(R.id.qs_detail);
mHeader = findViewById(R.id.header);
mQSCustomizer = findViewById(R.id.qs_customize);
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
@@ -175,9 +173,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
int height = calculateContainerHeight();
int scrollBottom = calculateContainerBottom();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + scrollBottom);
int qsDetailBottomMargin = ((MarginLayoutParams) mQSDetail.getLayoutParams()).bottomMargin;
mQSDetail.setBottom(getTop() + scrollBottom - qsDetailBottomMargin);
}
protected int calculateContainerHeight() {

View File

@@ -1,439 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.qs;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_MORE_SETTINGS;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Animatable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.statusbar.CommandQueue;
public class QSDetail extends LinearLayout {
private static final String TAG = "QSDetail";
private static final long FADE_DURATION = 300;
private final SparseArray<View> mDetailViews = new SparseArray<>();
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
private ViewGroup mDetailContent;
private FalsingManager mFalsingManager;
protected TextView mDetailSettingsButton;
protected TextView mDetailDoneButton;
@VisibleForTesting
QSDetailClipper mClipper;
@Nullable
private DetailAdapter mDetailAdapter;
private QSPanelController mQsPanelController;
protected View mQsDetailHeader;
protected TextView mQsDetailHeaderTitle;
private ViewStub mQsDetailHeaderSwitchStub;
@Nullable
private Switch mQsDetailHeaderSwitch;
protected ImageView mQsDetailHeaderProgress;
@Nullable
protected QSTileHost mHost;
private boolean mScanState;
private boolean mClosingDetail;
private boolean mFullyExpanded;
private QuickStatusBarHeader mHeader;
private boolean mTriggeredExpand;
private boolean mShouldAnimate;
private int mOpenX;
private int mOpenY;
private boolean mAnimatingOpen;
private boolean mSwitchState;
private QSFooter mFooter;
@Nullable
private QSContainerController mQsContainerController;
public QSDetail(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size);
FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size);
for (int i = 0; i < mDetailViews.size(); i++) {
mDetailViews.valueAt(i).dispatchConfigurationChanged(newConfig);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mDetailContent = findViewById(android.R.id.content);
mDetailSettingsButton = findViewById(android.R.id.button2);
mDetailDoneButton = findViewById(android.R.id.button1);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
mQsDetailHeaderSwitchStub = mQsDetailHeader.findViewById(R.id.toggle_stub);
mQsDetailHeaderProgress = findViewById(R.id.qs_detail_header_progress);
updateDetailText();
mClipper = new QSDetailClipper(this);
}
public void setContainerController(QSContainerController controller) {
mQsContainerController = controller;
}
/** */
public void setQsPanel(QSPanelController panelController, QuickStatusBarHeader header,
QSFooter footer, FalsingManager falsingManager) {
mQsPanelController = panelController;
mHeader = header;
mFooter = footer;
mHeader.setCallback(mQsPanelCallback);
mQsPanelController.setCallback(mQsPanelCallback);
mFalsingManager = falsingManager;
}
public void setHost(QSTileHost host) {
mHost = host;
}
public boolean isShowingDetail() {
return mDetailAdapter != null;
}
public void setFullyExpanded(boolean fullyExpanded) {
mFullyExpanded = fullyExpanded;
}
public void setExpanded(boolean qsExpanded) {
if (!qsExpanded) {
mTriggeredExpand = false;
}
}
private void updateDetailText() {
int resId = mDetailAdapter != null ? mDetailAdapter.getDoneText() : Resources.ID_NULL;
mDetailDoneButton.setText(
(resId != Resources.ID_NULL) ? resId : R.string.quick_settings_done);
resId = mDetailAdapter != null ? mDetailAdapter.getSettingsText() : Resources.ID_NULL;
mDetailSettingsButton.setText(
(resId != Resources.ID_NULL) ? resId : R.string.quick_settings_more_settings);
}
public void updateResources() {
updateDetailText();
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.topMargin = SystemBarUtils.getQuickQsOffsetHeight(mContext);
setLayoutParams(lp);
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
int bottomNavBar = insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.bottomMargin = bottomNavBar;
setLayoutParams(lp);
return super.onApplyWindowInsets(insets);
}
public boolean isClosingDetail() {
return mClosingDetail;
}
public interface Callback {
/** Handle an event of showing detail. */
void onShowingDetail(@Nullable DetailAdapter detail, int x, int y);
void onToggleStateChanged(boolean state);
void onScanStateChanged(boolean state);
}
/** Handle an event of showing detail. */
public void handleShowingDetail(final @Nullable DetailAdapter adapter, int x, int y,
boolean toggleQs) {
final boolean showingDetail = adapter != null;
final boolean wasShowingDetail = mDetailAdapter != null;
setClickable(showingDetail);
if (showingDetail) {
setupDetailHeader(adapter);
if (toggleQs && !mFullyExpanded) {
mTriggeredExpand = true;
Dependency.get(CommandQueue.class).animateExpandSettingsPanel(null);
} else {
mTriggeredExpand = false;
}
mShouldAnimate = adapter.shouldAnimate();
mOpenX = x;
mOpenY = y;
} else {
// Ensure we collapse into the same point we opened from.
x = mOpenX;
y = mOpenY;
if (toggleQs && mTriggeredExpand) {
Dependency.get(CommandQueue.class).animateCollapsePanels();
mTriggeredExpand = false;
}
// Always animate on close, even if the last opened detail adapter had shouldAnimate()
// return false. This is necessary to avoid a race condition which could leave the
// keyguard in a bad state where QS remains visible underneath the notifications, clock,
// and status area.
mShouldAnimate = true;
}
boolean visibleDiff = wasShowingDetail != showingDetail;
if (!visibleDiff && !wasShowingDetail) return; // already in right state
AnimatorListener listener;
if (showingDetail) {
int viewCacheIndex = adapter.getMetricsCategory();
View detailView = adapter.createDetailView(mContext, mDetailViews.get(viewCacheIndex),
mDetailContent);
if (detailView == null) throw new IllegalStateException("Must return detail view");
setupDetailFooter(adapter);
mDetailContent.removeAllViews();
mDetailContent.addView(detailView);
mDetailViews.put(viewCacheIndex, detailView);
Dependency.get(MetricsLogger.class).visible(adapter.getMetricsCategory());
mUiEventLogger.log(adapter.openDetailEvent());
announceForAccessibility(mContext.getString(
R.string.accessibility_quick_settings_detail,
adapter.getTitle()));
mDetailAdapter = adapter;
listener = mHideGridContentWhenDone;
setVisibility(View.VISIBLE);
updateDetailText();
} else {
if (wasShowingDetail) {
Dependency.get(MetricsLogger.class).hidden(mDetailAdapter.getMetricsCategory());
mUiEventLogger.log(mDetailAdapter.closeDetailEvent());
}
mClosingDetail = true;
mDetailAdapter = null;
listener = mTeardownDetailWhenDone;
// Only update visibility if already expanded. Otherwise, a race condition can cause the
// keyguard to enter a bad state where the QS tiles are displayed underneath the
// notifications, clock, and status area.
if (mQsPanelController.isExpanded()) {
mHeader.setVisibility(View.VISIBLE);
mFooter.setVisibility(View.VISIBLE);
mQsPanelController.setGridContentVisibility(true);
mQsPanelCallback.onScanStateChanged(false);
}
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
animateDetailVisibleDiff(x, y, visibleDiff, listener);
if (mQsContainerController != null) {
mQsContainerController.setDetailShowing(showingDetail);
}
}
protected void animateDetailVisibleDiff(int x, int y, boolean visibleDiff, AnimatorListener listener) {
if (visibleDiff) {
mAnimatingOpen = mDetailAdapter != null;
if (mFullyExpanded || mDetailAdapter != null) {
setAlpha(1);
mClipper.updateCircularClip(mShouldAnimate, x, y, mDetailAdapter != null, listener);
} else {
animate().alpha(0)
.setDuration(mShouldAnimate ? FADE_DURATION : 0)
.setListener(listener)
.start();
}
}
}
protected void setupDetailFooter(DetailAdapter adapter) {
final Intent settingsIntent = adapter.getSettingsIntent();
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
mDetailSettingsButton.setOnClickListener(v -> {
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
}
Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
adapter.getMetricsCategory());
mUiEventLogger.log(adapter.moreSettingsEvent());
Dependency.get(ActivityStarter.class)
.postStartActivityDismissingKeyguard(settingsIntent, 0);
});
mDetailDoneButton.setOnClickListener(v -> {
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
}
announceForAccessibility(
mContext.getString(R.string.accessibility_desc_quick_settings));
if (!adapter.onDoneButtonClicked()) {
mQsPanelController.closeDetail();
}
});
}
protected void setupDetailHeader(final DetailAdapter adapter) {
mQsDetailHeaderTitle.setText(adapter.getTitle());
final Boolean toggleState = adapter.getToggleState();
if (toggleState == null) {
if (mQsDetailHeaderSwitch != null) mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
mQsDetailHeader.setClickable(false);
} else {
if (mQsDetailHeaderSwitch == null) {
mQsDetailHeaderSwitch = (Switch) mQsDetailHeaderSwitchStub.inflate();
}
mQsDetailHeaderSwitch.setVisibility(VISIBLE);
handleToggleStateChanged(toggleState, adapter.getToggleEnabled());
mQsDetailHeader.setClickable(true);
mQsDetailHeader.setOnClickListener(v -> {
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
}
boolean checked = !mQsDetailHeaderSwitch.isChecked();
mQsDetailHeaderSwitch.setChecked(checked);
adapter.setToggleState(checked);
});
}
}
private void handleToggleStateChanged(boolean state, boolean toggleEnabled) {
mSwitchState = state;
if (mAnimatingOpen) {
return;
}
if (mQsDetailHeaderSwitch != null) mQsDetailHeaderSwitch.setChecked(state);
mQsDetailHeader.setEnabled(toggleEnabled);
if (mQsDetailHeaderSwitch != null) mQsDetailHeaderSwitch.setEnabled(toggleEnabled);
}
private void handleScanStateChanged(boolean state) {
if (mScanState == state) return;
mScanState = state;
final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable();
if (state) {
mQsDetailHeaderProgress.animate().cancel();
mQsDetailHeaderProgress.animate()
.alpha(1)
.withEndAction(anim::start)
.start();
} else {
mQsDetailHeaderProgress.animate().cancel();
mQsDetailHeaderProgress.animate()
.alpha(0f)
.withEndAction(anim::stop)
.start();
}
}
private void checkPendingAnimations() {
handleToggleStateChanged(mSwitchState,
mDetailAdapter != null && mDetailAdapter.getToggleEnabled());
}
protected Callback mQsPanelCallback = new Callback() {
@Override
public void onToggleStateChanged(final boolean state) {
post(new Runnable() {
@Override
public void run() {
handleToggleStateChanged(state,
mDetailAdapter != null && mDetailAdapter.getToggleEnabled());
}
});
}
@Override
public void onShowingDetail(
final @Nullable DetailAdapter detail, final int x, final int y) {
post(new Runnable() {
@Override
public void run() {
if (isAttachedToWindow()) {
handleShowingDetail(detail, x, y, false /* toggleQs */);
}
}
});
}
@Override
public void onScanStateChanged(final boolean state) {
post(new Runnable() {
@Override
public void run() {
handleScanStateChanged(state);
}
});
}
};
private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() {
public void onAnimationCancel(Animator animation) {
// If we have been cancelled, remove the listener so that onAnimationEnd doesn't get
// called, this will avoid accidentally turning off the grid when we don't want to.
animation.removeListener(this);
mAnimatingOpen = false;
checkPendingAnimations();
};
@Override
public void onAnimationEnd(Animator animation) {
// Only hide content if still in detail state.
if (mDetailAdapter != null) {
mQsPanelController.setGridContentVisibility(false);
mHeader.setVisibility(View.INVISIBLE);
mFooter.setVisibility(View.INVISIBLE);
}
mAnimatingOpen = false;
checkPendingAnimations();
}
};
private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
mDetailContent.removeAllViews();
setVisibility(View.INVISIBLE);
mClosingDetail = false;
};
};
}

View File

@@ -25,7 +25,7 @@ import android.view.ViewAnimationUtils;
import androidx.annotation.Nullable;
/** Helper for quick settings detail panel clip animations. **/
/** Helper for quick settings detail panel clip animations. Currently used by the customizer **/
public class QSDetailClipper {
private final View mDetail;

View File

@@ -1,48 +0,0 @@
/*
* 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.qs;
import androidx.annotation.Nullable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.qs.DetailAdapter;
import javax.inject.Inject;
/**
* Proxy class for talking with the QSPanel and showing custom content within it.
*/
@SysUISingleton
public class QSDetailDisplayer {
@Nullable
private QSPanelController mQsPanelController;
@Inject
public QSDetailDisplayer() {
}
public void setQsPanelController(@Nullable QSPanelController qsPanelController) {
mQsPanelController = qsPanelController;
}
/** Show the supplied DetailAdapter in the Quick Settings. */
public void showDetailAdapter(DetailAdapter detailAdapter, int x, int y) {
if (mQsPanelController != null) {
mQsPanelController.showDetailAdapter(detailAdapter, x, y);
}
}
}

View File

@@ -1,289 +0,0 @@
/*
* Copyright (C) 2014 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.qs;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
/**
* Quick settings common detail view with line items.
*/
public class QSDetailItems extends FrameLayout {
private static final String TAG = "QSDetailItems";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final int mQsDetailIconOverlaySize;
private final Context mContext;
private final H mHandler = new H();
private final Adapter mAdapter = new Adapter();
private String mTag;
@Nullable
private Callback mCallback;
private boolean mItemsVisible = true;
private AutoSizingList mItemList;
private View mEmpty;
private TextView mEmptyText;
private ImageView mEmptyIcon;
private Item[] mItems;
public QSDetailItems(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mTag = TAG;
mQsDetailIconOverlaySize = (int) getResources().getDimension(
R.dimen.qs_detail_icon_overlay_size);
}
public static QSDetailItems convertOrInflate(Context context, View convert, ViewGroup parent) {
if (convert instanceof QSDetailItems) {
return (QSDetailItems) convert;
}
return (QSDetailItems) LayoutInflater.from(context).inflate(R.layout.qs_detail_items,
parent, false);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mItemList = findViewById(android.R.id.list);
mItemList.setVisibility(GONE);
mItemList.setAdapter(mAdapter);
mEmpty = findViewById(android.R.id.empty);
mEmpty.setVisibility(GONE);
mEmptyText = mEmpty.findViewById(android.R.id.title);
mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
int count = mItemList.getChildCount();
for (int i = 0; i < count; i++) {
View item = mItemList.getChildAt(i);
FontSizeUtils.updateFontSize(item, android.R.id.title,
R.dimen.qs_detail_item_primary_text_size);
FontSizeUtils.updateFontSize(item, android.R.id.summary,
R.dimen.qs_detail_item_secondary_text_size);
}
}
public void setTagSuffix(String suffix) {
mTag = TAG + "." + suffix;
}
public void setEmptyState(int icon, int text) {
mEmptyIcon.post(() -> {
mEmptyIcon.setImageResource(icon);
mEmptyText.setText(text);
});
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
mCallback = null;
}
public void setCallback(Callback callback) {
mHandler.removeMessages(H.SET_CALLBACK);
mHandler.obtainMessage(H.SET_CALLBACK, callback).sendToTarget();
}
/** Set items. */
public void setItems(@Nullable Item[] items) {
mHandler.removeMessages(H.SET_ITEMS);
mHandler.obtainMessage(H.SET_ITEMS, items).sendToTarget();
}
public void setItemsVisible(boolean visible) {
mHandler.removeMessages(H.SET_ITEMS_VISIBLE);
mHandler.obtainMessage(H.SET_ITEMS_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
}
private void handleSetCallback(Callback callback) {
mCallback = callback;
}
private void handleSetItems(Item[] items) {
final int itemCount = items != null ? items.length : 0;
mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
mItems = items;
mAdapter.notifyDataSetChanged();
}
private void handleSetItemsVisible(boolean visible) {
if (mItemsVisible == visible) return;
mItemsVisible = visible;
for (int i = 0; i < mItemList.getChildCount(); i++) {
mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
}
}
private class Adapter extends BaseAdapter {
@Override
public int getCount() {
return mItems != null ? mItems.length : 0;
}
@Override
public Object getItem(int position) {
return mItems[position];
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
final Item item = mItems[position];
if (view == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
false);
}
view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
if (item.icon != null) {
iv.setImageDrawable(item.icon.getDrawable(iv.getContext()));
} else {
iv.setImageResource(item.iconResId);
}
iv.getOverlay().clear();
if (item.overlay != null) {
item.overlay.setBounds(0, 0, mQsDetailIconOverlaySize, mQsDetailIconOverlaySize);
iv.getOverlay().add(item.overlay);
}
final TextView title = (TextView) view.findViewById(android.R.id.title);
title.setText(item.line1);
final TextView summary = (TextView) view.findViewById(android.R.id.summary);
final boolean twoLines = !TextUtils.isEmpty(item.line2);
title.setMaxLines(twoLines ? 1 : 2);
summary.setVisibility(twoLines ? VISIBLE : GONE);
summary.setText(twoLines ? item.line2 : null);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mCallback != null) {
mCallback.onDetailItemClick(item);
}
}
});
final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
if (item.canDisconnect) {
icon2.setImageResource(R.drawable.ic_qs_cancel);
icon2.setVisibility(VISIBLE);
icon2.setClickable(true);
icon2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mCallback != null) {
mCallback.onDetailItemDisconnect(item);
}
}
});
} else if (item.icon2 != -1) {
icon2.setVisibility(VISIBLE);
icon2.setImageResource(item.icon2);
icon2.setClickable(false);
} else {
icon2.setVisibility(GONE);
}
return view;
}
};
private class H extends Handler {
private static final int SET_ITEMS = 1;
private static final int SET_CALLBACK = 2;
private static final int SET_ITEMS_VISIBLE = 3;
public H() {
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
if (msg.what == SET_ITEMS) {
handleSetItems((Item[]) msg.obj);
} else if (msg.what == SET_CALLBACK) {
handleSetCallback((QSDetailItems.Callback) msg.obj);
} else if (msg.what == SET_ITEMS_VISIBLE) {
handleSetItemsVisible(msg.arg1 != 0);
}
}
}
public static class Item {
public Item(int iconResId, CharSequence line1, Object tag) {
this.iconResId = iconResId;
this.line1 = line1;
this.tag = tag;
}
public int iconResId;
@Nullable
public QSTile.Icon icon;
@Nullable
public Drawable overlay;
public CharSequence line1;
@Nullable
public CharSequence line2;
public Object tag;
public boolean canDisconnect;
public int icon2 = -1;
}
public interface Callback {
void onDetailItemClick(Item item);
void onDetailItemDisconnect(Item item);
}
}

View File

@@ -124,13 +124,13 @@ enum class QSUserSwitcherEvent(private val _id: Int) : UiEventLogger.UiEventEnum
@UiEvent(doc = "The current user has been switched in the detail panel")
QS_USER_SWITCH(424),
@UiEvent(doc = "User switcher QS detail panel open")
@UiEvent(doc = "User switcher QS dialog open")
QS_USER_DETAIL_OPEN(425),
@UiEvent(doc = "User switcher QS detail panel closed")
@UiEvent(doc = "User switcher QS dialog closed")
QS_USER_DETAIL_CLOSE(426),
@UiEvent(doc = "User switcher QS detail panel more settings pressed")
@UiEvent(doc = "User switcher QS dialog more settings pressed")
QS_USER_MORE_SETTINGS(427),
@UiEvent(doc = "The user has added a guest in the detail panel")

View File

@@ -33,7 +33,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout.LayoutParams;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -85,7 +84,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private QSSquishinessController mQSSquishinessController;
protected QuickStatusBarHeader mHeader;
protected NonInterceptingScrollView mQSPanelScrollView;
private QSDetail mQSDetail;
private boolean mListening;
private QSContainerImpl mContainer;
private int mLayoutDirection;
@@ -96,8 +94,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private boolean mQsDisabled;
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private final CommandQueue mCommandQueue;
private final QSDetailDisplayer mQsDetailDisplayer;
private final MediaHost mQsMediaHost;
private final MediaHost mQqsMediaHost;
private final QSFragmentComponent.Factory mQsComponentFactory;
@@ -126,7 +122,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
* otherwise.
*/
private boolean mInSplitShade;
private boolean mPulseExpanding;
/**
* Are we currently transitioning from lockscreen to the full shade?
@@ -150,15 +145,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
QSTileHost qsTileHost,
StatusBarStateController statusBarStateController, CommandQueue commandQueue,
QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
KeyguardBypassController keyguardBypassController,
QSFragmentComponent.Factory qsComponentFactory,
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
FalsingManager falsingManager, DumpManager dumpManager) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mCommandQueue = commandQueue;
mQsDetailDisplayer = qsDetailDisplayer;
mQsMediaHost = qsMediaHost;
mQqsMediaHost = qqsMediaHost;
mQsComponentFactory = qsComponentFactory;
@@ -209,19 +202,15 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mScrollListener.onQsPanelScrollChanged(scrollY);
}
});
mQSDetail = view.findViewById(R.id.qs_detail);
mHeader = view.findViewById(R.id.header);
mQSPanelController.setHeaderContainer(view.findViewById(R.id.header_text_container));
mFooter = qsFragmentComponent.getQSFooter();
mQsDetailDisplayer.setQsPanelController(mQSPanelController);
mQSContainerImplController = qsFragmentComponent.getQSContainerImplController();
mQSContainerImplController.init();
mContainer = mQSContainerImplController.getView();
mDumpManager.registerDumpable(mContainer.getClass().getName(), mContainer);
mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter, mFalsingManager);
mQSAnimator = qsFragmentComponent.getQSAnimator();
mQSSquishinessController = qsFragmentComponent.getQSSquishinessController();
@@ -237,7 +226,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQSPanelController.getTileLayout().restoreInstanceState(savedInstanceState);
}
}
setHost(mHost);
mStatusBarStateController.addCallback(this);
onStateChanged(mStatusBarStateController.getState());
view.addOnLayoutChangeListener(
@@ -271,7 +259,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
setListening(false);
}
mQSCustomizerController.setQs(null);
mQsDetailDisplayer.setQsPanelController(null);
mScrollListener = null;
mDumpManager.unregisterDumpable(mContainer.getClass().getName());
}
@@ -352,7 +339,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public void setContainerController(QSContainerController controller) {
mQSCustomizerController.setContainerController(controller);
mQSDetail.setContainerController(controller);
}
@Override
@@ -360,10 +346,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
return mQSCustomizerController.isCustomizing();
}
public void setHost(QSTileHost qsh) {
mQSDetail.setHost(qsh);
}
@Override
public void disable(int displayId, int state1, int state2, boolean animate) {
if (displayId != getContext().getDisplayId()) {
@@ -392,7 +374,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
final boolean expandVisually = expanded || mStackScrollerOverscrolling
|| mHeaderAnimating;
mQSPanelController.setExpanded(expanded);
mQSDetail.setExpanded(expanded);
boolean keyguardShowing = isKeyguardState();
mHeader.setVisibility((expanded || !keyguardShowing || mHeaderAnimating
|| mShowCollapsedOnKeyguard)
@@ -444,7 +425,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public boolean isShowingDetail() {
return mQSCustomizerController.isCustomizing() || mQSDetail.isShowingDetail();
return mQSCustomizerController.isCustomizing();
}
@Override
@@ -573,7 +554,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (fullyCollapsed) {
mQSPanelScrollView.setScrollY(0);
}
mQSDetail.setFullyExpanded(fullyExpanded);
if (!fullyExpanded) {
// Set bounds on the QS panel so it doesn't run over the header when animating.
@@ -732,14 +712,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (mQSCustomizerController.isCustomizing()) {
return getView().getHeight();
}
if (mQSDetail.isClosingDetail()) {
LayoutParams layoutParams = (LayoutParams) mQSPanelScrollView.getLayoutParams();
int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
+ mQSPanelScrollView.getMeasuredHeight();
return panelHeight + getView().getPaddingBottom();
} else {
return getView().getMeasuredHeight();
}
return getView().getMeasuredHeight();
}
@Override

View File

@@ -41,10 +41,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.widget.RemeasuringLinearLayout;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -80,7 +78,6 @@ public class QSPanel extends LinearLayout implements Tunable {
protected boolean mExpanded;
protected boolean mListening;
private QSDetail.Callback mCallback;
protected QSTileHost mHost;
private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
new ArrayList<>();
@@ -100,9 +97,6 @@ public class QSPanel extends LinearLayout implements Tunable {
private int mContentMarginEnd;
private boolean mUsingHorizontalLayout;
private Record mDetailRecord;
private BrightnessMirrorController mBrightnessMirrorController;
private LinearLayout mHorizontalLinearLayout;
protected LinearLayout mHorizontalContentContainer;
@@ -315,24 +309,12 @@ public class QSPanel extends LinearLayout implements Tunable {
view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);
}
/** */
public void openDetails(QSTile tile) {
// If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
// QSFactory will not be able to create a tile and getTile will return null
if (tile != null) {
showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
}
}
@Nullable
View getBrightnessView() {
return mBrightnessView;
}
public void setCallback(QSDetail.Callback callback) {
mCallback = callback;
}
/**
* Links the footer's page indicator, which is used in landscape orientation to save space.
*
@@ -519,25 +501,6 @@ public class QSPanel extends LinearLayout implements Tunable {
mListening = listening;
}
public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) {
int xInWindow = locationInWindow[0];
int yInWindow = locationInWindow[1];
((View) getParent()).getLocationInWindow(locationInWindow);
Record r = new Record();
r.detailAdapter = adapter;
r.x = xInWindow - locationInWindow[0];
r.y = yInWindow - locationInWindow[1];
locationInWindow[0] = xInWindow;
locationInWindow[1] = yInWindow;
showDetail(show, r);
}
protected void showDetail(boolean show, Record r) {
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
protected void drawTile(QSPanelControllerBase.TileRecord r, QSTile.State state) {
r.tileView.onStateChanged(state);
@@ -565,30 +528,6 @@ public class QSPanel extends LinearLayout implements Tunable {
public void onStateChanged(QSTile.State state) {
drawTile(tileRecord, state);
}
@Override
public void onShowDetail(boolean show) {
// Both the collapsed and full QS panels get this callback, this check determines
// which one should handle showing the detail.
if (shouldShowDetail()) {
QSPanel.this.showDetail(show, tileRecord);
}
}
@Override
public void onToggleStateChanged(boolean state) {
if (mDetailRecord == tileRecord) {
fireToggleStateChanged(state);
}
}
@Override
public void onScanStateChanged(boolean state) {
tileRecord.scanState = state;
if (mDetailRecord == tileRecord) {
fireScanStateChanged(tileRecord.scanState);
}
}
};
tileRecord.tile.addCallback(callback);
@@ -605,72 +544,10 @@ public class QSPanel extends LinearLayout implements Tunable {
mTileLayout.removeTile(tileRecord);
}
void closeDetail() {
showDetail(false, mDetailRecord);
}
public int getGridHeight() {
return getMeasuredHeight();
}
protected void handleShowDetail(Record r, boolean show) {
if (r instanceof QSPanelControllerBase.TileRecord) {
handleShowDetailTile((QSPanelControllerBase.TileRecord) r, show);
} else {
int x = 0;
int y = 0;
if (r != null) {
x = r.x;
y = r.y;
}
handleShowDetailImpl(r, show, x, y);
}
}
private void handleShowDetailTile(QSPanelControllerBase.TileRecord r, boolean show) {
if ((mDetailRecord != null) == show && mDetailRecord == r) return;
if (show) {
r.detailAdapter = r.tile.getDetailAdapter();
if (r.detailAdapter == null) return;
}
r.tile.setDetailListening(show);
int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
int y = r.tileView.getDetailY() + mTileLayout.getOffsetTop(r) + getTop();
handleShowDetailImpl(r, show, x, y);
}
private void handleShowDetailImpl(Record r, boolean show, int x, int y) {
setDetailRecord(show ? r : null);
fireShowingDetail(show ? r.detailAdapter : null, x, y);
}
protected void setDetailRecord(Record r) {
if (r == mDetailRecord) return;
mDetailRecord = r;
final boolean scanState = mDetailRecord instanceof QSPanelControllerBase.TileRecord
&& ((QSPanelControllerBase.TileRecord) mDetailRecord).scanState;
fireScanStateChanged(scanState);
}
private void fireShowingDetail(DetailAdapter detail, int x, int y) {
if (mCallback != null) {
mCallback.onShowingDetail(detail, x, y);
}
}
private void fireToggleStateChanged(boolean state) {
if (mCallback != null) {
mCallback.onToggleStateChanged(state);
}
}
private void fireScanStateChanged(boolean state) {
if (mCallback != null) {
mCallback.onScanStateChanged(state);
}
}
QSTileLayout getTileLayout() {
return mTileLayout;
}
@@ -774,26 +651,16 @@ public class QSPanel extends LinearLayout implements Tunable {
}
private class H extends Handler {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 3;
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 1;
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_DETAIL) {
handleShowDetail((Record) msg.obj, msg.arg1 != 0);
} else if (msg.what == ANNOUNCE_FOR_ACCESSIBILITY) {
if (msg.what == ANNOUNCE_FOR_ACCESSIBILITY) {
announceForAccessibility((CharSequence) msg.obj);
}
}
}
protected static class Record {
DetailAdapter detailAdapter;
int x;
int y;
}
public interface QSTileLayout {
/** */
default void saveInstanceState(Bundle outState) {}

View File

@@ -36,15 +36,12 @@ import com.android.systemui.flags.Flags;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
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.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessController;
import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Utils;
@@ -57,7 +54,6 @@ import javax.inject.Named;
*/
@QSScope
public class QSPanelController extends QSPanelControllerBase<QSPanel> {
public static final String QS_REMOVE_LABELS = "sysui_remove_labels";
private final QSFgsManagerFooter mQSFgsManagerFooter;
private final QSSecurityFooter mQsSecurityFooter;
@@ -65,7 +61,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
private final QSCustomizerController mQsCustomizerController;
private final QSTileRevealController.Factory mQsTileRevealControllerFactory;
private final FalsingManager mFalsingManager;
private final CommandQueue mCommandQueue;
private final BrightnessController mBrightnessController;
private final BrightnessSliderController mBrightnessSliderController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
@@ -107,7 +102,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager, CommandQueue commandQueue, FeatureFlags featureFlags) {
FalsingManager falsingManager, FeatureFlags featureFlags) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mQSFgsManagerFooter = qsFgsManagerFooter;
@@ -116,7 +111,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mQsCustomizerController = qsCustomizerController;
mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
mFalsingManager = falsingManager;
mCommandQueue = commandQueue;
mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
mView.setBrightnessView(mBrightnessSliderController.getRootView());
@@ -221,15 +215,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
return mHost;
}
/** Open the details for a specific tile.. */
public void openDetails(String subPanel) {
QSTile tile = getTile(subPanel);
if (tile != null) {
mView.openDetails(tile);
}
}
/** Show the device monitoring dialog. */
public void showDeviceMonitoringDialog() {
mQsSecurityFooter.showDeviceMonitoringDialog();
@@ -260,11 +245,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
});
}
/** */
public void setCallback(QSDetail.Callback qsPanelCallback) {
mView.setCallback(qsPanelCallback);
}
/** */
public void setGridContentVisibility(boolean visible) {
int newVis = visible ? View.VISIBLE : View.INVISIBLE;
@@ -293,19 +273,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mView.setContentMargins(startMargin, endMargin, mMediaHost.getHostView());
}
/** */
public void showDetailAdapter(DetailAdapter detailAdapter, int x, int y) {
// TODO(b/199296365)
// Workaround for opening detail from QQS, when there might not be enough space to
// display e.g. in case of multiuser detail from split shade. Currently showing detail works
// only for QS (mView below) and that's why expanding panel (thus showing QS instead of QQS)
// makes it displayed correctly.
if (!isExpanded()) {
mCommandQueue.animateExpandSettingsPanel(null);
}
mView.showDetailAdapter(true, detailAdapter, new int[]{x, y});
}
/** */
public void setFooterPageIndicator(PageIndicator pageIndicator) {
mView.setFooterPageIndicator(pageIndicator);

View File

@@ -298,21 +298,8 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
mQsCustomizerController.hide();
return;
}
mView.closeDetail();
}
/** */
public void openDetails(String subPanel) {
QSTile tile = getTile(subPanel);
// If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
// QSFactory will not be able to create a tile and getTile will return null
if (tile != null) {
mView.showDetailAdapter(
true, tile.getDetailAdapter(), new int[]{mView.getWidth() / 2, 0});
}
}
void setListening(boolean listening) {
mView.setListening(listening);
@@ -429,7 +416,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
}
/** */
public static final class TileRecord extends QSPanel.Record {
public static final class TileRecord {
public TileRecord(QSTile tile, com.android.systemui.plugins.qs.QSTileView tileView) {
this.tile = tile;
this.tileView = tileView;

View File

@@ -39,7 +39,6 @@ import com.android.internal.policy.SystemBarUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.qs.QSDetail.Callback;
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.phone.StatusIconContainer;
@@ -548,10 +547,6 @@ public class QuickStatusBarHeader extends FrameLayout {
post(() -> setClickable(!mExpanded));
}
public void setCallback(Callback qsPanelCallback) {
mHeaderQsPanel.setCallback(qsPanelCallback);
}
private void setContentMargins(View view, int marginStart, int marginEnd) {
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
lp.setMarginStart(marginStart);

View File

@@ -205,15 +205,6 @@ public class TileQueryHelper {
finished();
}
}
@Override
public void onShowDetail(boolean show) {}
@Override
public void onToggleStateChanged(boolean state) {}
@Override
public void onScanStateChanged(boolean state) {}
}
private void addPackageTiles(final QSTileHost host) {

View File

@@ -53,7 +53,6 @@ import com.android.systemui.qs.tiles.ReduceBrightColorsTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.ScreenRecordTile;
import com.android.systemui.qs.tiles.UiModeNightTile;
import com.android.systemui.qs.tiles.UserTile;
import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.qs.tiles.WorkModeTile;
import com.android.systemui.util.leak.GarbageMonitor;
@@ -82,7 +81,6 @@ public class QSFactoryImpl implements QSFactory {
private final Provider<LocationTile> mLocationTileProvider;
private final Provider<CastTile> mCastTileProvider;
private final Provider<HotspotTile> mHotspotTileProvider;
private final Provider<UserTile> mUserTileProvider;
private final Provider<BatterySaverTile> mBatterySaverTileProvider;
private final Provider<DataSaverTile> mDataSaverTileProvider;
private final Provider<NightDisplayTile> mNightDisplayTileProvider;
@@ -119,7 +117,6 @@ public class QSFactoryImpl implements QSFactory {
Provider<LocationTile> locationTileProvider,
Provider<CastTile> castTileProvider,
Provider<HotspotTile> hotspotTileProvider,
Provider<UserTile> userTileProvider,
Provider<BatterySaverTile> batterySaverTileProvider,
Provider<DataSaverTile> dataSaverTileProvider,
Provider<NightDisplayTile> nightDisplayTileProvider,
@@ -152,7 +149,6 @@ public class QSFactoryImpl implements QSFactory {
mLocationTileProvider = locationTileProvider;
mCastTileProvider = castTileProvider;
mHotspotTileProvider = hotspotTileProvider;
mUserTileProvider = userTileProvider;
mBatterySaverTileProvider = batterySaverTileProvider;
mDataSaverTileProvider = dataSaverTileProvider;
mNightDisplayTileProvider = nightDisplayTileProvider;
@@ -212,8 +208,6 @@ public class QSFactoryImpl implements QSFactory {
return mCastTileProvider.get();
case "hotspot":
return mHotspotTileProvider.get();
case "user":
return mUserTileProvider.get();
case "battery":
return mBatterySaverTileProvider.get();
case "saver":

View File

@@ -60,7 +60,6 @@ import com.android.systemui.Dumpable;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
@@ -261,16 +260,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
return new QSIconViewImpl(context);
}
/** Returns corresponding DetailAdapter. */
@Nullable
public DetailAdapter getDetailAdapter() {
return null; // optional
}
protected DetailAdapter createDetailAdapter() {
throw new UnsupportedOperationException();
}
/**
* Is a startup check whether this device currently supports this tile.
* Should not be used to conditionally hide tiles. Only checked on tile
@@ -337,10 +326,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
.addTaggedData(FIELD_QS_POSITION, mHost.indexOf(mTileSpec));
}
public void showDetail(boolean show) {
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0).sendToTarget();
}
public void refreshState() {
refreshState(null);
}
@@ -353,14 +338,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget();
}
public void fireToggleStateChanged(boolean state) {
mHandler.obtainMessage(H.TOGGLE_STATE_CHANGED, state ? 1 : 0, 0).sendToTarget();
}
public void fireScanStateChanged(boolean state) {
mHandler.obtainMessage(H.SCAN_STATE_CHANGED, state ? 1 : 0, 0).sendToTarget();
}
public void destroy() {
mHandler.sendEmptyMessage(H.DESTROY);
}
@@ -462,29 +439,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
}
}
private void handleShowDetail(boolean show) {
mShowingDetail = show;
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onShowDetail(show);
}
}
protected boolean isShowingDetail() {
return mShowingDetail;
}
private void handleToggleStateChanged(boolean state) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onToggleStateChanged(state);
}
}
private void handleScanStateChanged(boolean state) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onScanStateChanged(state);
}
}
protected void handleUserSwitch(int newUserId) {
handleRefreshState(null);
}
@@ -591,17 +545,14 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
private static final int SECONDARY_CLICK = 3;
private static final int LONG_CLICK = 4;
private static final int REFRESH_STATE = 5;
private static final int SHOW_DETAIL = 6;
private static final int USER_SWITCH = 7;
private static final int TOGGLE_STATE_CHANGED = 8;
private static final int SCAN_STATE_CHANGED = 9;
private static final int DESTROY = 10;
private static final int REMOVE_CALLBACKS = 11;
private static final int REMOVE_CALLBACK = 12;
private static final int SET_LISTENING = 13;
private static final int USER_SWITCH = 6;
private static final int DESTROY = 7;
private static final int REMOVE_CALLBACKS = 8;
private static final int REMOVE_CALLBACK = 9;
private static final int SET_LISTENING = 10;
@VisibleForTesting
protected static final int STALE = 14;
private static final int INITIALIZE = 15;
protected static final int STALE = 11;
private static final int INITIALIZE = 12;
@VisibleForTesting
protected H(Looper looper) {
@@ -639,18 +590,9 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
} else if (msg.what == REFRESH_STATE) {
name = "handleRefreshState";
handleRefreshState(msg.obj);
} else if (msg.what == SHOW_DETAIL) {
name = "handleShowDetail";
handleShowDetail(msg.arg1 != 0);
} else if (msg.what == USER_SWITCH) {
name = "handleUserSwitch";
handleUserSwitch(msg.arg1);
} else if (msg.what == TOGGLE_STATE_CHANGED) {
name = "handleToggleStateChanged";
handleToggleStateChanged(msg.arg1 != 0);
} else if (msg.what == SCAN_STATE_CHANGED) {
name = "handleScanStateChanged";
handleScanStateChanged(msg.arg1 != 0);
} else if (msg.what == DESTROY) {
name = "handleDestroy";
handleDestroy();

View File

@@ -19,7 +19,6 @@ package com.android.systemui.qs.tiles;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -29,7 +28,6 @@ import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import androidx.annotation.Nullable;
@@ -38,24 +36,18 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BluetoothController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
@@ -65,7 +57,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
private final BluetoothController mController;
private final BluetoothDetailAdapter mDetailAdapter;
@Inject
public BluetoothTile(
@@ -82,15 +73,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = bluetoothController;
mDetailAdapter = (BluetoothDetailAdapter) createDetailAdapter();
mController.observe(getLifecycle(), mCallback);
}
@Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
@Override
public BooleanState newTileState() {
return new BooleanState();
@@ -117,7 +102,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
new Intent(Settings.ACTION_BLUETOOTH_SETTINGS), 0);
return;
}
showDetail(true);
if (!mState.value) {
mController.setBluetoothEnabled(true);
}
@@ -251,53 +235,14 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
@Override
public void onBluetoothStateChange(boolean enabled) {
refreshState();
if (isShowingDetail()) {
mDetailAdapter.updateItems();
fireToggleStateChanged(mDetailAdapter.getToggleState());
}
}
@Override
public void onBluetoothDevicesChanged() {
refreshState();
if (isShowingDetail()) {
mDetailAdapter.updateItems();
}
}
};
@Override
protected DetailAdapter createDetailAdapter() {
return new BluetoothDetailAdapter();
}
/**
* Bluetooth icon wrapper for Quick Settings with a battery indicator that reflects the
* connected device's battery level. This is used instead of
* {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to use a context
* that reflects dark/light theme attributes.
*/
private class BluetoothBatteryTileIcon extends Icon {
private int mBatteryLevel;
private float mIconScale;
BluetoothBatteryTileIcon(int batteryLevel, float iconScale) {
mBatteryLevel = batteryLevel;
mIconScale = iconScale;
}
@Override
public Drawable getDrawable(Context context) {
// This method returns Pair<Drawable, String> while first value is the drawable
return BluetoothDeviceLayerDrawable.createLayerDrawable(
context,
R.drawable.ic_bluetooth_connected,
mBatteryLevel,
mIconScale);
}
}
/**
* Bluetooth icon wrapper (when connected with no battery indicator) for Quick Settings. This is
* used instead of {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to
@@ -315,129 +260,4 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
return context.getDrawable(R.drawable.ic_bluetooth_connected);
}
}
protected class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
// We probably won't ever have space in the UI for more than 20 devices, so don't
// get info for them.
private static final int MAX_DEVICES = 20;
@Nullable
private QSDetailItems mItems;
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_bluetooth_label);
}
@Override
public Boolean getToggleState() {
return mState.value;
}
@Override
public boolean getToggleEnabled() {
return mController.getBluetoothState() == BluetoothAdapter.STATE_OFF
|| mController.getBluetoothState() == BluetoothAdapter.STATE_ON;
}
@Override
public Intent getSettingsIntent() {
return BLUETOOTH_SETTINGS;
}
@Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state);
mController.setBluetoothEnabled(state);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_BLUETOOTH_DETAILS;
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Bluetooth");
mItems.setCallback(this);
updateItems();
setItemsVisible(mState.value);
return mItems;
}
public void setItemsVisible(boolean visible) {
if (mItems == null) return;
mItems.setItemsVisible(visible);
}
private void updateItems() {
if (mItems == null) return;
if (mController.isBluetoothEnabled()) {
mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
R.string.quick_settings_bluetooth_detail_empty_text);
} else {
mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
R.string.bt_is_off);
}
ArrayList<Item> items = new ArrayList<Item>();
final Collection<CachedBluetoothDevice> devices = mController.getDevices();
if (devices != null) {
int connectedDevices = 0;
int count = 0;
for (CachedBluetoothDevice device : devices) {
if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue;
final Item item =
new Item(
com.android.internal.R.drawable.ic_qs_bluetooth,
device.getName(),
device);
int state = device.getMaxConnectionState();
if (state == BluetoothProfile.STATE_CONNECTED) {
item.iconResId = R.drawable.ic_bluetooth_connected;
int batteryLevel = device.getBatteryLevel();
if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
item.icon = new BluetoothBatteryTileIcon(batteryLevel,1 /* iconScale */);
item.line2 = mContext.getString(
R.string.quick_settings_connected_battery_level,
Utils.formatPercentage(batteryLevel));
} else {
item.line2 = mContext.getString(R.string.quick_settings_connected);
}
item.canDisconnect = true;
items.add(connectedDevices, item);
connectedDevices++;
} else if (state == BluetoothProfile.STATE_CONNECTING) {
item.iconResId = R.drawable.ic_qs_bluetooth_connecting;
item.line2 = mContext.getString(R.string.quick_settings_connecting);
items.add(connectedDevices, item);
} else {
items.add(item);
}
if (++count == MAX_DEVICES) {
break;
}
}
}
mItems.setItems(items.toArray(new Item[items.size()]));
}
@Override
public void onDetailItemClick(Item item) {
if (item == null || item.tag == null) return;
final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
if (device != null && device.getMaxConnectionState()
== BluetoothProfile.STATE_DISCONNECTED) {
mController.connect(device);
}
}
@Override
public void onDetailItemDisconnect(Item item) {
if (item == null || item.tag == null) return;
final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
if (device != null) {
mController.disconnect(device);
}
}
}
}

View File

@@ -20,7 +20,6 @@ import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRouter.RouteInfo;
import android.os.Handler;
@@ -29,8 +28,6 @@ import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.Nullable;
@@ -44,11 +41,8 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -62,7 +56,6 @@ import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import javax.inject.Inject;
@@ -73,7 +66,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
new Intent(Settings.ACTION_CAST_SETTINGS);
private final CastController mController;
private final CastDetailAdapter mDetailAdapter;
private final KeyguardStateController mKeyguard;
private final NetworkController mNetworkController;
private final DialogLaunchAnimator mDialogLaunchAnimator;
@@ -100,7 +92,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = castController;
mDetailAdapter = new CastDetailAdapter();
mKeyguard = keyguardStateController;
mNetworkController = networkController;
mDialogLaunchAnimator = dialogLaunchAnimator;
@@ -110,11 +101,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
hotspotController.observe(this, mHotspotCallback);
}
@Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
@Override
public BooleanState newTileState() {
BooleanState state = new BooleanState();
@@ -154,14 +140,14 @@ public class CastTile extends QSTileImpl<BooleanState> {
}
List<CastDevice> activeDevices = getActiveDevices();
if (willPopDetail()) {
if (willPopDialog()) {
if (!mKeyguard.isShowing()) {
showDetail(view);
showDialog(view);
} else {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
// Dismissing the keyguard will collapse the shade, so we don't animate from the
// view here as it would not look good.
showDetail(null /* view */);
showDialog(null /* view */);
});
}
} else {
@@ -173,7 +159,7 @@ public class CastTile extends QSTileImpl<BooleanState> {
// (neither routes nor projection), or if we have an active route. In other cases, we assume
// that a projection is active. This is messy, but this tile never correctly handled the
// case where multiple devices were active :-/.
private boolean willPopDetail() {
private boolean willPopDialog() {
List<CastDevice> activeDevices = getActiveDevices();
return activeDevices.isEmpty() || (activeDevices.get(0).tag instanceof RouteInfo);
}
@@ -190,11 +176,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
return activeDevices;
}
@Override
public void showDetail(boolean show) {
showDetail(null /* view */);
}
private static class DialogHolder {
private Dialog mDialog;
@@ -203,7 +184,7 @@ public class CastTile extends QSTileImpl<BooleanState> {
}
}
private void showDetail(@Nullable View view) {
private void showDialog(@Nullable View view) {
mUiHandler.post(() -> {
final DialogHolder holder = new DialogHolder();
final Dialog dialog = MediaRouteDialogPresenter.createDialog(
@@ -268,10 +249,8 @@ public class CastTile extends QSTileImpl<BooleanState> {
if (!state.value) {
state.secondaryLabel = "";
}
state.contentDescription = state.contentDescription + ","
+ mContext.getString(R.string.accessibility_quick_settings_open_details);
state.expandedAccessibilityClassName = Button.class.getName();
state.forceExpandIcon = willPopDetail();
state.forceExpandIcon = willPopDialog();
} else {
state.state = Tile.STATE_UNAVAILABLE;
String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi);
@@ -279,7 +258,6 @@ public class CastTile extends QSTileImpl<BooleanState> {
state.forceExpandIcon = false;
}
state.stateDescription = state.stateDescription + ", " + state.secondaryLabel;
mDetailAdapter.updateItems(devices);
}
@Override
@@ -339,118 +317,4 @@ public class CastTile extends QSTileImpl<BooleanState> {
refreshState();
}
};
private final class CastDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
private final LinkedHashMap<String, CastDevice> mVisibleOrder = new LinkedHashMap<>();
private QSDetailItems mItems;
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_cast_title);
}
@Override
public Boolean getToggleState() {
return null;
}
@Override
public Intent getSettingsIntent() {
return CAST_SETTINGS;
}
@Override
public void setToggleState(boolean state) {
// noop
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_CAST_DETAILS;
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Cast");
if (convertView == null) {
if (DEBUG) Log.d(TAG, "addOnAttachStateChangeListener");
mItems.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
if (DEBUG) Log.d(TAG, "onViewAttachedToWindow");
}
@Override
public void onViewDetachedFromWindow(View v) {
if (DEBUG) Log.d(TAG, "onViewDetachedFromWindow");
mVisibleOrder.clear();
}
});
}
mItems.setEmptyState(R.drawable.ic_qs_cast_detail_empty,
R.string.quick_settings_cast_detail_empty_text);
mItems.setCallback(this);
updateItems(mController.getCastDevices());
mController.setDiscovering(true);
return mItems;
}
private void updateItems(List<CastDevice> devices) {
if (mItems == null) return;
Item[] items = null;
if (devices != null && !devices.isEmpty()) {
// if we are connected, simply show that device
for (CastDevice device : devices) {
if (device.state == CastDevice.STATE_CONNECTED) {
final Item item =
new Item(
R.drawable.ic_cast_connected,
getDeviceName(device),
device);
item.line2 = mContext.getString(R.string.quick_settings_connected);
item.canDisconnect = true;
items = new Item[] { item };
break;
}
}
// otherwise list all available devices, and don't move them around
if (items == null) {
for (CastDevice device : devices) {
mVisibleOrder.put(device.id, device);
}
items = new Item[devices.size()];
int i = 0;
for (String id : mVisibleOrder.keySet()) {
final CastDevice device = mVisibleOrder.get(id);
if (!devices.contains(device)) continue;
final Item item =
new Item(R.drawable.ic_cast, getDeviceName(device), device);
if (device.state == CastDevice.STATE_CONNECTING) {
item.line2 = mContext.getString(R.string.quick_settings_connecting);
}
items[i++] = item;
}
}
}
mItems.setItems(items);
}
@Override
public void onDetailItemClick(Item item) {
if (item == null || item.tag == null) return;
MetricsLogger.action(mContext, MetricsEvent.QS_CAST_SELECT);
final CastDevice device = (CastDevice) item.tag;
mController.startCasting(device);
}
@Override
public void onDetailItemDisconnect(Item item) {
if (item == null || item.tag == null) return;
MetricsLogger.action(mContext, MetricsEvent.QS_CAST_DISCONNECT);
final CastDevice device = (CastDevice) item.tag;
mController.stopCasting(device);
}
}
}

View File

@@ -32,9 +32,7 @@ import android.service.quicksettings.Tile;
import android.telephony.SubscriptionManager;
import android.text.Html;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.Switch;
@@ -49,7 +47,6 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -71,7 +68,6 @@ public class CellularTile extends QSTileImpl<SignalState> {
private final NetworkController mController;
private final DataUsageController mDataController;
private final CellularDetailAdapter mDetailAdapter;
private final CellSignalCallback mSignalCallback = new CellSignalCallback();
@@ -91,7 +87,6 @@ public class CellularTile extends QSTileImpl<SignalState> {
statusBarStateController, activityStarter, qsLogger);
mController = networkController;
mDataController = mController.getMobileDataController();
mDetailAdapter = new CellularDetailAdapter();
mController.observe(getLifecycle(), mSignalCallback);
}
@@ -105,11 +100,6 @@ public class CellularTile extends QSTileImpl<SignalState> {
return new SignalTileView(context);
}
@Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
@Override
public Intent getLongClickIntent() {
if (getState().state == Tile.STATE_UNAVAILABLE) {
@@ -161,12 +151,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
protected void handleSecondaryClick(@Nullable View view) {
if (mDataController.isMobileDataSupported()) {
showDetail(true);
} else {
mActivityStarter
.postStartActivityDismissingKeyguard(getCellularSettingIntent(),0 /* delay */);
}
handleLongClick(view);
}
@Override
@@ -298,11 +283,6 @@ public class CellularTile extends QSTileImpl<SignalState> {
mInfo.airplaneModeEnabled = icon.visible;
refreshState(mInfo);
}
@Override
public void setMobileDataEnabled(boolean enabled) {
mDetailAdapter.setMobileDataEnabled(enabled);
}
}
static Intent getCellularSettingIntent() {
@@ -314,53 +294,4 @@ public class CellularTile extends QSTileImpl<SignalState> {
}
return intent;
}
private final class CellularDetailAdapter implements DetailAdapter {
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_cellular_detail_title);
}
@Nullable
@Override
public Boolean getToggleState() {
return mDataController.isMobileDataSupported()
? mDataController.isMobileDataEnabled()
: null;
}
@Override
public Intent getSettingsIntent() {
return getCellularSettingIntent();
}
@Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state);
mDataController.setMobileDataEnabled(state);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_DATAUSAGEDETAIL;
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
? convertView
: LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
final DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
if (info == null) return v;
v.bind(info);
v.findViewById(R.id.roaming_text).setVisibility(mSignalCallback.mInfo.roaming
? View.VISIBLE : View.INVISIBLE);
return v;
}
public void setMobileDataEnabled(boolean enabled) {
fireToggleStateChanged(enabled);
}
}
}

View File

@@ -25,8 +25,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -34,16 +32,10 @@ import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ZenRule;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.Toast;
import androidx.annotation.Nullable;
@@ -52,13 +44,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.notification.EnableZenModeDialog;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
@@ -69,7 +59,6 @@ import com.android.systemui.qs.tiles.dialog.QSZenModeDialogMetricsLogger;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.volume.ZenModePanel;
import javax.inject.Inject;
@@ -83,14 +72,12 @@ public class DndTile extends QSTileImpl<BooleanState> {
new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
private final SharedPreferences mSharedPreferences;
private final SettingObserver mSettingZenDuration;
private final DialogLaunchAnimator mDialogLaunchAnimator;
private final QSZenModeDialogMetricsLogger mQSZenDialogMetricsLogger;
private boolean mListening;
private boolean mShowingDetail;
@Inject
public DndTile(
@@ -111,7 +98,6 @@ public class DndTile extends QSTileImpl<BooleanState> {
statusBarStateController, activityStarter, qsLogger);
mController = zenModeController;
mSharedPreferences = sharedPreferences;
mDetailAdapter = new DndDetailAdapter();
mController.observe(getLifecycle(), mZenCallback);
mDialogLaunchAnimator = dialogLaunchAnimator;
mSettingZenDuration = new SettingObserver(secureSettings, mUiHandler,
@@ -141,11 +127,6 @@ public class DndTile extends QSTileImpl<BooleanState> {
false /* defaultValue */);
}
@Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
@Override
public BooleanState newTileState() {
return new BooleanState();
@@ -225,28 +206,7 @@ public class DndTile extends QSTileImpl<BooleanState> {
@Override
protected void handleSecondaryClick(@Nullable View view) {
if (mController.isVolumeRestricted()) {
// Collapse the panels, so the user can see the toast.
mHost.collapsePanels();
SysUIToast.makeText(mContext, mContext.getString(
com.android.internal.R.string.error_message_change_not_allowed),
Toast.LENGTH_LONG).show();
return;
}
if (!mState.value) {
// Because of the complexity of the zen panel, it needs to be shown after
// we turn on zen below.
mController.addCallback(new ZenModeController.Callback() {
@Override
public void onZenChanged(int zen) {
mController.removeCallback(this);
showDetail(true);
}
});
mController.setZen(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
} else {
showDetail(true);
}
handleLongClick(view);
}
@Override
@@ -295,9 +255,6 @@ public class DndTile extends QSTileImpl<BooleanState> {
R.string.accessibility_quick_settings_dnd);
break;
}
if (valueChanged) {
fireToggleStateChanged(state.value);
}
state.dualLabelContentDescription = mContext.getResources().getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
@@ -349,146 +306,6 @@ public class DndTile extends QSTileImpl<BooleanState> {
private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
public void onZenChanged(int zen) {
refreshState(zen);
if (isShowingDetail()) {
mDetailAdapter.updatePanel();
}
}
@Override
public void onConfigChanged(ZenModeConfig config) {
if (isShowingDetail()) {
mDetailAdapter.updatePanel();
}
}
};
private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
@Nullable
private ZenModePanel mZenPanel;
private boolean mAuto;
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_dnd_label);
}
@Override
public Boolean getToggleState() {
return mState.value;
}
@Override
public Intent getSettingsIntent() {
return ZEN_SETTINGS;
}
@Override
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
if (!state) {
mController.setZen(ZEN_MODE_OFF, null, TAG);
mAuto = false;
} else {
mController.setZen(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
}
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_DND_DETAILS;
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
mZenPanel = convertView != null ? (ZenModePanel) convertView
: (ZenModePanel) LayoutInflater.from(context).inflate(
R.layout.zen_mode_panel, parent, false);
if (convertView == null) {
mZenPanel.init(mController);
mZenPanel.addOnAttachStateChangeListener(this);
mZenPanel.setCallback(mZenModePanelCallback);
mZenPanel.setEmptyState(R.drawable.ic_qs_dnd_detail_empty, R.string.dnd_is_off);
}
updatePanel();
return mZenPanel;
}
private void updatePanel() {
if (mZenPanel == null) return;
mAuto = false;
if (mController.getZen() == ZEN_MODE_OFF) {
mZenPanel.setState(ZenModePanel.STATE_OFF);
} else {
ZenModeConfig config = mController.getConfig();
String summary = "";
if (config.manualRule != null && config.manualRule.enabler != null) {
summary = getOwnerCaption(config.manualRule.enabler);
}
for (ZenRule automaticRule : config.automaticRules.values()) {
if (automaticRule.isAutomaticActive()) {
if (summary.isEmpty()) {
summary = mContext.getString(R.string.qs_dnd_prompt_auto_rule,
automaticRule.name);
} else {
summary = mContext.getString(R.string.qs_dnd_prompt_auto_rule_app);
}
}
}
if (summary.isEmpty()) {
mZenPanel.setState(ZenModePanel.STATE_MODIFY);
} else {
mAuto = true;
mZenPanel.setState(ZenModePanel.STATE_AUTO_RULE);
mZenPanel.setAutoText(summary);
}
}
}
private String getOwnerCaption(String owner) {
final PackageManager pm = mContext.getPackageManager();
try {
final ApplicationInfo info = pm.getApplicationInfo(owner, 0);
if (info != null) {
final CharSequence seq = info.loadLabel(pm);
if (seq != null) {
final String str = seq.toString().trim();
return mContext.getString(R.string.qs_dnd_prompt_app, str);
}
}
} catch (Throwable e) {
Slog.w(TAG, "Error loading owner caption", e);
}
return "";
}
@Override
public void onViewAttachedToWindow(View v) {
mShowingDetail = true;
}
@Override
public void onViewDetachedFromWindow(View v) {
mShowingDetail = false;
mZenPanel = null;
}
}
private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
@Override
public void onPrioritySettings() {
mActivityStarter.postStartActivityDismissingKeyguard(
ZEN_PRIORITY_SETTINGS, 0);
}
@Override
public void onInteraction() {
// noop
}
@Override
public void onExpanded(boolean expanded) {
// noop
}
};

View File

@@ -411,10 +411,6 @@ public class InternetTile extends QSTileImpl<SignalState> {
}
boolean wifiConnected = cb.mEnabled && (cb.mWifiSignalIconId > 0) && (cb.mSsid != null);
boolean wifiNotConnected = (cb.mWifiSignalIconId > 0) && (cb.mSsid == null);
boolean enabledChanging = state.value != cb.mEnabled;
if (enabledChanging) {
fireToggleStateChanged(cb.mEnabled);
}
if (state.slash == null) {
state.slash = new SlashState();
state.slash.rotation = 6;

View File

@@ -36,7 +36,6 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
@@ -134,12 +133,6 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS
return new Intent(Settings.ACTION_PRIVACY_SETTINGS);
}
@Nullable
@Override
public DetailAdapter getDetailAdapter() {
return super.getDetailAdapter();
}
@Override
public void onSensorBlockedChanged(int sensor, boolean blocked) {
if (sensor == getSensorId()) {

View File

@@ -150,6 +150,6 @@ public class UserDetailItemView extends LinearLayout {
}
protected int getFontSizeDimen() {
return R.dimen.qs_detail_item_secondary_text_size;
return R.dimen.qs_tile_text_size;
}
}

View File

@@ -1,127 +0,0 @@
/*
* Copyright (C) 2015 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.qs.tiles;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Pair;
import android.view.View;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import javax.inject.Inject;
public class UserTile extends QSTileImpl<State> implements UserInfoController.OnUserInfoChangedListener {
private final UserSwitcherController mUserSwitcherController;
private final UserInfoController mUserInfoController;
@Nullable
private Pair<String, Drawable> mLastUpdate;
@Inject
public UserTile(
QSHost host,
@Background Looper backgroundLooper,
@Main Handler mainHandler,
FalsingManager falsingManager,
MetricsLogger metricsLogger,
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
UserSwitcherController userSwitcherController,
UserInfoController userInfoController
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mUserSwitcherController = userSwitcherController;
mUserInfoController = userInfoController;
mUserInfoController.observe(getLifecycle(), this);
}
@Override
public State newTileState() {
return new QSTile.State();
}
@Override
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_USER_SETTINGS);
}
@Override
protected void handleClick(@Nullable View view) {
showDetail(true);
}
@Override
public DetailAdapter getDetailAdapter() {
return mUserSwitcherController.mUserDetailAdapter;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_USER_TILE;
}
@Override
public CharSequence getTileLabel() {
return getState().label;
}
@Override
protected void handleUpdateState(State state, Object arg) {
final Pair<String, Drawable> p = arg != null ? (Pair<String, Drawable>) arg : mLastUpdate;
if (p != null) {
state.label = p.first;
// TODO: Better content description.
state.contentDescription = p.first;
state.icon = new Icon() {
@Override
public Drawable getDrawable(Context context) {
return p.second;
}
};
} else {
// TODO: Default state.
}
}
@Override
public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
mLastUpdate = new Pair<>(name, picture);
refreshState(mLastUpdate);
}
}

View File

@@ -28,27 +28,22 @@ import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.AlphaControlledSignalTileView;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSIconViewImpl;
@@ -58,9 +53,6 @@ import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
import com.android.systemui.statusbar.connectivity.WifiIcons;
import com.android.systemui.statusbar.connectivity.WifiIndicators;
import com.android.wifitrackerlib.WifiEntry;
import java.util.List;
import javax.inject.Inject;
@@ -70,7 +62,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
protected final NetworkController mController;
private final AccessPointController mWifiController;
private final WifiDetailAdapter mDetailAdapter;
private final QSTile.SignalState mStateBeforeClick = newTileState();
protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
@@ -93,7 +84,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
statusBarStateController, activityStarter, qsLogger);
mController = networkController;
mWifiController = accessPointController;
mDetailAdapter = (WifiDetailAdapter) createDetailAdapter();
mController.observe(getLifecycle(), mSignalCallback);
mStateBeforeClick.spec = "wifi";
}
@@ -103,25 +93,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
return new SignalState();
}
@Override
public void setDetailListening(boolean listening) {
if (listening) {
mWifiController.addAccessPointCallback(mDetailAdapter);
} else {
mWifiController.removeAccessPointCallback(mDetailAdapter);
}
}
@Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
@Override
protected DetailAdapter createDetailAdapter() {
return new WifiDetailAdapter();
}
@Override
public QSIconView createTileView(Context context) {
return new AlphaControlledSignalTileView(context);
@@ -158,7 +129,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
new Intent(Settings.ACTION_WIFI_SETTINGS), 0);
return;
}
showDetail(true);
if (!mState.value) {
mController.setWifiEnabled(true);
}
@@ -185,11 +155,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
&& (cb.ssid != null || cb.wifiSignalIconId != WifiIcons.QS_WIFI_NO_NETWORK);
boolean wifiNotConnected = (cb.ssid == null)
&& (cb.wifiSignalIconId == WifiIcons.QS_WIFI_NO_NETWORK);
boolean enabledChanging = state.value != cb.enabled;
if (enabledChanging) {
mDetailAdapter.setItemsVisible(cb.enabled);
fireToggleStateChanged(cb.enabled);
}
if (state.slash == null) {
state.slash = new SlashState();
state.slash.rotation = 6;
@@ -315,150 +280,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
mInfo.wifiSignalContentDescription = indicators.qsIcon.contentDescription;
mInfo.isTransient = indicators.isTransient;
mInfo.statusLabel = indicators.statusLabel;
if (isShowingDetail()) {
mDetailAdapter.updateItems();
}
refreshState();
}
}
protected class WifiDetailAdapter implements DetailAdapter,
AccessPointController.AccessPointCallback, QSDetailItems.Callback {
@Nullable
private QSDetailItems mItems;
@Nullable
private WifiEntry[] mAccessPoints;
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_wifi_label);
}
public Intent getSettingsIntent() {
return WIFI_SETTINGS;
}
@Override
public Boolean getToggleState() {
return mState.value;
}
@Override
public void setToggleState(boolean state) {
if (DEBUG) Log.d(TAG, "setToggleState " + state);
MetricsLogger.action(mContext, MetricsEvent.QS_WIFI_TOGGLE, state);
mController.setWifiEnabled(state);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_WIFI_DETAILS;
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
mAccessPoints = null;
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Wifi");
mItems.setCallback(this);
mWifiController.scanForAccessPoints(); // updates APs and items
setItemsVisible(mState.value);
return mItems;
}
@Override
public void onAccessPointsChanged(final List<WifiEntry> accessPoints) {
mAccessPoints = filterUnreachableAPs(accessPoints);
updateItems();
}
/** Filter unreachable APs from mAccessPoints */
private WifiEntry[] filterUnreachableAPs(List<WifiEntry> unfiltered) {
int numReachable = 0;
for (WifiEntry ap : unfiltered) {
if (isWifiEntryReachable(ap)) numReachable++;
}
if (numReachable != unfiltered.size()) {
WifiEntry[] accessPoints = new WifiEntry[numReachable];
int i = 0;
for (WifiEntry ap : unfiltered) {
if (isWifiEntryReachable(ap)) accessPoints[i++] = ap;
}
return accessPoints;
}
return unfiltered.toArray(new WifiEntry[0]);
}
@Override
public void onSettingsActivityTriggered(Intent settingsIntent) {
mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
}
@Override
public void onDetailItemClick(Item item) {
if (item == null || item.tag == null) return;
final WifiEntry ap = (WifiEntry) item.tag;
if (ap.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
if (mWifiController.connect(ap)) {
mHost.collapsePanels();
}
}
showDetail(false);
}
@Override
public void onDetailItemDisconnect(Item item) {
// noop
}
public void setItemsVisible(boolean visible) {
if (mItems == null) return;
mItems.setItemsVisible(visible);
}
private void updateItems() {
if (mItems == null) return;
if ((mAccessPoints != null && mAccessPoints.length > 0)
|| !mSignalCallback.mInfo.enabled) {
fireScanStateChanged(false);
} else {
fireScanStateChanged(true);
}
// Wi-Fi is off
if (!mSignalCallback.mInfo.enabled) {
mItems.setEmptyState(WifiIcons.QS_WIFI_NO_NETWORK,
R.string.wifi_is_off);
mItems.setItems(null);
return;
}
// No available access points
mItems.setEmptyState(WifiIcons.QS_WIFI_NO_NETWORK,
R.string.quick_settings_wifi_detail_empty_text);
// Build the list
Item[] items = null;
if (mAccessPoints != null) {
items = new Item[mAccessPoints.length];
for (int i = 0; i < mAccessPoints.length; i++) {
final WifiEntry ap = mAccessPoints[i];
final Item item = new Item(mWifiController.getIcon(ap), ap.getSsid(), ap);
item.line2 = ap.getSummary();
item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
? R.drawable.qs_ic_wifi_lock
: -1;
items[i] = item;
}
}
mItems.setItems(items);
}
}
private static boolean isWifiEntryReachable(WifiEntry ap) {
return ap.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE;
}
}

View File

@@ -24,11 +24,13 @@ import android.provider.Settings
import android.view.LayoutInflater
import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.internal.logging.UiEventLogger
import com.android.systemui.R
import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.QSUserSwitcherEvent
import com.android.systemui.qs.tiles.UserDetailView
import com.android.systemui.statusbar.phone.SystemUIDialog
import javax.inject.Inject
@@ -43,6 +45,7 @@ class UserSwitchDialogController @VisibleForTesting constructor(
private val activityStarter: ActivityStarter,
private val falsingManager: FalsingManager,
private val dialogLaunchAnimator: DialogLaunchAnimator,
private val uiEventLogger: UiEventLogger,
private val dialogFactory: (Context) -> SystemUIDialog
) {
@@ -51,12 +54,14 @@ class UserSwitchDialogController @VisibleForTesting constructor(
userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>,
activityStarter: ActivityStarter,
falsingManager: FalsingManager,
dialogLaunchAnimator: DialogLaunchAnimator
dialogLaunchAnimator: DialogLaunchAnimator,
uiEventLogger: UiEventLogger
) : this(
userDetailViewAdapterProvider,
activityStarter,
falsingManager,
dialogLaunchAnimator,
uiEventLogger,
{ SystemUIDialog(it) }
)
@@ -76,10 +81,13 @@ class UserSwitchDialogController @VisibleForTesting constructor(
setCanceledOnTouchOutside(true)
setTitle(R.string.qs_user_switch_dialog_title)
setPositiveButton(R.string.quick_settings_done, null)
setPositiveButton(R.string.quick_settings_done) { _, _ ->
uiEventLogger.log(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE)
}
setNeutralButton(R.string.quick_settings_more_user_settings) { _, _ ->
if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations()
uiEventLogger.log(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS)
activityStarter.postStartActivityDismissingKeyguard(
USER_SETTINGS_INTENT,
0
@@ -95,6 +103,7 @@ class UserSwitchDialogController @VisibleForTesting constructor(
adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid))
dialogLaunchAnimator.showFromView(this, view)
uiEventLogger.log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN)
adapter.injectDialogShower(DialogShowerImpl(this, dialogLaunchAnimator))
}
}

View File

@@ -29,9 +29,7 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.FooterActionsView;
import com.android.systemui.qs.QSDetailDisplayer;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -44,7 +42,6 @@ import javax.inject.Inject;
public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
private final UserManager mUserManager;
private final UserSwitcherController mUserSwitcherController;
private final QSDetailDisplayer mQsDetailDisplayer;
private final FalsingManager mFalsingManager;
private final UserSwitchDialogController mUserSwitchDialogController;
private final ActivityStarter mActivityStarter;
@@ -66,17 +63,8 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
mActivityStarter.startActivity(intent, true /* dismissShade */,
ActivityLaunchAnimator.Controller.fromView(v, null),
true /* showOverlockscreenwhenlocked */);
} else if (mFeatureFlags.isEnabled(Flags.NEW_USER_SWITCHER)) {
mUserSwitchDialogController.showDialog(v);
} else {
View center = mView.getChildCount() > 0 ? mView.getChildAt(0) : mView;
int[] tmpInt = new int[2];
center.getLocationInWindow(tmpInt);
tmpInt[0] += center.getWidth() / 2;
tmpInt[1] += center.getHeight() / 2;
mQsDetailDisplayer.showDetailAdapter(getUserDetailAdapter(), tmpInt[0], tmpInt[1]);
mUserSwitchDialogController.showDialog(v);
}
}
};
@@ -85,7 +73,6 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
public static class Factory {
private final UserManager mUserManager;
private final UserSwitcherController mUserSwitcherController;
private final QSDetailDisplayer mQsDetailDisplayer;
private final FalsingManager mFalsingManager;
private final UserSwitchDialogController mUserSwitchDialogController;
private final ActivityStarter mActivityStarter;
@@ -93,12 +80,11 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
@Inject
public Factory(UserManager userManager, UserSwitcherController userSwitcherController,
QSDetailDisplayer qsDetailDisplayer, FalsingManager falsingManager,
FalsingManager falsingManager,
UserSwitchDialogController userSwitchDialogController, FeatureFlags featureFlags,
ActivityStarter activityStarter) {
mUserManager = userManager;
mUserSwitcherController = userSwitcherController;
mQsDetailDisplayer = qsDetailDisplayer;
mFalsingManager = falsingManager;
mUserSwitchDialogController = userSwitchDialogController;
mActivityStarter = activityStarter;
@@ -107,20 +93,19 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
public MultiUserSwitchController create(FooterActionsView view) {
return new MultiUserSwitchController(view.findViewById(R.id.multi_user_switch),
mUserManager, mUserSwitcherController, mQsDetailDisplayer,
mUserManager, mUserSwitcherController,
mFalsingManager, mUserSwitchDialogController, mFeatureFlags,
mActivityStarter);
}
}
private MultiUserSwitchController(MultiUserSwitch view, UserManager userManager,
UserSwitcherController userSwitcherController, QSDetailDisplayer qsDetailDisplayer,
UserSwitcherController userSwitcherController,
FalsingManager falsingManager, UserSwitchDialogController userSwitchDialogController,
FeatureFlags featureFlags, ActivityStarter activityStarter) {
super(view);
mUserManager = userManager;
mUserSwitcherController = userSwitcherController;
mQsDetailDisplayer = qsDetailDisplayer;
mFalsingManager = falsingManager;
mUserSwitchDialogController = userSwitchDialogController;
mFeatureFlags = featureFlags;
@@ -143,10 +128,6 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
mView.setOnClickListener(null);
}
protected DetailAdapter getUserDetailAdapter() {
return mUserSwitcherController.mUserDetailAdapter;
}
private void registerListener() {
if (mUserManager.isUserSwitcherEnabled() && mUserListener == null) {

View File

@@ -146,12 +146,10 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingManager.FalsingTapListener;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController;
import com.android.systemui.qs.QSDetailDisplayer;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -325,7 +323,6 @@ public class NotificationPanelViewController extends PanelViewController
private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
private final IdleViewComponent.Factory mIdleViewComponentFactory;
private final QSDetailDisplayer mQSDetailDisplayer;
private final FragmentService mFragmentService;
private final ScrimController mScrimController;
private final PrivacyDotViewController mPrivacyDotViewController;
@@ -773,7 +770,6 @@ public class NotificationPanelViewController extends PanelViewController
CommunalViewComponent.Factory communalViewComponentFactory,
IdleViewComponent.Factory idleViewComponentFactory,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
QSDetailDisplayer qsDetailDisplayer,
NotificationGroupManagerLegacy groupManager,
NotificationIconAreaController notificationIconAreaController,
AuthController authController,
@@ -848,7 +844,6 @@ public class NotificationPanelViewController extends PanelViewController
mContentResolver = contentResolver;
mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
mQSDetailDisplayer = qsDetailDisplayer;
mFragmentService = fragmentService;
mSettingsChangeObserver = new SettingsChangeObserver(handler);
mShouldUseSplitNotificationShade =
@@ -1136,7 +1131,6 @@ public class NotificationPanelViewController extends PanelViewController
mKeyguardQsUserSwitchComponentFactory.build(userAvatarView);
mKeyguardQsUserSwitchController =
userSwitcherComponent.getKeyguardQsUserSwitchController();
mKeyguardQsUserSwitchController.setNotificationPanelViewController(this);
mKeyguardQsUserSwitchController.init();
mKeyguardStatusBarViewController.setKeyguardUserSwitcherEnabled(true);
} else if (keyguardUserSwitcherView != null) {
@@ -1848,18 +1842,6 @@ public class NotificationPanelViewController extends PanelViewController
}
}
public void expandWithQsDetail(DetailAdapter qsDetailAdapter) {
traceQsJank(true /* startTracing */, false /* wasCancelled */);
flingSettings(0 /* velocity */, FLING_EXPAND);
// When expanding with a panel, there's no meaningful touch point to correspond to. Set the
// origin to somewhere above the screen. This is used for animations.
int x = mQsFrame.getWidth() / 2;
mQSDetailDisplayer.showDetailAdapter(qsDetailAdapter, x, -getHeight());
if (mAccessibilityManager.isEnabled()) {
mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
}
}
public void expandWithoutQs() {
if (isQsExpanded()) {
flingSettings(0 /* velocity */, FLING_COLLAPSE);

View File

@@ -235,11 +235,6 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks {
// Settings are not available in setup
if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
QSPanelController qsPanelController = mStatusBar.getQSPanelController();
if (subPanel != null && qsPanelController != null) {
qsPanelController.openDetails(subPanel);
}
mNotificationPanelViewController.expandWithQs();
}

View File

@@ -37,12 +37,9 @@ import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.R;
import com.android.systemui.communal.CommunalStateController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
@@ -51,13 +48,11 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.UserAvatarView;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Manages the user switch on the Keyguard that is used for opening the QS user panel.
@@ -81,11 +76,8 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
protected final SysuiStatusBarStateController mStatusBarStateController;
private final ConfigurationController mConfigurationController;
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
private final KeyguardUserDetailAdapter mUserDetailAdapter;
private final FeatureFlags mFeatureFlags;
private final UserSwitchDialogController mUserSwitchDialogController;
private final UiEventLogger mUiEventLogger;
private NotificationPanelViewController mNotificationPanelViewController;
private UserAvatarView mUserAvatarView;
UserSwitcherController.UserRecord mCurrentUser;
@@ -133,9 +125,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
ConfigurationController configurationController,
SysuiStatusBarStateController statusBarStateController,
DozeParameters dozeParameters,
Provider<UserDetailView.Adapter> userDetailViewAdapterProvider,
ScreenOffAnimationController screenOffAnimationController,
FeatureFlags featureFlags,
UserSwitchDialogController userSwitchDialogController,
UiEventLogger uiEventLogger) {
super(view);
@@ -152,8 +142,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
keyguardStateController, dozeParameters,
screenOffAnimationController, /* animateYPos= */ false,
/* visibleOnCommunal= */ false);
mUserDetailAdapter = new KeyguardUserDetailAdapter(context, userDetailViewAdapterProvider);
mFeatureFlags = featureFlags;
mUserSwitchDialogController = userSwitchDialogController;
mUiEventLogger = uiEventLogger;
}
@@ -182,11 +170,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
mUiEventLogger.log(
LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP);
if (mFeatureFlags.isEnabled(Flags.NEW_USER_SWITCHER)) {
mUserSwitchDialogController.showDialog(mView);
} else {
openQsUserPanel();
}
mUserSwitchDialogController.showDialog(mView);
});
mUserAvatarView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@@ -331,40 +315,4 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
private boolean isListAnimating() {
return mKeyguardVisibilityHelper.isVisibilityAnimating();
}
private void openQsUserPanel() {
mNotificationPanelViewController.expandWithQsDetail(mUserDetailAdapter);
}
public void setNotificationPanelViewController(
NotificationPanelViewController notificationPanelViewController) {
mNotificationPanelViewController = notificationPanelViewController;
}
class KeyguardUserDetailAdapter extends UserSwitcherController.UserDetailAdapter {
KeyguardUserDetailAdapter(Context context,
Provider<UserDetailView.Adapter> userDetailViewAdapterProvider) {
super(context, userDetailViewAdapterProvider);
}
@Override
public boolean shouldAnimate() {
return false;
}
@Override
public int getDoneText() {
return R.string.quick_settings_close_user_panel;
}
@Override
public boolean onDoneButtonClicked() {
if (mNotificationPanelViewController != null) {
mNotificationPanelViewController.animateCloseQs(true /* animateAway */);
return true;
} else {
return false;
}
}
}
}

View File

@@ -51,7 +51,6 @@ import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManagerGlobal;
import android.widget.BaseAdapter;
@@ -60,7 +59,6 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.Dumpable;
@@ -77,9 +75,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -96,7 +92,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Keeps a list of all users on the device for user switching.
@@ -153,7 +148,6 @@ public class UserSwitcherController implements Dumpable {
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
private final UiEventLogger mUiEventLogger;
private final IActivityManager mActivityManager;
public final DetailAdapter mUserDetailAdapter;
private final Executor mBgExecutor;
private final boolean mGuestUserAutoCreated;
private final AtomicBoolean mGuestIsResetting;
@@ -177,7 +171,6 @@ public class UserSwitcherController implements Dumpable {
FalsingManager falsingManager,
TelephonyListenerManager telephonyListenerManager,
IActivityTaskManager activityTaskManager,
UserDetailAdapter userDetailAdapter,
SecureSettings secureSettings,
@Background Executor bgExecutor,
InteractionJankMonitor interactionJankMonitor,
@@ -196,7 +189,6 @@ public class UserSwitcherController implements Dumpable {
mLatencyTracker = latencyTracker;
mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(
this, mUserTracker, mUiEventLogger, secureSettings);
mUserDetailAdapter = userDetailAdapter;
mBgExecutor = bgExecutor;
if (!UserManager.isGuestUserEphemeral()) {
mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
@@ -1118,77 +1110,6 @@ public class UserSwitcherController implements Dumpable {
}
}
public static class UserDetailAdapter implements DetailAdapter {
private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
private final Context mContext;
private final Provider<UserDetailView.Adapter> mUserDetailViewAdapterProvider;
@Inject
UserDetailAdapter(Context context,
Provider<UserDetailView.Adapter> userDetailViewAdapterProvider) {
mContext = context;
mUserDetailViewAdapterProvider = userDetailViewAdapterProvider;
}
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_user_title);
}
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
UserDetailView v;
if (!(convertView instanceof UserDetailView)) {
v = UserDetailView.inflate(context, parent, false);
v.setAdapter(mUserDetailViewAdapterProvider.get());
} else {
v = (UserDetailView) convertView;
}
v.refreshAdapter();
return v;
}
@Override
public Intent getSettingsIntent() {
return USER_SETTINGS_INTENT;
}
@Override
public int getSettingsText() {
return R.string.quick_settings_more_user_settings;
}
@Override
public Boolean getToggleState() {
return null;
}
@Override
public void setToggleState(boolean state) {
}
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_USERDETAIL;
}
@Override
public UiEventLogger.UiEventEnum openDetailEvent() {
return QSUserSwitcherEvent.QS_USER_DETAIL_OPEN;
}
@Override
public UiEventLogger.UiEventEnum closeDetailEvent() {
return QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE;
}
@Override
public UiEventLogger.UiEventEnum moreSettingsEvent() {
return QSUserSwitcherEvent.QS_USER_MORE_SETTINGS;
}
};
private final KeyguardStateController.Callback mCallback =
new KeyguardStateController.Callback() {
@Override

View File

@@ -1,147 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.tuner;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
import com.android.systemui.volume.ZenModePanel.Callback;
public class TunerZenModePanel extends LinearLayout implements OnClickListener {
private static final String TAG = "TunerZenModePanel";
private Callback mCallback;
private ZenModePanel mZenModePanel;
private View mHeaderSwitch;
private int mZenMode;
private ZenModeController mController;
private View mButtons;
private View mMoreSettings;
private View mDone;
private OnClickListener mDoneListener;
private boolean mEditing;
public TunerZenModePanel(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public void init(ZenModeController zenModeController) {
mController = zenModeController;
mHeaderSwitch = findViewById(R.id.tuner_zen_switch);
mHeaderSwitch.setVisibility(View.VISIBLE);
mHeaderSwitch.setOnClickListener(this);
((TextView) mHeaderSwitch.findViewById(android.R.id.title)).setText(
R.string.quick_settings_dnd_label);
mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
mZenModePanel.init(zenModeController);
mButtons = findViewById(R.id.tuner_zen_buttons);
mMoreSettings = mButtons.findViewById(android.R.id.button2);
mMoreSettings.setOnClickListener(this);
((TextView) mMoreSettings).setText(R.string.quick_settings_more_settings);
mDone = mButtons.findViewById(android.R.id.button1);
mDone.setOnClickListener(this);
((TextView) mDone).setText(R.string.quick_settings_done);
// Hide the resizing space because it causes issues in the volume panel.
ViewGroup detail_header = findViewById(R.id.tuner_zen_switch);
detail_header.getChildAt(0).setVisibility(View.GONE);
// No background so it can blend with volume panel.
findViewById(R.id.edit_container).setBackground(null);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mEditing = false;
}
public void setCallback(Callback zenPanelCallback) {
mCallback = zenPanelCallback;
mZenModePanel.setCallback(zenPanelCallback);
}
@Override
public void onClick(View v) {
if (v == mHeaderSwitch) {
mEditing = true;
if (mZenMode == Global.ZEN_MODE_OFF) {
mZenMode = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN,
Global.ZEN_MODE_ALARMS);
mController.setZen(mZenMode, null, TAG);
postUpdatePanel();
} else {
mZenMode = Global.ZEN_MODE_OFF;
mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
postUpdatePanel();
}
} else if (v == mMoreSettings) {
Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
} else if (v == mDone) {
mEditing = false;
setVisibility(View.GONE);
mDoneListener.onClick(v);
}
}
public boolean isEditing() {
return mEditing;
}
public void setZenState(int zenMode) {
mZenMode = zenMode;
postUpdatePanel();
}
private void postUpdatePanel() {
// The complicated structure from reusing the same ZenPanel has resulted in some
// unstableness/flickering from callbacks coming in quickly. To solve this just
// post the UI updates a little bit.
removeCallbacks(mUpdate);
postDelayed(mUpdate, 40);
}
public void setDoneListener(OnClickListener onClickListener) {
mDoneListener = onClickListener;
}
private void updatePanel() {
boolean zenOn = mZenMode != Global.ZEN_MODE_OFF;
((Checkable) mHeaderSwitch.findViewById(android.R.id.toggle)).setChecked(zenOn);
mZenModePanel.setVisibility(zenOn ? View.VISIBLE : View.GONE);
mButtons.setVisibility(zenOn ? View.VISIBLE : View.GONE);
}
private final Runnable mUpdate = new Runnable() {
@Override
public void run() {
updatePanel();
}
};
}

View File

@@ -22,6 +22,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.VolumePolicy;
import android.os.Bundle;
import android.provider.Settings;
import android.view.WindowManager.LayoutParams;
import com.android.settingslib.applications.InterestingConfigChanges;
@@ -59,6 +60,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
private static final Intent ZEN_SETTINGS =
new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
private static final Intent ZEN_PRIORITY_SETTINGS =
new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
protected final Context mContext;
private final VolumeDialogControllerImpl mController;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
@@ -191,12 +197,12 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() {
@Override
public void onZenSettingsClicked() {
startSettings(ZenModePanel.ZEN_SETTINGS);
startSettings(ZEN_SETTINGS);
}
@Override
public void onZenPrioritySettingsClicked() {
startSettings(ZenModePanel.ZEN_PRIORITY_SETTINGS);
startSettings(ZEN_PRIORITY_SETTINGS);
}
};

View File

@@ -1,203 +0,0 @@
/*
* Copyright (C) 2017 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.qs;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_MORE_SETTINGS;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.ViewUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class QSDetailTest extends SysuiTestCase {
private MetricsLogger mMetricsLogger;
private QSDetail mQsDetail;
private QSPanelController mQsPanelController;
private QuickStatusBarHeader mQuickHeader;
private ActivityStarter mActivityStarter;
private DetailAdapter mMockDetailAdapter;
private TestableLooper mTestableLooper;
private UiEventLoggerFake mUiEventLogger;
private FrameLayout mParent;
@Before
public void setup() throws Exception {
mTestableLooper = TestableLooper.get(this);
mUiEventLogger = QSEvents.INSTANCE.setLoggerForTesting();
mParent = new FrameLayout(mContext);
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class);
LayoutInflater.from(mContext).inflate(R.layout.qs_detail, mParent);
mQsDetail = (QSDetail) mParent.getChildAt(0);
mQsPanelController = mock(QSPanelController.class);
mQuickHeader = mock(QuickStatusBarHeader.class);
mQsDetail.setQsPanel(mQsPanelController, mQuickHeader, mock(QSFooter.class),
mock(FalsingManager.class));
mQsDetail.mClipper = mock(QSDetailClipper.class);
mMockDetailAdapter = mock(DetailAdapter.class);
when(mMockDetailAdapter.createDetailView(any(), any(), any()))
.thenReturn(new View(mContext));
// Only detail in use is the user detail
when(mMockDetailAdapter.openDetailEvent())
.thenReturn(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN);
when(mMockDetailAdapter.closeDetailEvent())
.thenReturn(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE);
when(mMockDetailAdapter.moreSettingsEvent())
.thenReturn(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS);
ViewUtils.attachView(mParent);
}
@After
public void tearDown() {
QSEvents.INSTANCE.resetLogger();
mTestableLooper.processAllMessages();
ViewUtils.detachView(mParent);
}
@Test
public void testShowDetail_Metrics() {
mTestableLooper.processAllMessages();
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
verify(mMetricsLogger).visible(eq(mMockDetailAdapter.getMetricsCategory()));
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN.getId(), mUiEventLogger.eventId(0));
mUiEventLogger.getLogs().clear();
mQsDetail.handleShowingDetail(null, 0, 0, false);
verify(mMetricsLogger).hidden(eq(mMockDetailAdapter.getMetricsCategory()));
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE.getId(), mUiEventLogger.eventId(0));
}
@Test
public void testShowDetail_ShouldAnimate() {
mTestableLooper.processAllMessages();
when(mMockDetailAdapter.shouldAnimate()).thenReturn(true);
mQsDetail.setFullyExpanded(true);
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(),
eq(true) /* in */, any());
clearInvocations(mQsDetail.mClipper);
mQsDetail.handleShowingDetail(null, 0, 0, false);
verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(),
eq(false) /* in */, any());
}
@Test
public void testShowDetail_ShouldNotAnimate() {
mTestableLooper.processAllMessages();
when(mMockDetailAdapter.shouldAnimate()).thenReturn(false);
mQsDetail.setFullyExpanded(true);
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
verify(mQsDetail.mClipper).updateCircularClip(eq(false) /* animate */, anyInt(), anyInt(),
eq(true) /* in */, any());
clearInvocations(mQsDetail.mClipper);
// Detail adapters should always animate on close. shouldAnimate() should only affect the
// open transition
mQsDetail.handleShowingDetail(null, 0, 0, false);
verify(mQsDetail.mClipper).updateCircularClip(eq(true) /* animate */, anyInt(), anyInt(),
eq(false) /* in */, any());
}
@Test
public void testDoneButton_CloseDetailPanel() {
mTestableLooper.processAllMessages();
when(mMockDetailAdapter.onDoneButtonClicked()).thenReturn(false);
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
mQsDetail.requireViewById(android.R.id.button1).performClick();
verify(mQsPanelController).closeDetail();
}
@Test
public void testDoneButton_KeepDetailPanelOpen() {
mTestableLooper.processAllMessages();
when(mMockDetailAdapter.onDoneButtonClicked()).thenReturn(true);
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
mQsDetail.requireViewById(android.R.id.button1).performClick();
verify(mQsPanelController, never()).closeDetail();
}
@Test
public void testMoreSettingsButton() {
mTestableLooper.processAllMessages();
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
mUiEventLogger.getLogs().clear();
mQsDetail.requireViewById(android.R.id.button2).performClick();
int metricsCategory = mMockDetailAdapter.getMetricsCategory();
verify(mMetricsLogger).action(eq(ACTION_QS_MORE_SETTINGS), eq(metricsCategory));
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS.getId(), mUiEventLogger.eventId(0));
verify(mActivityStarter).postStartActivityDismissingKeyguard(any(), anyInt());
}
@Test
public void testNullAdapterClick() {
DetailAdapter mock = mock(DetailAdapter.class);
when(mock.moreSettingsEvent()).thenReturn(DetailAdapter.INVALID);
mQsDetail.setupDetailFooter(mock);
mQsDetail.requireViewById(android.R.id.button2).performClick();
}
}

View File

@@ -146,7 +146,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
mock(SecureSettings.class), mock(CustomTileStatePersister.class),
mTileServiceRequestControllerBuilder, mock(TileLifecycleManager.Factory.class));
qs.setHost(host);
qs.setListening(true);
processAllMessages();
@@ -186,7 +185,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mock(QSTileHost.class),
mock(StatusBarStateController.class),
commandQueue,
new QSDetailDisplayer(),
mQSMediaHost,
mQQSMediaHost,
mBypassController,

View File

@@ -1,151 +0,0 @@
/*
* 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.qs;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.brightness.BrightnessController;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.settings.brightness.ToggleSlider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.animation.DisappearParameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class QSPanelControllerTest extends SysuiTestCase {
@Mock
private QSPanel mQSPanel;
@Mock
private QSTileHost mQSTileHost;
@Mock
private QSCustomizerController mQSCustomizerController;
@Mock
private QSTileRevealController.Factory mQSTileRevealControllerFactory;
@Mock
private QSTileRevealController mQSTileRevealController;
@Mock
private MediaHost mMediaHost;
@Mock
private MetricsLogger mMetricsLogger;
private UiEventLogger mUiEventLogger = new UiEventLoggerFake();
private DumpManager mDumpManager = new DumpManager();
@Mock
private TunerService mTunerService;
@Mock
private QSFgsManagerFooter mQSFgsManagerFooter;
@Mock
private QSSecurityFooter mQSSecurityFooter;
@Mock
private QSLogger mQSLogger;
@Mock
private BrightnessController.Factory mBrightnessControllerFactory;
@Mock
private BrightnessController mBrightnessController;
@Mock
private BrightnessSliderController.Factory mToggleSliderViewControllerFactory;
@Mock
private BrightnessSliderController mBrightnessSliderController;
@Mock
QSTileImpl mQSTile;
@Mock
QSTileView mQSTileView;
@Mock
PagedTileLayout mPagedTileLayout;
@Mock
CommandQueue mCommandQueue;
FalsingManagerFake mFalsingManager = new FalsingManagerFake();
@Mock
Resources mResources;
@Mock
Configuration mConfiguration;
@Mock
FeatureFlags mFeatureFlags;
private QSPanelController mController;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
when(mQSPanel.isAttachedToWindow()).thenReturn(true);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
when(mQSPanel.getOrCreateTileLayout()).thenReturn(mPagedTileLayout);
when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
when(mQSPanel.getResources()).thenReturn(mResources);
when(mResources.getConfiguration()).thenReturn(mConfiguration);
when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mToggleSliderViewControllerFactory.create(any(), any()))
.thenReturn(mBrightnessSliderController);
when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
.thenReturn(mBrightnessController);
when(mQSTileRevealControllerFactory.create(any(), any()))
.thenReturn(mQSTileRevealController);
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
mController = new QSPanelController(mQSPanel, mQSFgsManagerFooter, mQSSecurityFooter,
mTunerService, mQSTileHost, mQSCustomizerController, true, mMediaHost,
mQSTileRevealControllerFactory, mDumpManager, mMetricsLogger, mUiEventLogger,
mQSLogger, mBrightnessControllerFactory, mToggleSliderViewControllerFactory,
mFalsingManager, mCommandQueue, mFeatureFlags
);
mController.init();
}
@Test
public void testOpenDetailsWithNonExistingTile_NoException() {
mController.openDetails("none");
verify(mQSPanel, never()).openDetails(any());
}
}

View File

@@ -36,10 +36,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
@@ -63,9 +60,6 @@ class QSPanelTest : SysuiTestCase() {
private lateinit var mQSLogger: QSLogger
private lateinit var mParentView: ViewGroup
@Mock
private lateinit var mCallback: QSDetail.Callback
@Mock
private lateinit var mQSTileView: QSTileView
@@ -97,28 +91,9 @@ class QSPanelTest : SysuiTestCase() {
whenever(mHost.tiles).thenReturn(emptyList())
whenever(mHost.createTileView(any(), any(), anyBoolean())).thenReturn(mQSTileView)
mQsPanel.addTile(mDndTileRecord)
mQsPanel.setCallback(mCallback)
}
}
@Test
fun testOpenDetailsWithExistingTile_NoException() {
mTestableLooper.runWithLooper {
mQsPanel.openDetails(dndTile)
}
verify(mCallback).onShowingDetail(any(), anyInt(), anyInt())
}
@Test
fun testOpenDetailsWithNullParameter_NoException() {
mTestableLooper.runWithLooper {
mQsPanel.openDetails(null)
}
verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt())
}
@Test
fun testSecurityFooter_appearsOnBottomOnSplitShade() {
mQsPanel.onConfigurationChanged(getNewOrientationConfig(ORIENTATION_LANDSCAPE))

View File

@@ -53,7 +53,6 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.InstanceId;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSTileHost;
@@ -420,11 +419,5 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Override
public void destroy() {}
@Override
public DetailAdapter getDetailAdapter() {
return null;
}
}
}

View File

@@ -48,7 +48,6 @@ import com.android.systemui.qs.tiles.ReduceBrightColorsTile
import com.android.systemui.qs.tiles.RotationLockTile
import com.android.systemui.qs.tiles.ScreenRecordTile
import com.android.systemui.qs.tiles.UiModeNightTile
import com.android.systemui.qs.tiles.UserTile
import com.android.systemui.qs.tiles.WifiTile
import com.android.systemui.qs.tiles.WorkModeTile
import com.android.systemui.util.leak.GarbageMonitor
@@ -76,7 +75,6 @@ private val specMap = mapOf(
"location" to LocationTile::class.java,
"cast" to CastTile::class.java,
"hotspot" to HotspotTile::class.java,
"user" to UserTile::class.java,
"battery" to BatterySaverTile::class.java,
"saver" to DataSaverTile::class.java,
"night" to NightDisplayTile::class.java,
@@ -115,7 +113,6 @@ class QSFactoryImplTest : SysuiTestCase() {
@Mock private lateinit var locationTile: LocationTile
@Mock private lateinit var castTile: CastTile
@Mock private lateinit var hotspotTile: HotspotTile
@Mock private lateinit var userTile: UserTile
@Mock private lateinit var batterySaverTile: BatterySaverTile
@Mock private lateinit var dataSaverTile: DataSaverTile
@Mock private lateinit var nightDisplayTile: NightDisplayTile
@@ -159,7 +156,6 @@ class QSFactoryImplTest : SysuiTestCase() {
{ locationTile },
{ castTile },
{ hotspotTile },
{ userTile },
{ batterySaverTile },
{ dataSaverTile },
{ nightDisplayTile },

View File

@@ -22,11 +22,13 @@ import android.provider.Settings
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.animation.DialogLaunchAnimator
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.PseudoGridView
import com.android.systemui.qs.QSUserSwitcherEvent
import com.android.systemui.qs.tiles.UserDetailView
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.util.mockito.any
@@ -62,6 +64,8 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
private lateinit var launchView: View
@Mock
private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
@Mock
private lateinit var uiEventLogger: UiEventLogger
@Captor
private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener>
@@ -79,6 +83,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
activityStarter,
falsingManager,
dialogLaunchAnimator,
uiEventLogger,
{ dialog }
)
}
@@ -87,6 +92,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
fun showDialog_callsDialogShow() {
controller.showDialog(launchView)
verify(dialogLaunchAnimator).showFromView(dialog, launchView)
verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN)
}
@Test
@@ -108,10 +114,14 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
}
@Test
fun doneButtonSetWithNullHandler() {
fun doneButtonLogsCorrectly() {
controller.showDialog(launchView)
verify(dialog).setPositiveButton(anyInt(), eq(null))
verify(dialog).setPositiveButton(anyInt(), capture(clickCaptor))
clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE)
}
@Test
@@ -129,6 +139,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() {
argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)),
eq(0)
)
verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS)
}
@Test

View File

@@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.annotations.Requires;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QS.HeightListener;
import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
@@ -99,7 +98,6 @@ public class VersionInfoTest extends SysuiTestCase {
@Requires(target = QS.class, version = QS.VERSION)
@Requires(target = HeightListener.class, version = HeightListener.VERSION)
@Requires(target = DetailAdapter.class, version = DetailAdapter.VERSION)
public static class QSImpl {
}
}

View File

@@ -110,7 +110,6 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController;
import com.android.systemui.qs.QSDetailDisplayer;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -273,8 +272,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
@Mock
private IdleHostViewController mIdleHostViewController;
@Mock
private QSDetailDisplayer mQSDetailDisplayer;
@Mock
private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
@Mock
private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
@@ -528,7 +525,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mCommunalViewComponentFactory,
mIdleViewComponentFactory,
mLockscreenShadeTransitionController,
mQSDetailDisplayer,
mGroupManager,
mNotificationAreaController,
mAuthController,

View File

@@ -27,26 +27,22 @@ import com.android.internal.logging.UiEventLogger
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.CommunalStateController
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.tiles.UserDetailView
import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.LockscreenGestureLogger
import com.android.systemui.statusbar.phone.NotificationPanelViewController
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import javax.inject.Provider
@SmallTest
@TestableLooper.RunWithLooper
@@ -76,24 +72,15 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
@Mock
private lateinit var dozeParameters: DozeParameters
@Mock
private lateinit var userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>
@Mock
private lateinit var screenOffAnimationController: ScreenOffAnimationController
@Mock
private lateinit var featureFlags: FeatureFlags
@Mock
private lateinit var userSwitchDialogController: UserSwitchDialogController
@Mock
private lateinit var uiEventLogger: UiEventLogger
@Mock
private lateinit var notificationPanelViewController: NotificationPanelViewController
private lateinit var view: FrameLayout
private lateinit var testableLooper: TestableLooper
private lateinit var keyguardQsUserSwitchController: KeyguardQsUserSwitchController
@@ -118,16 +105,12 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
configurationController,
statusBarStateController,
dozeParameters,
userDetailViewAdapterProvider,
screenOffAnimationController,
featureFlags,
userSwitchDialogController,
uiEventLogger)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
keyguardQsUserSwitchController
.setNotificationPanelViewController(notificationPanelViewController)
`when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController)
`when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true)
keyguardQsUserSwitchController.init()

View File

@@ -54,8 +54,8 @@ import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.time.FakeSystemClock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
@@ -86,7 +86,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
@Mock private lateinit var activityTaskManager: IActivityTaskManager
@Mock private lateinit var userDetailAdapter: UserSwitcherController.UserDetailAdapter
@Mock private lateinit var telephonyListenerManager: TelephonyListenerManager
@Mock private lateinit var secureSettings: SecureSettings
@Mock private lateinit var falsingManager: FalsingManager
@@ -161,7 +160,6 @@ class UserSwitcherControllerTest : SysuiTestCase() {
falsingManager,
telephonyListenerManager,
activityTaskManager,
userDetailAdapter,
secureSettings,
uiBgExecutor,
interactionJankMonitor,