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:
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user