Updated QS UI
- Adds footer to QS which contains the date/alarm info
and all touch targets (settings, edit, etc.)
- Swaps out emergency + carrier text on cell tile for a
standard CarrierText from lock screen in the header
to make the header only contain status info.
- Add dividing line
- Work on animations
Test: runtest systemui
Change-Id: I97dfea1b1ea7006b53eb61ac3a1f942c64dd282d
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java
new file mode 100644
index 0000000..f6f8f53
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.view.View;
+import android.view.ViewGroup;
+
+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);
+ Intent getSettingsIntent();
+ 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;
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index b7467eb..4a5a681 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -14,58 +14,53 @@
package com.android.systemui.plugins.qs;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
import com.android.systemui.plugins.FragmentBase;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.plugins.qs.QS.HeightListener;
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RelativeLayout;
-
/**
* Fragment that contains QS in the notification shade. Most of the interface is for
* handling the expand/collapsing of the view interaction.
*/
@ProvidesInterface(action = QS.ACTION, version = QS.VERSION)
@DependsOn(target = HeightListener.class)
-@DependsOn(target = Callback.class)
-@DependsOn(target = DetailAdapter.class)
public interface QS extends FragmentBase {
public static final String ACTION = "com.android.systemui.action.PLUGIN_QS";
- public static final int VERSION = 5;
+ public static final int VERSION = 6;
String TAG = "QS";
- public abstract void setPanelView(HeightListener notificationPanelView);
- public abstract BaseStatusBarHeader getHeader();
+ void setPanelView(HeightListener notificationPanelView);
- public abstract void hideImmediately();
- public abstract int getQsMinExpansionHeight();
- public abstract int getDesiredHeight();
- public abstract void setHeightOverride(int desiredHeight);
- public abstract void setHeaderClickable(boolean qsExpansionEnabled);
- public abstract boolean isCustomizing();
- public abstract void setOverscrolling(boolean overscrolling);
- public abstract void setExpanded(boolean qsExpanded);
- public abstract void setListening(boolean listening);
- public abstract boolean isShowingDetail();
- public abstract void closeDetail();
- public abstract void setKeyguardShowing(boolean keyguardShowing);
- public abstract void animateHeaderSlidingIn(long delay);
- public abstract void animateHeaderSlidingOut();
- public abstract void setQsExpansion(float qsExpansionFraction, float headerTranslation);
- public abstract void setHeaderListening(boolean listening);
- public abstract void notifyCustomizeChanged();
+ void hideImmediately();
+ int getQsMinExpansionHeight();
+ int getDesiredHeight();
+ void setHeightOverride(int desiredHeight);
+ void setHeaderClickable(boolean qsExpansionEnabled);
+ boolean isCustomizing();
+ void setOverscrolling(boolean overscrolling);
+ void setExpanded(boolean qsExpanded);
+ void setListening(boolean listening);
+ boolean isShowingDetail();
+ void closeDetail();
+ void setKeyguardShowing(boolean keyguardShowing);
+ void animateHeaderSlidingIn(long delay);
+ void animateHeaderSlidingOut();
+ void setQsExpansion(float qsExpansionFraction, float headerTranslation);
+ void setHeaderListening(boolean listening);
+ void notifyCustomizeChanged();
- public abstract void setContainer(ViewGroup container);
+ void setContainer(ViewGroup container);
+ void setExpandClickListener(OnClickListener onClickListener);
+
+ View getHeader();
@ProvidesInterface(version = HeightListener.VERSION)
public interface HeightListener {
@@ -73,51 +68,4 @@
void onQsHeightChanged();
}
- @ProvidesInterface(version = Callback.VERSION)
- public interface Callback {
- public static final int VERSION = 1;
- void onShowingDetail(DetailAdapter detail, int x, int y);
- void onToggleStateChanged(boolean state);
- void onScanStateChanged(boolean state);
- }
-
- @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);
- Intent getSettingsIntent();
- 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; }
- }
-
- @ProvidesInterface(version = BaseStatusBarHeader.VERSION)
- public abstract static class BaseStatusBarHeader extends RelativeLayout {
- public static final int VERSION = 1;
-
- public BaseStatusBarHeader(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public abstract int getCollapsedHeight();
- public abstract int getExpandedHeight();
-
- public abstract void setExpanded(boolean b);
- public abstract void setExpansion(float headerExpansionFraction);
- public abstract void setListening(boolean listening);
- public abstract void updateEverything();
- public abstract void setCallback(Callback qsPanelCallback);
- public abstract View getExpandView();
- }
-
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 887dafc..7bb31c0 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -20,7 +20,6 @@
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.Callback;
import com.android.systemui.plugins.qs.QSTile.Icon;
import com.android.systemui.plugins.qs.QSTile.State;
diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
similarity index 96%
rename from packages/SystemUI/res/drawable/ic_settings_20dp.xml
rename to packages/SystemUI/res/drawable/ic_settings_16dp.xml
index 3170f86..c21b60c 100644
--- a/packages/SystemUI/res/drawable/ic_settings_20dp.xml
+++ b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="20dp"
- android:height="20dp"
+ android:width="16dp"
+ android:height="16dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_sim.xml b/packages/SystemUI/res/drawable/ic_sim.xml
new file mode 100644
index 0000000..983c1d0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sim.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M0 0h24v24H0z"
+ android:fillColor="#00000000"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18.0,2.0l-8.0,0.0L4.02,8.0 4.0,20.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
deleted file mode 100644
index 46c761a..0000000
--- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
+++ /dev/null
@@ -1,75 +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"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/date_time_alarm_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginStart="16dp"
- android:gravity="start"
- android:orientation="vertical">
- <LinearLayout
- android:id="@+id/date_time_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:focusable="true" >
-
- <include layout="@layout/split_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:id="@+id/clock" />
-
- <com.android.systemui.statusbar.policy.DateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="6dp"
- android:drawableStart="@drawable/header_dot"
- android:drawablePadding="6dp"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
- android:textSize="@dimen/qs_time_collapsed_size"
- android:gravity="top"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/alarm_status_collapsed"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:src="@drawable/ic_access_alarms_small"
- android:paddingStart="6dp"
- android:gravity="center"
- android:visibility="gone" />
- </LinearLayout>
-
- <com.android.systemui.statusbar.AlphaOptimizedButton
- android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="20dp"
- android:paddingTop="3dp"
- android:drawablePadding="8dp"
- android:drawableStart="@drawable/ic_access_alarms_small"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:gravity="top"
- android:background="?android:attr/selectableItemBackground"
- android:visibility="gone" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_divider.xml b/packages/SystemUI/res/layout/qs_divider.xml
new file mode 100644
index 0000000..660e4af
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_divider.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:background="?android:attr/colorForeground" />
diff --git a/packages/SystemUI/res/layout/qs_footer.xml b/packages/SystemUI/res/layout/qs_footer.xml
new file mode 100644
index 0000000..82e1ae7
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_footer.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2012, 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 RelativeLayout -->
+<com.android.systemui.qs.QSFooter
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/header"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:baselineAligned="false"
+ android:clickable="false"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:paddingTop="0dp"
+ android:paddingEnd="8dp"
+ android:paddingStart="16dp"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+ <include
+ android:id="@+id/date_time_alarm_group"
+ layout="@layout/status_bar_alarm_group"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+ <com.android.systemui.statusbar.phone.MultiUserSwitch
+ android:id="@+id/multi_user_switch"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/ripple_drawable"
+ android:focusable="true">
+
+ <ImageView
+ android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_expanded_size"
+ android:layout_height="@dimen/multi_user_avatar_expanded_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"/>
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@android:id/edit"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:contentDescription="@string/accessibility_quick_settings_edit"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_mode_edit"
+ android:tint="?android:attr/colorForeground"/>
+
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/settings_button_container"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:src="@drawable/ic_settings_16dp"
+ android:tint="?android:attr/colorForeground"/>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="36dp"
+ android:paddingEnd="4dp"
+ android:src="@drawable/tuner"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="invisible"/>
+
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+ <com.android.systemui.statusbar.phone.ExpandableIndicator
+ android:id="@+id/expand_indicator"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:clipToPadding="false"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_quick_settings_expand"
+ android:padding="14dp" />
+
+</com.android.systemui.qs.QSFooter>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 895185b..3658313 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -26,12 +26,16 @@
<com.android.systemui.qs.QSPanel
android:id="@+id/quick_settings_panel"
android:background="#0000"
- android:layout_marginTop="52dp"
+ android:layout_marginTop="28dp"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="48dp" />
<include layout="@layout/quick_status_bar_expanded_header" />
+ <include android:id="@+id/qs_footer"
+ layout="@layout/qs_footer" />
+
<include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
<include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 78d4bdd..520dab4 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -16,8 +16,9 @@
-->
<!-- Extends RelativeLayout -->
-<com.android.systemui.statusbar.phone.QuickStatusBarHeader
+<com.android.systemui.qs.QuickStatusBarHeader
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_header_height"
@@ -26,147 +27,71 @@
android:clickable="false"
android:clipChildren="false"
android:clipToPadding="false"
+ android:paddingBottom="48dp"
android:paddingTop="0dp"
android:paddingEnd="0dp"
android:paddingStart="0dp">
<LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_width="match_parent"
+ android:layout_height="24dp"
android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
- android:paddingEnd="4dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
android:orientation="horizontal">
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@+id/multi_user_switch"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_alignParentEnd="true"
- android:background="@drawable/ripple_drawable"
- android:focusable="true">
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside"/>
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
+ <com.android.keyguard.CarrierText
+ android:id="@+id/qs_carrier_text"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_vertical|start"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true" />
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@android:id/edit"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:clickable="true"
- android:clipToPadding="false"
- android:contentDescription="@string/accessibility_quick_settings_edit"
- android:focusable="true"
- android:padding="14dp"
- android:src="@drawable/ic_mode_edit"
- android:tint="?android:attr/colorForeground"/>
-
- <LinearLayout
- android:id="@+id/system_icons_super_container"
+ <FrameLayout
+ android:id="@+id/system_icons_container"
android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_alignWithParentIfMissing="true"
- android:layout_toStartOf="@id/multi_user_switch"
- android:background="@drawable/ripple_drawable">
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical">
- <FrameLayout
- android:id="@+id/system_icons_container"
- android:layout_width="wrap_content"
- android:layout_height="24dp"
- android:layout_gravity="center_vertical">
+ <include layout="@layout/system_icons" />
- <include layout="@layout/system_icons" />
- </FrameLayout>
- </LinearLayout>
+ </FrameLayout>
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/ripple_drawable"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:src="@drawable/ic_settings_20dp"
- android:tint="?android:attr/colorForeground"/>
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/tuner_icon"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="36dp"
- android:src="@drawable/tuner"
- android:tint="?android:attr/textColorTertiary"
- android:visibility="invisible"/>
-
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
- <com.android.systemui.statusbar.phone.ExpandableIndicator
- android:id="@+id/expand_indicator"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:clipToPadding="false"
- android:clickable="true"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:contentDescription="@string/accessibility_quick_settings_expand"
- android:padding="12dp" />
-
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:singleLine="true"
+ android:paddingStart="@dimen/status_bar_clock_starting_padding"
+ android:paddingEnd="@dimen/status_bar_clock_end_padding"
+ android:gravity="center_vertical|start"
+ systemui:showDark="false"
+ />
</LinearLayout>
- <TextView
- android:id="@+id/header_emergency_calls_only"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:focusable="true"
- android:gravity="center_vertical"
- android:paddingStart="16dp"
- android:paddingTop="6dp"
- android:singleLine="true"
- android:text="@*android:string/emergency_calls_only"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
- android:visibility="gone"/>
-
- <include
- android:id="@+id/date_time_alarm_group"
- layout="@layout/status_bar_alarm_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginTop="12dp"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true" />
-
<com.android.systemui.qs.QuickQSPanel
android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
- android:layout_marginTop="54dp"
- android:layout_marginBottom="24dp"
+ android:layout_marginTop="36dp"
+ android:layout_marginBottom="8dp"
android:layout_alignParentTop="true"
android:accessibilityTraversalAfter="@+id/date_time_group"
android:accessibilityTraversalBefore="@id/expand_indicator"
android:clipChildren="false"
android:clipToPadding="false"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
android:focusable="true"
android:importantForAccessibility="yes"
android:paddingTop="0dp"/>
@@ -192,4 +117,4 @@
android:textStyle="bold"
android:visibility="invisible"/>
-</com.android.systemui.statusbar.phone.QuickStatusBarHeader>
+</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index 745320e..7a5b6dc 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -18,57 +18,42 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/date_time_alarm_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginStart="16dp"
- android:gravity="start"
- android:orientation="vertical">
- <LinearLayout
- android:id="@+id/date_time_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:focusable="true" >
-
- <include layout="@layout/split_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:id="@+id/clock" />
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/alarm_status_collapsed"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:src="@drawable/ic_access_alarms_small"
- android:tint="?android:attr/textColorPrimary"
- android:paddingStart="6dp"
- android:gravity="center"
- android:visibility="gone" />
- </LinearLayout>
+ android:layout_width="0dp"
+ android:layout_height="48dp"
+ android:layout_weight="1"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:background="?android:attr/selectableItemBackground">
<com.android.systemui.statusbar.policy.DateView
android:id="@+id/date"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:singleLine="true"
- android:layout_marginTop="-4dp"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
android:textSize="@dimen/qs_time_collapsed_size"
- android:gravity="top"
+ android:gravity="center_vertical"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/alarm_status_collapsed"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_access_alarms_small"
+ android:tint="?android:attr/textColorPrimary"
+ android:paddingStart="6dp"
+ android:paddingEnd="6dp"
+ android:gravity="center"
+ android:visibility="gone" />
+
<com.android.systemui.statusbar.AlphaOptimizedButton
android:id="@+id/alarm_status"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="20dp"
- android:paddingTop="3dp"
- android:drawablePadding="8dp"
- android:drawableStart="@drawable/ic_access_alarms_small"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:gravity="top"
- android:background="?android:attr/selectableItemBackground"
+ android:layout_height="match_parent"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+ android:gravity="center_vertical"
+ android:background="@null"
+ android:clickable="false"
android:visibility="gone" />
</LinearLayout>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 7632f87..f405943 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -50,6 +50,7 @@
<enum name="small" value="1" />
<enum name="gone" value="2" />
</attr>
+ <attr name="showDark" format="boolean" />
</declare-styleable>
<attr name="orientation">
<enum name="horizontal" value="0" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f42344e..3512761 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -179,10 +179,10 @@
<dimen name="close_handle_underlap">32dp</dimen>
<!-- Height of the status bar header bar -->
- <dimen name="status_bar_header_height">126dp</dimen>
+ <dimen name="status_bar_header_height">124dp</dimen>
<!-- Height of the status bar header bar when expanded -->
- <dimen name="status_bar_header_height_expanded">116dp</dimen>
+ <dimen name="status_bar_header_height_expanded">124dp</dimen>
<!-- Height of the status bar header bar when on Keyguard -->
<dimen name="status_bar_header_height_keyguard">40dp</dimen>
@@ -238,7 +238,7 @@
<dimen name="qs_tile_padding_below_icon">12dp</dimen>
<dimen name="qs_tile_padding_bottom">16dp</dimen>
<dimen name="qs_tile_spacing">4dp</dimen>
- <dimen name="qs_panel_padding_bottom">8dp</dimen>
+ <dimen name="qs_panel_padding_bottom">0dp</dimen>
<dimen name="qs_detail_header_height">56dp</dimen>
<dimen name="qs_detail_header_padding">0dp</dimen>
<dimen name="qs_detail_header_bottom_padding">0dp</dimen>
@@ -428,7 +428,7 @@
<dimen name="multi_user_avatar_keyguard_size">22dp</dimen>
<!-- The width of user avatar when expanded -->
- <dimen name="multi_user_avatar_expanded_size">24dp</dimen>
+ <dimen name="multi_user_avatar_expanded_size">16dp</dimen>
<!-- The font size of the time when collapsed in QS -->
<dimen name="qs_time_collapsed_size">14sp</dimen>
@@ -731,4 +731,7 @@
<!-- The size of the PIP drag-to-dismiss target. -->
<dimen name="pip_dismiss_target_size">48dp</dimen>
+ <dimen name="default_gear_space">18dp</dimen>
+ <dimen name="cell_overlay_padding">18dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 815c41f..62e11f7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1819,4 +1819,7 @@
<!-- Action label for launching app info on the specified app [CHAR LIMIT=20] -->
<string name="app_info">App info</string>
+ <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
+ <string name="mobile_data">Mobile data</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 411fd3d..af7e9b4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -35,7 +35,7 @@
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
index 58670da..79f78c9 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -358,7 +358,7 @@
+ ", expected " + mVersion);
return null;
}
- } catch (Exception e) {
+ } catch (Throwable e) {
Log.w(TAG, "Couldn't load plugin: " + pkg, e);
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
new file mode 100644
index 0000000..7fe28c3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -0,0 +1,53 @@
+/*
+ * 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 android.content.Context;
+import android.content.res.ColorStateList;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.ImageView;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon;
+
+// Exists to provide easy way to add sim icon to cell tile
+// TODO Find a better way to handle this and remove it.
+public class CellTileView extends SignalTileView {
+
+ private final ImageView mOverlay;
+
+ public CellTileView(Context context) {
+ super(context);
+ mOverlay = new ImageView(mContext);
+ mOverlay.setImageTintList(ColorStateList.valueOf(Utils.getColorAttr(context,
+ android.R.attr.colorPrimary)));
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT);
+ int padding = context.getResources().getDimensionPixelOffset(R.dimen.cell_overlay_padding);
+ params.leftMargin = params.rightMargin = padding;
+ mIconFrame.addView(mOverlay, params);
+ }
+
+ @Override
+ public void setIcon(State state) {
+ State s = state.copy();
+ updateIcon(mOverlay, state);
+ s.icon = ResourceIcon.get(R.drawable.ic_sim);
+ super.setIcon(s);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 5d3effc..3337090 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -27,7 +27,6 @@
import com.android.systemui.qs.QSHost.Callback;
import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.qs.TouchAnimator.Listener;
-import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -162,7 +161,9 @@
QSTileLayout tileLayout = mQsPanel.getTileLayout();
mAllViews.add((View) tileLayout);
- firstPageBuilder.addFloat(tileLayout, "translationY", mQsPanel.getHeight(), 0);
+ int heightDiff = mQsPanel.getBottom() - mQs.getHeader().getBottom()
+ + mQs.getHeader().getPaddingBottom();
+ firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
for (QSTile tile : tiles) {
QSTileView tileView = mQsPanel.getTileView(tile);
@@ -208,7 +209,7 @@
final int xDiff = loc2[0] - loc1[0];
final int yDiff = loc2[1] - loc1[1];
- firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+ firstPageBuilder.addFloat(tileView, "translationY", heightDiff, 0);
translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
translationYBuilder.addFloat(tileIcon, "translationY", -yDiff, 0);
@@ -216,7 +217,7 @@
mAllViews.add(tileIcon);
} else {
firstPageBuilder.addFloat(tileView, "alpha", 0, 1);
- firstPageBuilder.addFloat(tileView, "translationY", -mQsPanel.getHeight(), 0);
+ firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
}
mAllViews.add(tileView);
count++;
@@ -225,12 +226,15 @@
// Make brightness appear static position and alpha in through second half.
View brightness = mQsPanel.getBrightnessView();
if (brightness != null) {
- firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0);
+ firstPageBuilder.addFloat(brightness, "translationY", heightDiff, 0);
mBrightnessAnimator = new TouchAnimator.Builder()
.addFloat(brightness, "alpha", 0, 1)
.addFloat(mQsPanel.getPageIndicator(), "alpha", 0, 1)
+ .addFloat(mQsPanel.getDivider(), "alpha", 0, 1)
.setStartDelay(.5f)
.build();
+ mAllViews.add(mQsPanel.getPageIndicator());
+ mAllViews.add(mQsPanel.getDivider());
mAllViews.add(brightness);
} else {
mBrightnessAnimator = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 91b4d0d..06264ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -38,6 +38,7 @@
protected View mHeader;
protected float mQsExpansion;
private QSCustomizer mQSCustomizer;
+ private QSFooter mQSFooter;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -49,7 +50,8 @@
mQSPanel = findViewById(R.id.quick_settings_panel);
mQSDetail = findViewById(R.id.qs_detail);
mHeader = findViewById(R.id.header);
- mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
+ mQSCustomizer = findViewById(R.id.qs_customize);
+ mQSFooter = findViewById(R.id.qs_footer);
}
@Override
@@ -60,7 +62,8 @@
mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
int width = mQSPanel.getMeasuredWidth();
- int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+ LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+ int height = layoutParams.topMargin + layoutParams.bottomMargin
+ mQSPanel.getMeasuredHeight();
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
@@ -93,6 +96,8 @@
int height = calculateContainerHeight();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + height);
+ // Pin QS Footer to the bottom of the panel.
+ mQSFooter.setTranslationY(height - mQSFooter.getHeight());
}
protected int calculateContainerHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 7df124a..1709718 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -38,11 +38,8 @@
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.QSTileHost;
public class QSDetail extends LinearLayout {
@@ -68,7 +65,7 @@
private boolean mScanState;
private boolean mClosingDetail;
private boolean mFullyExpanded;
- private BaseStatusBarHeader mHeader;
+ private QuickStatusBarHeader mHeader;
private boolean mTriggeredExpand;
private int mOpenX;
private int mOpenY;
@@ -117,7 +114,7 @@
mDetailDoneButton.setOnClickListener(doneListener);
}
- public void setQsPanel(QSPanel panel, BaseStatusBarHeader header) {
+ public void setQsPanel(QSPanel panel, QuickStatusBarHeader header) {
mQsPanel = panel;
mHeader = header;
mHeader.setCallback(mQsPanelCallback);
@@ -154,7 +151,11 @@
return mClosingDetail;
}
-
+ public interface Callback {
+ void onShowingDetail(DetailAdapter detail, int x, int y);
+ void onToggleStateChanged(boolean state);
+ void onScanStateChanged(boolean state);
+ }
public void handleShowingDetail(final DetailAdapter adapter, int x, int y,
boolean toggleQs) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index d6c2447..2202b58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -11,372 +11,381 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
*/
+
package com.android.systemui.qs;
-import android.app.AlertDialog;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.SpannableStringBuilder;
-import android.text.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
-import android.util.Log;
-import android.view.LayoutInflater;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
+import android.os.UserManager;
+import android.provider.AlarmClock;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.R.dimen;
+import com.android.systemui.R.id;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.phone.MultiUserSwitch;
+import com.android.systemui.statusbar.phone.SettingsButton;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import com.android.systemui.tuner.TunerService;
-import static android.provider.Settings.ACTION_VPN_SETTINGS;
+public class QSFooter extends LinearLayout implements
+ NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
+ SignalCallback {
+ private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
-public class QSFooter implements OnClickListener, DialogInterface.OnClickListener {
- protected static final String TAG = "QSFooter";
- protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private ActivityStarter mActivityStarter;
+ private NextAlarmController mNextAlarmController;
+ private UserInfoController mUserInfoController;
+ private SettingsButton mSettingsButton;
+ protected View mSettingsContainer;
- private final View mRootView;
- private final TextView mFooterText;
- private final ImageView mFooterIcon;
- private final ImageView mFooterIcon2;
- private final Context mContext;
- private final Callback mCallback = new Callback();
- private final SecurityController mSecurityController;
- private final ActivityStarter mActivityStarter;
- private final Handler mMainHandler;
+ private TextView mAlarmStatus;
+ private View mAlarmStatusCollapsed;
+ private View mDate;
- private AlertDialog mDialog;
- private QSTileHost mHost;
- protected H mHandler;
+ private QSPanel mQsPanel;
- private boolean mIsVisible;
- private boolean mIsIconVisible;
- private boolean mIsIcon2Visible;
- private CharSequence mFooterTextContent = null;
- private int mFooterTextId;
- private int mFooterIconId;
- private int mFooterIcon2Id;
+ private boolean mExpanded;
+ private boolean mAlarmShowing;
- public QSFooter(QSPanel qsPanel, Context context) {
- mRootView = LayoutInflater.from(context)
- .inflate(R.layout.quick_settings_footer, qsPanel, false);
- mRootView.setOnClickListener(this);
- mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
- mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
- mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
- mFooterIconId = R.drawable.ic_qs_vpn;
- mFooterIcon2Id = R.drawable.ic_qs_network_logging;
- mContext = context;
- mMainHandler = new Handler(Looper.getMainLooper());
+ protected ExpandableIndicator mExpandIndicator;
+
+ private boolean mListening;
+ private AlarmManager.AlarmClockInfo mNextAlarm;
+
+ private boolean mShowEmergencyCallsOnly;
+ protected MultiUserSwitch mMultiUserSwitch;
+ private ImageView mMultiUserAvatar;
+ private boolean mAlwaysShowMultiUserSwitch;
+
+ protected TouchAnimator mSettingsAlpha;
+ private float mExpansionAmount;
+
+ protected View mEdit;
+ private boolean mShowEditIcon;
+ private TouchAnimator mAnimator;
+ private View mDateTimeGroup;
+
+ public QSFooter(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ Resources res = getResources();
+
+ mShowEditIcon = res.getBoolean(R.bool.config_showQuickSettingsEditingIcon);
+
+ mEdit = findViewById(android.R.id.edit);
+ mEdit.setVisibility(mShowEditIcon ? VISIBLE : GONE);
+
+ if (mShowEditIcon) {
+ findViewById(android.R.id.edit).setOnClickListener(view ->
+ Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
+ mQsPanel.showEdit(view)));
+ }
+
+ mDateTimeGroup = findViewById(id.date_time_alarm_group);
+ mDate = findViewById(R.id.date);
+
+ mExpandIndicator = findViewById(R.id.expand_indicator);
+ mExpandIndicator.setVisibility(
+ res.getBoolean(R.bool.config_showQuickSettingsExpandIndicator)
+ ? VISIBLE : GONE);
+
+ mSettingsButton = findViewById(R.id.settings_button);
+ mSettingsContainer = findViewById(R.id.settings_button_container);
+ mSettingsButton.setOnClickListener(this);
+
+ mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
+ mAlarmStatus = findViewById(R.id.alarm_status);
+ mDateTimeGroup.setOnClickListener(this);
+
+ mMultiUserSwitch = findViewById(R.id.multi_user_switch);
+ mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+ mAlwaysShowMultiUserSwitch = res.getBoolean(R.bool.config_alwaysShowMultiUserSwitcher);
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
+
+ updateResources();
+
+ mNextAlarmController = Dependency.get(NextAlarmController.class);
+ mUserInfoController = Dependency.get(UserInfoController.class);
mActivityStarter = Dependency.get(ActivityStarter.class);
- mSecurityController = Dependency.get(SecurityController.class);
- mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+ addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
+ oldBottom) -> updateAnimator(right - left));
}
- public void setHostEnvironment(QSTileHost host) {
- mHost = host;
+ private void updateAnimator(int width) {
+ int numTiles = QuickQSPanel.getNumQuickTiles(mContext);
+ int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+ - mContext.getResources().getDimensionPixelSize(dimen.qs_quick_tile_padding);
+ int remaining = (width - numTiles * size) / (numTiles - 1);
+ int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
+
+ final Builder builder = new Builder()
+ .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0)
+ .addFloat(mSettingsButton, "rotation", -120, 0)
+ .addFloat(mAlarmStatus, "alpha", 0, 1)
+ .addFloat(mAlarmStatus, "translationX", 0, -mDate.getWidth())
+ .addFloat(mAlarmStatusCollapsed, "translationX", 0, -mDate.getWidth());
+ if (mAlarmShowing) {
+ builder.addFloat(mDate, "alpha", 1, 0);
+ }
+ mAnimator = builder.build();
+ setExpansion(mExpansionAmount);
}
- public void setListening(boolean listening) {
- if (listening) {
- mSecurityController.addCallback(mCallback);
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateResources();
+ }
+
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ updateResources();
+ }
+
+ private void updateResources() {
+ FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
+
+ updateSettingsAnimator();
+ }
+
+ private void updateSettingsAnimator() {
+ mSettingsAlpha = createSettingsAlphaAnimator();
+
+ final boolean isRtl = isLayoutRtl();
+ if (isRtl && mDate.getWidth() == 0) {
+ mDate.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ mDate.setPivotX(getWidth());
+ mDate.removeOnLayoutChangeListener(this);
+ }
+ });
} else {
- mSecurityController.removeCallback(mCallback);
+ mDate.setPivotX(isRtl ? mDate.getWidth() : 0);
}
}
- public void onConfigurationChanged() {
- FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+ @Nullable
+ private TouchAnimator createSettingsAlphaAnimator() {
+ // If the settings icon is not shown and the user switcher is always shown, then there
+ // is nothing to animate.
+ if (!mShowEditIcon && mAlwaysShowMultiUserSwitch) {
+ return null;
+ }
+
+ TouchAnimator.Builder animatorBuilder = new TouchAnimator.Builder();
+
+ if (mShowEditIcon) {
+ animatorBuilder.addFloat(mEdit, "alpha", 0, 1);
+ }
+
+ if (!mAlwaysShowMultiUserSwitch) {
+ animatorBuilder.addFloat(mMultiUserSwitch, "alpha", 0, 1);
+ }
+
+ return animatorBuilder.build();
}
- public View getView() {
- return mRootView;
+ public void setExpanded(boolean expanded) {
+ if (mExpanded == expanded) return;
+ mExpanded = expanded;
+ updateEverything();
}
- public boolean hasFooter() {
- return mRootView.getVisibility() != View.GONE;
+ @Override
+ public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
+ mNextAlarm = nextAlarm;
+ if (nextAlarm != null) {
+ String alarmString = KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm);
+ mAlarmStatus.setText(alarmString);
+ mAlarmStatus.setContentDescription(mContext.getString(
+ R.string.accessibility_quick_settings_alarm, alarmString));
+ mAlarmStatusCollapsed.setContentDescription(mContext.getString(
+ R.string.accessibility_quick_settings_alarm, alarmString));
+ }
+ if (mAlarmShowing != (nextAlarm != null)) {
+ mAlarmShowing = nextAlarm != null;
+ updateAnimator(getWidth());
+ updateEverything();
+ }
+ }
+
+ public void setExpansion(float headerExpansionFraction) {
+ mExpansionAmount = headerExpansionFraction;
+ if (mAnimator != null) mAnimator.setPosition(headerExpansionFraction);
+
+ if (mSettingsAlpha != null) {
+ mSettingsAlpha.setPosition(headerExpansionFraction);
+ }
+
+ updateAlarmVisibilities();
+
+ mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
+ }
+
+ @Override
+ @VisibleForTesting
+ public void onDetachedFromWindow() {
+ setListening(false);
+ super.onDetachedFromWindow();
+ }
+
+ private void updateAlarmVisibilities() {
+ mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+ mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ public void setListening(boolean listening) {
+ if (listening == mListening) {
+ return;
+ }
+ mListening = listening;
+ updateListeners();
+ }
+
+ public View getExpandView() {
+ return findViewById(R.id.expand_indicator);
+ }
+
+ public void updateEverything() {
+ post(() -> {
+ updateVisibilities();
+ setClickable(false);
+ });
+ }
+
+ private void updateVisibilities() {
+ updateAlarmVisibilities();
+ mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
+ TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
+ final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
+
+ mMultiUserSwitch.setVisibility((mExpanded || mAlwaysShowMultiUserSwitch)
+ && mMultiUserSwitch.hasMultipleUsers() && !isDemo
+ ? View.VISIBLE : View.INVISIBLE);
+
+ if (mShowEditIcon) {
+ mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
+ }
+ }
+
+ private void updateListeners() {
+ if (mListening) {
+ mNextAlarmController.addCallback(this);
+ mUserInfoController.addCallback(this);
+ if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
+ Dependency.get(NetworkController.class).addEmergencyListener(this);
+ Dependency.get(NetworkController.class).addCallback(this);
+ }
+ } else {
+ mNextAlarmController.removeCallback(this);
+ mUserInfoController.removeCallback(this);
+ Dependency.get(NetworkController.class).removeEmergencyListener(this);
+ Dependency.get(NetworkController.class).removeCallback(this);
+ }
+ }
+
+ public void setQSPanel(final QSPanel qsPanel) {
+ mQsPanel = qsPanel;
+ if (mQsPanel != null) {
+ mMultiUserSwitch.setQsPanel(qsPanel);
+ }
}
@Override
public void onClick(View v) {
- mHandler.sendEmptyMessage(H.CLICK);
- }
+ if (v == mSettingsButton) {
+ MetricsLogger.action(mContext,
+ mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
+ if (mSettingsButton.isTunerClick()) {
+ Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+ if (TunerService.isTunerEnabled(mContext)) {
+ TunerService.showResetRequest(mContext, () -> {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity();
+ });
+ } else {
+ Toast.makeText(getContext(), R.string.tuner_toast,
+ Toast.LENGTH_LONG).show();
+ TunerService.setTunerEnabled(mContext, true);
+ }
+ startSettingsActivity();
- private void handleClick() {
- showDeviceMonitoringDialog();
- }
-
- public void showDeviceMonitoringDialog() {
- mHost.collapsePanels();
- // TODO: Delay dialog creation until after panels are collapsed.
- createDialog();
- }
-
- public void refreshState() {
- mHandler.sendEmptyMessage(H.REFRESH_STATE);
- }
-
- private void handleRefreshState() {
- boolean isVpnEnabled = mSecurityController.isVpnEnabled();
- boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
- mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
- mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
- if (mSecurityController.isDeviceManaged()) {
- final CharSequence organizationName =
- mSecurityController.getDeviceOwnerOrganizationName();
- if (organizationName != null) {
- mFooterTextContent = mContext.getResources().getString(
- R.string.do_disclosure_with_name, organizationName);
+ });
} else {
- mFooterTextContent =
- mContext.getResources().getString(R.string.do_disclosure_generic);
+ startSettingsActivity();
}
- mIsVisible = true;
- int footerIconId = isVpnEnabled
- ? R.drawable.ic_qs_vpn
- : R.drawable.ic_qs_network_logging;
- if (mFooterIconId != footerIconId) {
- mFooterIconId = footerIconId;
- mMainHandler.post(mUpdateIcon);
+ } else if (v == mDateTimeGroup) {
+ if (mNextAlarm != null) {
+ PendingIntent showIntent = mNextAlarm.getShowIntent();
+ mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
+ } else {
+ mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+ AlarmClock.ACTION_SHOW_ALARMS), 0);
}
- } else {
- boolean isBranded = mSecurityController.isVpnBranded();
- mFooterTextContent = mContext.getResources().getText(
- isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
- // Update the VPN footer icon, if needed.
- int footerIconId = isVpnEnabled
- ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
- : R.drawable.ic_qs_network_logging;
- if (mFooterIconId != footerIconId) {
- mFooterIconId = footerIconId;
- mMainHandler.post(mUpdateIcon);
- }
- mIsVisible = mIsIconVisible;
}
- mMainHandler.post(mUpdateDisplayState);
+ }
+
+ private void startSettingsActivity() {
+ mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+ true /* dismissShade */);
}
@Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_NEGATIVE) {
- final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
- mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
- }
- }
-
- private void createDialog() {
- final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
- final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
- final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
- final String primaryVpn = mSecurityController.getPrimaryVpnName();
- final String profileVpn = mSecurityController.getProfileVpnName();
- final CharSequence deviceOwnerOrganization =
- mSecurityController.getDeviceOwnerOrganizationName();
- boolean hasProfileOwner = mSecurityController.hasProfileOwner();
- boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
-
- mDialog = new SystemUIDialog(mContext);
- if (!isBranded) {
- mDialog.setTitle(getTitle(deviceOwnerPackage));
- }
- CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
- profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
- if (deviceOwnerPackage == null) {
- mDialog.setMessage(msg);
- if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
- mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
- }
- } else {
- View dialogView = LayoutInflater.from(mContext)
- .inflate(R.layout.quick_settings_footer_dialog, null, false);
- mDialog.setView(dialogView);
- TextView deviceOwnerWarning =
- (TextView) dialogView.findViewById(R.id.device_owner_warning);
- deviceOwnerWarning.setText(msg);
- // Make the link "learn more" clickable.
- deviceOwnerWarning.setMovementMethod(new LinkMovementMethod());
- if (primaryVpn == null) {
- dialogView.findViewById(R.id.vpn_icon).setVisibility(View.GONE);
- dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
- dialogView.findViewById(R.id.vpn_warning).setVisibility(View.GONE);
- } else {
- final SpannableStringBuilder message = new SpannableStringBuilder();
- message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
- primaryVpn));
- if (!mSecurityController.isVpnRestricted()) {
- message.append(mContext.getString(
- R.string.monitoring_description_vpn_settings_separator));
- message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
- new VpnSpan(), 0);
- }
-
- TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
- vpnWarning.setText(message);
- // Make the link "Open VPN Settings" clickable.
- vpnWarning.setMovementMethod(new LinkMovementMethod());
- }
- if (!isNetworkLoggingEnabled) {
- dialogView.findViewById(R.id.network_logging_icon).setVisibility(View.GONE);
- dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
- dialogView.findViewById(R.id.network_logging_warning).setVisibility(View.GONE);
- }
- }
-
- mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
- mDialog.show();
- mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- private String getSettingsButton() {
- return mContext.getString(R.string.status_bar_settings_settings_button);
- }
-
- private String getPositiveButton(boolean isBranded) {
- return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
- }
-
- protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
- String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
- boolean hasProfileOwner, boolean isBranded) {
- if (deviceOwnerPackage != null) {
- final SpannableStringBuilder message = new SpannableStringBuilder();
- if (deviceOwnerOrganization != null) {
- message.append(mContext.getString(
- R.string.monitoring_description_do_header_with_name,
- deviceOwnerOrganization, deviceOwnerPackage));
- } else {
- message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
- deviceOwnerPackage));
- }
- message.append("\n\n");
- message.append(mContext.getString(R.string.monitoring_description_do_body));
- message.append(mContext.getString(
- R.string.monitoring_description_do_learn_more_separator));
- message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
- new EnterprisePrivacySpan(), 0);
- return message;
- } else if (primaryVpn != null) {
- if (profileVpn != null) {
- return mContext.getString(R.string.monitoring_description_app_personal_work,
- profileOwnerPackage, profileVpn, primaryVpn);
- } else {
- if (isBranded) {
- return mContext.getString(R.string.branded_monitoring_description_app_personal,
- primaryVpn);
- } else {
- return mContext.getString(R.string.monitoring_description_app_personal,
- primaryVpn);
- }
- }
- } else if (profileVpn != null) {
- return mContext.getString(R.string.monitoring_description_app_work,
- profileOwnerPackage, profileVpn);
- } else if (profileOwnerPackage != null && hasProfileOwner) {
- return mContext.getString(R.string.do_disclosure_with_name,
- profileOwnerPackage);
- } else {
- // No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
- return null;
- }
- }
-
- private int getTitle(String deviceOwner) {
- if (deviceOwner != null) {
- return R.string.monitoring_title_device_owned;
- } else {
- return R.string.monitoring_title;
- }
- }
-
- private final Runnable mUpdateIcon = new Runnable() {
- @Override
- public void run() {
- mFooterIcon.setImageResource(mFooterIconId);
- mFooterIcon2.setImageResource(mFooterIcon2Id);
- }
- };
-
- private final Runnable mUpdateDisplayState = new Runnable() {
- @Override
- public void run() {
- if (mFooterTextContent != null) {
- mFooterText.setText(mFooterTextContent);
- }
- mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
- mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
- mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
- }
- };
-
- private class Callback implements SecurityController.SecurityControllerCallback {
- @Override
- public void onStateChanged() {
- refreshState();
- }
- }
-
- private class H extends Handler {
- private static final int CLICK = 0;
- private static final int REFRESH_STATE = 1;
-
- private H(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- String name = null;
- try {
- if (msg.what == REFRESH_STATE) {
- name = "handleRefreshState";
- handleRefreshState();
- } else if (msg.what == CLICK) {
- name = "handleClick";
- handleClick();
- }
- } catch (Throwable t) {
- final String error = "Error in " + name;
- Log.w(TAG, error, t);
- mHost.warn(error, t);
+ public void setEmergencyCallsOnly(boolean show) {
+ boolean changed = show != mShowEmergencyCallsOnly;
+ if (changed) {
+ mShowEmergencyCallsOnly = show;
+ if (mExpanded) {
+ updateEverything();
}
}
}
- protected class EnterprisePrivacySpan extends ClickableSpan {
- @Override
- public void onClick(View widget) {
- final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mDialog.dismiss();
- mContext.startActivity(intent);
- }
-
- @Override
- public boolean equals(Object object) {
- return object instanceof EnterprisePrivacySpan;
- }
- }
-
- protected class VpnSpan extends ClickableSpan {
- @Override
- public void onClick(View widget) {
- final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mDialog.dismiss();
- mContext.startActivity(intent);
- }
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+ mMultiUserAvatar.setImageDrawable(picture);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 95e0301..3a93d51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -24,6 +24,7 @@
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout.LayoutParams;
@@ -33,8 +34,6 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
import com.android.systemui.statusbar.stack.StackStateAnimator;
public class QSFragment extends Fragment implements QS {
@@ -58,6 +57,7 @@
private boolean mListening;
private QSContainerImpl mContainer;
private int mLayoutDirection;
+ private QSFooter mFooter;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -68,9 +68,10 @@
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- mQSPanel = (QSPanel) view.findViewById(R.id.quick_settings_panel);
- mQSDetail = (QSDetail) view.findViewById(R.id.qs_detail);
- mHeader = (QuickStatusBarHeader) view.findViewById(R.id.header);
+ mQSPanel = view.findViewById(R.id.quick_settings_panel);
+ mQSDetail = view.findViewById(R.id.qs_detail);
+ mHeader = view.findViewById(R.id.header);
+ mFooter = view.findViewById(R.id.qs_footer);
mContainer = (QSContainerImpl) view;
mQSDetail.setQsPanel(mQSPanel, mHeader);
@@ -79,13 +80,18 @@
// the row to the full QS panel.
if (getResources().getBoolean(R.bool.config_showQuickSettingsRow)) {
mQSAnimator = new QSAnimator(this,
- (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
+ mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
}
- mQSCustomizer = (QSCustomizer) view.findViewById(R.id.qs_customize);
+ mQSCustomizer = view.findViewById(R.id.qs_customize);
mQSCustomizer.setQs(this);
}
+ @Override
+ public View getHeader() {
+ return mHeader;
+ }
+
public void setPanelView(HeightListener panelView) {
mPanelView = panelView;
}
@@ -116,6 +122,7 @@
public void setHost(QSTileHost qsh) {
mQSPanel.setHost(qsh, mQSCustomizer);
mHeader.setQSPanel(mQSPanel);
+ mFooter.setQSPanel(mQSPanel);
mQSDetail.setHost(qsh);
if (mQSAnimator != null) {
@@ -133,13 +140,14 @@
: View.INVISIBLE);
mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
|| (mQsExpanded && !mStackScrollerOverscrolling));
+ mFooter.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ mFooter.setExpanded((mKeyguardShowing && !mHeaderAnimating)
+ || (mQsExpanded && !mStackScrollerOverscrolling));
mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
}
- public BaseStatusBarHeader getHeader() {
- return mHeader;
- }
-
public QSPanel getQsPanel() {
return mQSPanel;
}
@@ -155,6 +163,7 @@
public void setHeaderClickable(boolean clickable) {
if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
mHeader.setClickable(clickable);
+ mFooter.setClickable(clickable);
}
public void setExpanded(boolean expanded) {
@@ -185,11 +194,13 @@
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
mHeader.setListening(listening);
+ mFooter.setListening(listening);
mQSPanel.setListening(mListening && mQsExpanded);
}
public void setHeaderListening(boolean listening) {
mHeader.setListening(listening);
+ mFooter.setListening(listening);
}
public void setQsExpansion(float expansion, float headerTranslation) {
@@ -201,7 +212,9 @@
: headerTranslation);
}
mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
- mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
+ mFooter.setExpansion(mKeyguardShowing ? 1 : expansion);
+ int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
+ mQSPanel.setTranslationY(translationScaleY * heightDiff);
mQSDetail.setFullyExpanded(expansion == 1);
if (mQSAnimator != null) {
@@ -209,7 +222,7 @@
}
// Set bounds on the QS panel so it doesn't run over the header.
- mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion));
+ mQsBounds.top = (int) (mHeader.getBottom() * (1 - expansion));
mQsBounds.right = mQSPanel.getWidth();
mQsBounds.bottom = mQSPanel.getHeight();
mQSPanel.setClipBounds(mQsBounds);
@@ -245,6 +258,11 @@
}
@Override
+ public void setExpandClickListener(OnClickListener onClickListener) {
+ mFooter.getExpandView().setOnClickListener(onClickListener);
+ }
+
+ @Override
public void closeDetail() {
mQSPanel.closeDetail();
}
@@ -254,6 +272,7 @@
mContainer.updateBottom();
mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
+ mFooter.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
// Let the panel know the position changed and it needs to update where notifications
// and whatnot are.
mPanelView.onQsHeightChanged();
@@ -268,7 +287,8 @@
return getView().getHeight();
}
if (mQSDetail.isClosingDetail()) {
- int panelHeight = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+ LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+ int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
+ mQSPanel.getMeasuredHeight();
return panelHeight + getView().getPaddingBottom();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b257ca9..8298cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -16,12 +16,15 @@
package com.android.systemui.qs;
+import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
+import android.service.quicksettings.Tile;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -31,8 +34,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.QSHost.Callback;
@@ -40,7 +42,6 @@
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSliderView;
-import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -64,11 +65,11 @@
protected boolean mExpanded;
protected boolean mListening;
- private QS.Callback mCallback;
+ private QSDetail.Callback mCallback;
private BrightnessController mBrightnessController;
protected QSTileHost mHost;
- protected QSFooter mFooter;
+ protected QSSecurityFooter mFooter;
private boolean mGridContentVisible = true;
protected QSTileLayout mTileLayout;
@@ -77,6 +78,7 @@
private Record mDetailRecord;
private BrightnessMirrorController mBrightnessMirrorController;
+ private View mDivider;
public QSPanel(Context context) {
this(context, null);
@@ -94,7 +96,7 @@
setupTileLayout();
- mFooter = new QSFooter(this, context);
+ mFooter = new QSSecurityFooter(this, context);
addView(mFooter.getView());
mPageIndicator = LayoutInflater.from(context).inflate(
@@ -104,11 +106,23 @@
((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator);
}
+ addDivider();
+
updateResources();
mBrightnessController = new BrightnessController(getContext(),
- (ImageView) findViewById(R.id.brightness_icon),
- (ToggleSliderView) findViewById(R.id.brightness_slider));
+ findViewById(R.id.brightness_icon),
+ findViewById(R.id.brightness_slider));
+ }
+
+ protected void addDivider() {
+ mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
+ mDivider.setBackgroundColor(getColorForState(mContext, Tile.STATE_INACTIVE));
+ addView(mDivider);
+ }
+
+ public View getDivider() {
+ return mDivider;
}
public View getPageIndicator() {
@@ -176,8 +190,8 @@
public void setBrightnessMirror(BrightnessMirrorController c) {
mBrightnessMirrorController = c;
- ToggleSliderView brightnessSlider = (ToggleSliderView) findViewById(R.id.brightness_slider);
- ToggleSliderView mirror = (ToggleSliderView) c.getMirror().findViewById(
+ ToggleSliderView brightnessSlider = findViewById(R.id.brightness_slider);
+ ToggleSliderView mirror = c.getMirror().findViewById(
R.id.brightness_slider);
brightnessSlider.setMirror(mirror);
brightnessSlider.setMirrorController(c);
@@ -187,7 +201,7 @@
return mBrightnessView;
}
- public void setCallback(QS.Callback callback) {
+ public void setCallback(QSDetail.Callback callback) {
mCallback = callback;
}
@@ -515,7 +529,7 @@
return null;
}
- public QSFooter getFooter() {
+ public QSSecurityFooter getFooter() {
return mFooter;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
new file mode 100644
index 0000000..4b2c20f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -0,0 +1,381 @@
+/*
+ * 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.text.SpannableStringBuilder;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+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.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.SecurityController;
+
+import static android.provider.Settings.ACTION_VPN_SETTINGS;
+
+public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
+ protected static final String TAG = "QSSecurityFooter";
+ protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final View mRootView;
+ private final TextView mFooterText;
+ private final ImageView mFooterIcon;
+ private final ImageView mFooterIcon2;
+ private final Context mContext;
+ private final Callback mCallback = new Callback();
+ private final SecurityController mSecurityController;
+ private final ActivityStarter mActivityStarter;
+ private final Handler mMainHandler;
+
+ private AlertDialog mDialog;
+ private QSTileHost mHost;
+ protected H mHandler;
+
+ private boolean mIsVisible;
+ private boolean mIsIconVisible;
+ private boolean mIsIcon2Visible;
+ private CharSequence mFooterTextContent = null;
+ private int mFooterTextId;
+ private int mFooterIconId;
+ private int mFooterIcon2Id;
+
+ public QSSecurityFooter(QSPanel qsPanel, Context context) {
+ mRootView = LayoutInflater.from(context)
+ .inflate(R.layout.quick_settings_footer, qsPanel, false);
+ mRootView.setOnClickListener(this);
+ mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
+ mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+ mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
+ mFooterIconId = R.drawable.ic_qs_vpn;
+ mFooterIcon2Id = R.drawable.ic_qs_network_logging;
+ mContext = context;
+ mMainHandler = new Handler(Looper.getMainLooper());
+ mActivityStarter = Dependency.get(ActivityStarter.class);
+ mSecurityController = Dependency.get(SecurityController.class);
+ mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+ }
+
+ public void setHostEnvironment(QSTileHost host) {
+ mHost = host;
+ }
+
+ public void setListening(boolean listening) {
+ if (listening) {
+ mSecurityController.addCallback(mCallback);
+ } else {
+ mSecurityController.removeCallback(mCallback);
+ }
+ }
+
+ public void onConfigurationChanged() {
+ FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+ }
+
+ public View getView() {
+ return mRootView;
+ }
+
+ public boolean hasFooter() {
+ return mRootView.getVisibility() != View.GONE;
+ }
+
+ @Override
+ public void onClick(View v) {
+ mHandler.sendEmptyMessage(H.CLICK);
+ }
+
+ private void handleClick() {
+ showDeviceMonitoringDialog();
+ }
+
+ public void showDeviceMonitoringDialog() {
+ mHost.collapsePanels();
+ // TODO: Delay dialog creation until after panels are collapsed.
+ createDialog();
+ }
+
+ public void refreshState() {
+ mHandler.sendEmptyMessage(H.REFRESH_STATE);
+ }
+
+ private void handleRefreshState() {
+ boolean isVpnEnabled = mSecurityController.isVpnEnabled();
+ boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
+ mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
+ if (mSecurityController.isDeviceManaged()) {
+ final CharSequence organizationName =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ if (organizationName != null) {
+ mFooterTextContent = mContext.getResources().getString(
+ R.string.do_disclosure_with_name, organizationName);
+ } else {
+ mFooterTextContent =
+ mContext.getResources().getString(R.string.do_disclosure_generic);
+ }
+ mIsVisible = true;
+ int footerIconId = isVpnEnabled
+ ? R.drawable.ic_qs_vpn
+ : R.drawable.ic_qs_network_logging;
+ if (mFooterIconId != footerIconId) {
+ mFooterIconId = footerIconId;
+ mMainHandler.post(mUpdateIcon);
+ }
+ } else {
+ boolean isBranded = mSecurityController.isVpnBranded();
+ mFooterTextContent = mContext.getResources().getText(
+ isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
+ // Update the VPN footer icon, if needed.
+ int footerIconId = isVpnEnabled
+ ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
+ : R.drawable.ic_qs_network_logging;
+ if (mFooterIconId != footerIconId) {
+ mFooterIconId = footerIconId;
+ mMainHandler.post(mUpdateIcon);
+ }
+ mIsVisible = mIsIconVisible;
+ }
+ mMainHandler.post(mUpdateDisplayState);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
+ mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
+ }
+ }
+
+ private void createDialog() {
+ final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
+ final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
+ final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ final String primaryVpn = mSecurityController.getPrimaryVpnName();
+ final String profileVpn = mSecurityController.getProfileVpnName();
+ final CharSequence deviceOwnerOrganization =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ boolean hasProfileOwner = mSecurityController.hasProfileOwner();
+ boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
+
+ mDialog = new SystemUIDialog(mContext);
+ if (!isBranded) {
+ mDialog.setTitle(getTitle(deviceOwnerPackage));
+ }
+ CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
+ profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
+ if (deviceOwnerPackage == null) {
+ mDialog.setMessage(msg);
+ if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
+ mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
+ }
+ } else {
+ View dialogView = LayoutInflater.from(mContext)
+ .inflate(R.layout.quick_settings_footer_dialog, null, false);
+ mDialog.setView(dialogView);
+ TextView deviceOwnerWarning =
+ (TextView) dialogView.findViewById(R.id.device_owner_warning);
+ deviceOwnerWarning.setText(msg);
+ // Make the link "learn more" clickable.
+ deviceOwnerWarning.setMovementMethod(new LinkMovementMethod());
+ if (primaryVpn == null) {
+ dialogView.findViewById(R.id.vpn_icon).setVisibility(View.GONE);
+ dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
+ dialogView.findViewById(R.id.vpn_warning).setVisibility(View.GONE);
+ } else {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
+ primaryVpn));
+ if (!mSecurityController.isVpnRestricted()) {
+ message.append(mContext.getString(
+ R.string.monitoring_description_vpn_settings_separator));
+ message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
+ new VpnSpan(), 0);
+ }
+
+ TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
+ vpnWarning.setText(message);
+ // Make the link "Open VPN Settings" clickable.
+ vpnWarning.setMovementMethod(new LinkMovementMethod());
+ }
+ if (!isNetworkLoggingEnabled) {
+ dialogView.findViewById(R.id.network_logging_icon).setVisibility(View.GONE);
+ dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
+ dialogView.findViewById(R.id.network_logging_warning).setVisibility(View.GONE);
+ }
+ }
+
+ mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
+ mDialog.show();
+ mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ private String getSettingsButton() {
+ return mContext.getString(R.string.status_bar_settings_settings_button);
+ }
+
+ private String getPositiveButton(boolean isBranded) {
+ return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
+ }
+
+ protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
+ String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
+ boolean hasProfileOwner, boolean isBranded) {
+ if (deviceOwnerPackage != null) {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ if (deviceOwnerOrganization != null) {
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_header_with_name,
+ deviceOwnerOrganization, deviceOwnerPackage));
+ } else {
+ message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
+ deviceOwnerPackage));
+ }
+ message.append("\n\n");
+ message.append(mContext.getString(R.string.monitoring_description_do_body));
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_learn_more_separator));
+ message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
+ new EnterprisePrivacySpan(), 0);
+ return message;
+ } else if (primaryVpn != null) {
+ if (profileVpn != null) {
+ return mContext.getString(R.string.monitoring_description_app_personal_work,
+ profileOwnerPackage, profileVpn, primaryVpn);
+ } else {
+ if (isBranded) {
+ return mContext.getString(R.string.branded_monitoring_description_app_personal,
+ primaryVpn);
+ } else {
+ return mContext.getString(R.string.monitoring_description_app_personal,
+ primaryVpn);
+ }
+ }
+ } else if (profileVpn != null) {
+ return mContext.getString(R.string.monitoring_description_app_work,
+ profileOwnerPackage, profileVpn);
+ } else if (profileOwnerPackage != null && hasProfileOwner) {
+ return mContext.getString(R.string.do_disclosure_with_name,
+ profileOwnerPackage);
+ } else {
+ // No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
+ return null;
+ }
+ }
+
+ private int getTitle(String deviceOwner) {
+ if (deviceOwner != null) {
+ return R.string.monitoring_title_device_owned;
+ } else {
+ return R.string.monitoring_title;
+ }
+ }
+
+ private final Runnable mUpdateIcon = new Runnable() {
+ @Override
+ public void run() {
+ mFooterIcon.setImageResource(mFooterIconId);
+ mFooterIcon2.setImageResource(mFooterIcon2Id);
+ }
+ };
+
+ private final Runnable mUpdateDisplayState = new Runnable() {
+ @Override
+ public void run() {
+ if (mFooterTextContent != null) {
+ mFooterText.setText(mFooterTextContent);
+ }
+ mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
+ mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
+ mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
+ }
+ };
+
+ private class Callback implements SecurityController.SecurityControllerCallback {
+ @Override
+ public void onStateChanged() {
+ refreshState();
+ }
+ }
+
+ private class H extends Handler {
+ private static final int CLICK = 0;
+ private static final int REFRESH_STATE = 1;
+
+ private H(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ String name = null;
+ try {
+ if (msg.what == REFRESH_STATE) {
+ name = "handleRefreshState";
+ handleRefreshState();
+ } else if (msg.what == CLICK) {
+ name = "handleClick";
+ handleClick();
+ }
+ } catch (Throwable t) {
+ final String error = "Error in " + name;
+ Log.w(TAG, error, t);
+ mHost.warn(error, t);
+ }
+ }
+ }
+
+ protected class EnterprisePrivacySpan extends ClickableSpan {
+ @Override
+ public void onClick(View widget) {
+ final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mDialog.dismiss();
+ mContext.startActivity(intent);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ return object instanceof EnterprisePrivacySpan;
+ }
+ }
+
+ protected class VpnSpan extends ClickableSpan {
+ @Override
+ public void onClick(View widget) {
+ final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mDialog.dismiss();
+ mContext.startActivity(intent);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
similarity index 88%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
rename to packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index bd7be91..0ca115e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -1,20 +1,18 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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.
+ * 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.statusbar.phone;
+package com.android.systemui.qs;
import android.app.ActivityManager;
import android.content.ComponentName;
@@ -36,30 +34,14 @@
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTileView;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
-import com.android.systemui.qs.tiles.AirplaneModeTile;
-import com.android.systemui.qs.tiles.BatterySaverTile;
-import com.android.systemui.qs.tiles.BluetoothTile;
-import com.android.systemui.qs.tiles.CastTile;
-import com.android.systemui.qs.tiles.CellularTile;
-import com.android.systemui.qs.tiles.ColorInversionTile;
-import com.android.systemui.qs.tiles.DataSaverTile;
-import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.qs.tiles.FlashlightTile;
-import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
-import com.android.systemui.qs.tiles.LocationTile;
-import com.android.systemui.qs.tiles.NfcTile;
-import com.android.systemui.qs.tiles.NightDisplayTile;
-import com.android.systemui.qs.tiles.RotationLockTile;
-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.statusbar.phone.AutoTileManager;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index c8a232f..8539cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -30,8 +30,6 @@
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.qs.tileimpl.QSTileBaseView;
-import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -47,7 +45,6 @@
private int mMaxTiles;
protected QSPanel mFullPanel;
- private View mHeader;
public QuickQSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -66,6 +63,10 @@
}
@Override
+ protected void addDivider() {
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES);
@@ -79,7 +80,6 @@
public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
mFullPanel = fullPanel;
- mHeader = header;
}
@Override
@@ -141,7 +141,7 @@
}
};
- public int getNumQuickTiles(Context context) {
+ public static int getNumQuickTiles(Context context) {
return Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, 6);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
new file mode 100644
index 0000000..8c1c89f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -0,0 +1,148 @@
+/*
+ * 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 android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.widget.RelativeLayout;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.BatteryMeterView;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSDetail.Callback;
+import com.android.systemui.statusbar.SignalClusterView;
+
+
+public class QuickStatusBarHeader extends RelativeLayout {
+
+ private ActivityStarter mActivityStarter;
+
+ private QSPanel mQsPanel;
+
+ private boolean mExpanded;
+ private boolean mListening;
+
+ protected QuickQSPanel mHeaderQsPanel;
+ protected QSTileHost mHost;
+
+ public QuickStatusBarHeader(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ Resources res = getResources();
+
+ mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
+ mHeaderQsPanel.setVisibility(res.getBoolean(R.bool.config_showQuickSettingsRow)
+ ? VISIBLE : GONE);
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+
+ updateResources();
+
+ // Set the light/dark theming on the header status UI to match the current theme.
+ SignalClusterView cluster = findViewById(R.id.signal_cluster);
+ int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
+ float intensity = colorForeground == Color.WHITE ? 0 : 1;
+ cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
+
+ BatteryMeterView battery = findViewById(R.id.battery);
+ battery.setForceShowPercent(true);
+ int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
+ battery.setRawColors(colorForeground, colorSecondary);
+
+ mActivityStarter = Dependency.get(ActivityStarter.class);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateResources();
+ }
+
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ updateResources();
+ }
+
+ private void updateResources() {
+ }
+
+ public int getCollapsedHeight() {
+ return getHeight();
+ }
+
+ public int getExpandedHeight() {
+ return getHeight();
+ }
+
+ public void setExpanded(boolean expanded) {
+ if (mExpanded == expanded) return;
+ mExpanded = expanded;
+ mHeaderQsPanel.setExpanded(expanded);
+ updateEverything();
+ }
+
+ public void setExpansion(float headerExpansionFraction) {
+ }
+
+ @Override
+ @VisibleForTesting
+ public void onDetachedFromWindow() {
+ setListening(false);
+ super.onDetachedFromWindow();
+ }
+
+ public void setListening(boolean listening) {
+ if (listening == mListening) {
+ return;
+ }
+ mHeaderQsPanel.setListening(listening);
+ mListening = listening;
+ }
+
+ public void updateEverything() {
+ post(() -> {
+ setClickable(false);
+ });
+ }
+
+ public void setQSPanel(final QSPanel qsPanel) {
+ mQsPanel = qsPanel;
+ setupHost(qsPanel.getHost());
+ }
+
+ public void setupHost(final QSTileHost host) {
+ mHost = host;
+ //host.setHeaderView(mExpandIndicator);
+ mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
+ mHeaderQsPanel.setHost(host, null /* No customization in header */);
+ }
+
+ public void setCallback(Callback qsPanelCallback) {
+ mHeaderQsPanel.setCallback(qsPanelCallback);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index b09c090..01f8169 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -29,12 +29,12 @@
import com.android.systemui.qs.tileimpl.QSIconViewImpl;
/** View that represents a custom quick settings tile for displaying signal info (wifi/cell). **/
-public final class SignalTileView extends QSIconViewImpl {
+public class SignalTileView extends QSIconViewImpl {
private static final long DEFAULT_DURATION = new ValueAnimator().getDuration();
private static final long SHORT_DURATION = DEFAULT_DURATION / 3;
- private FrameLayout mIconFrame;
- private ImageView mSignal;
+ protected FrameLayout mIconFrame;
+ protected ImageView mSignal;
private ImageView mIn;
private ImageView mOut;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 2c45d6a..c0fb4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -44,7 +44,7 @@
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
@@ -72,6 +72,8 @@
private NotificationsQuickSettingsContainer mNotifQsContainer;
private QS mQs;
private boolean mFinishedFetchingTiles = false;
+ private int mX;
+ private int mY;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -134,6 +136,8 @@
public void show(int x, int y) {
if (!isShown) {
+ mX = x;
+ mY = y;
MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = true;
setTileSpecs();
@@ -164,7 +168,7 @@
mToolbar.dismissPopupMenus();
setCustomizing(false);
save();
- mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
+ mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(false);
announceForAccessibility(mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 91bef27..c33d7da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -47,7 +47,7 @@
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index df7cbaf..547bef7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -35,7 +35,7 @@
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import java.util.ArrayList;
import java.util.Collection;
@@ -109,7 +109,7 @@
private void addPackageTiles(Handler mainHandler, Handler bgHandler) {
bgHandler.post(() -> {
- Collection<QSTile<?>> params = mHost.getTiles();
+ Collection<QSTile> params = mHost.getTiles();
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> services = pm.queryIntentServicesAsUser(
new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
@@ -150,8 +150,8 @@
});
}
- private State getState(Collection<QSTile<?>> tiles, String spec) {
- for (QSTile<?> tile : tiles) {
+ private State getState(Collection<QSTile> tiles, String spec) {
+ for (QSTile tile : tiles) {
if (spec.equals(tile.getTileSpec())) {
return tile.getState().copy();
}
@@ -165,7 +165,7 @@
}
TileInfo info = new TileInfo();
info.state = state;
- info.state.minimalAccessibilityClassName = info.state.expandedAccessibilityClassName =
+ info.state.expandedAccessibilityClassName =
Button.class.getName();
info.spec = spec;
info.appLabel = appLabel;
@@ -180,7 +180,6 @@
state.label = label;
state.contentDescription = label;
state.icon = new DrawableIcon(drawable);
- state.autoMirrorDrawable = false;
addTile(spec, appLabel, state, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 58e5acb..6f35017 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -41,7 +41,7 @@
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import libcore.util.Objects;
import static android.view.Display.DEFAULT_DISPLAY;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index ec4ca7a6..d9c3cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -37,7 +37,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index a683609..17a0d33 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -38,7 +38,7 @@
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.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
public class QSFactoryImpl implements QSFactory {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 3bb198f..a751ef4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -30,6 +30,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
import java.util.Objects;
@@ -81,7 +82,7 @@
setIcon((ImageView) mIcon, state);
}
- protected void setIcon(ImageView iv, QSTile.State state) {
+ protected void updateIcon(ImageView iv, State state) {
if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
Drawable d = state.icon != null
? iv.isShown() && mAnimationEnabled ? state.icon.getDrawable(mContext)
@@ -101,13 +102,17 @@
}
}
}
+ }
+
+ protected void setIcon(ImageView iv, QSTile.State state) {
+ updateIcon(iv, state);
if (state.disabledByPolicy) {
iv.setColorFilter(getContext().getColor(R.color.qs_tile_disabled_color));
} else {
iv.clearColorFilter();
}
if (state.state != mState) {
- int color = getColorForState(getContext(), state.state);
+ int color = getColor(state.state);
mState = state.state;
if (iv.isShown()) {
animateGrayScale(mTint, color, iv);
@@ -119,6 +124,10 @@
}
}
+ protected int getColor(int state) {
+ return getColorForState(getContext(), state);
+ }
+
public static void animateGrayScale(int fromColor, int toColor, ImageView iv) {
final float fromAlpha = Color.alpha(fromColor);
final float toAlpha = Color.alpha(toColor);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 585b72f..5ac7891 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -34,7 +34,7 @@
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+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;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index bcc553e..c7979d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -40,7 +40,7 @@
import com.android.settingslib.graph.UsageView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.tileimpl.QSTileImpl;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 6554087..d552a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -34,7 +34,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 68aefab..a1d3d26 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -31,7 +31,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 85788f3..ca70336 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,7 +24,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
+import android.widget.Switch;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -32,12 +32,12 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSHost;
+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.qs.CellTileView;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.qs.SignalTileView;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -83,7 +83,7 @@
@Override
public QSIconView createTileView(Context context) {
- return new SignalTileView(context);
+ return new CellTileView(context);
}
@Override
@@ -128,32 +128,13 @@
} else {
state.icon = ResourceIcon.get(iconId);
}
- state.dualTarget = true;
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
- state.label = cb.enabled
- ? removeTrailingPeriod(cb.enabledDesc)
- : r.getString(R.string.quick_settings_rssi_emergency_only);
+ state.label = r.getString(R.string.mobile_data);
- final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
- ? cb.signalContentDescription
- : r.getString(R.string.accessibility_no_signal);
-
- if (cb.noSim) {
- state.contentDescription = state.label;
- } else {
- String enabledDesc = cb.enabled ? r.getString(R.string.accessibility_cell_data_on)
- : r.getString(R.string.accessibility_cell_data_off);
-
- state.contentDescription = r.getString(
- R.string.accessibility_quick_settings_mobile,
- enabledDesc, signalContentDesc,
- state.label);
- }
- state.contentDescription = state.contentDescription + "," + r.getString(
- R.string.accessibility_quick_settings_open_settings, getTileLabel());
- state.expandedAccessibilityClassName = Button.class.getName();
+ state.contentDescription = state.label;
+ state.expandedAccessibilityClassName = Switch.class.getName();
state.value = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 5f89e23..d3586c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -40,7 +40,7 @@
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index c998431..d6043f4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -23,7 +23,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 1b5b64c..0270641 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -33,7 +33,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index cd9a49d..7512efa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,6 +24,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 8cad85c..820638c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -32,7 +32,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -74,7 +74,7 @@
if (mUserListener == null) {
return false;
}
- return mUserListener.getCount() != 0;
+ return mUserListener.getUserCount() > 1;
}
public void setUserSwitcherController(UserSwitcherController userSwitcherController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e6d3168..c24a2a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -295,7 +295,6 @@
lp.width = panelWidth;
lp.gravity = panelGravity;
mQsFrame.setLayoutParams(lp);
- post(mUpdateHeader);
}
lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
@@ -2140,13 +2139,6 @@
mKeyguardUserSwitcher = keyguardUserSwitcher;
}
- private final Runnable mUpdateHeader = new Runnable() {
- @Override
- public void run() {
- mQs.getHeader().updateEverything();
- }
- };
-
public void onScreenTurningOn() {
mKeyguardStatusView.refreshTime();
}
@@ -2442,7 +2434,7 @@
public void onFragmentViewCreated(String tag, Fragment fragment) {
mQs = (QS) fragment;
mQs.setPanelView(NotificationPanelView.this);
- mQs.getHeader().getExpandView().setOnClickListener(NotificationPanelView.this);
+ mQs.setExpandClickListener(NotificationPanelView.this);
mQs.setHeaderClickable(mQsExpansionEnabled);
mQs.setKeyguardShowing(mKeyguardShowing);
mQs.setOverscrolling(mStackScrollerOverscrolling);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
deleted file mode 100644
index a5590f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ /dev/null
@@ -1,482 +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.statusbar.phone;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.os.UserManager;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.telephony.SubscriptionInfo;
-import android.util.AttributeSet;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.settingslib.Utils;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.BatteryMeterView;
-import com.android.systemui.Dependency;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QuickQSPanel;
-import com.android.systemui.qs.TouchAnimator;
-import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.SignalClusterView;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
-import com.android.systemui.tuner.TunerService;
-
-import java.util.List;
-
-public class QuickStatusBarHeader extends BaseStatusBarHeader implements
- NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
- SignalCallback {
- private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
-
- private ActivityStarter mActivityStarter;
- private NextAlarmController mNextAlarmController;
- private UserInfoController mUserInfoController;
- private SettingsButton mSettingsButton;
- protected View mSettingsContainer;
-
- private TextView mAlarmStatus;
- private View mAlarmStatusCollapsed;
- private ViewGroup mDateTimeGroup;
- private ViewGroup mDateTimeAlarmGroup;
-
- private QSPanel mQsPanel;
-
- private boolean mExpanded;
- private boolean mAlarmShowing;
-
- private TextView mEmergencyOnly;
-
- protected ExpandableIndicator mExpandIndicator;
-
- private boolean mListening;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
- protected QuickQSPanel mHeaderQsPanel;
- private boolean mShowEmergencyCallsOnly;
- protected MultiUserSwitch mMultiUserSwitch;
- private ImageView mMultiUserAvatar;
- private boolean mAlwaysShowMultiUserSwitch;
-
- private TouchAnimator mAnimator;
- protected TouchAnimator mSettingsAlpha;
- private float mExpansionAmount;
- protected QSTileHost mHost;
-
- protected View mEdit;
- private boolean mShowEditIcon;
-
- private boolean mShowFullAlarm;
- private float mDateTimeTranslation;
- private SparseBooleanArray mRoamingsBySubId = new SparseBooleanArray();
- private boolean mIsRoaming;
-
- public QuickStatusBarHeader(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- Resources res = getResources();
-
- mEmergencyOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
-
- mShowEditIcon = res.getBoolean(R.bool.config_showQuickSettingsEditingIcon);
-
- mEdit = findViewById(android.R.id.edit);
- mEdit.setVisibility(mShowEditIcon ? VISIBLE : GONE);
-
- if (mShowEditIcon) {
- findViewById(android.R.id.edit).setOnClickListener(view ->
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
- mQsPanel.showEdit(view)));
- }
-
- mDateTimeAlarmGroup = (ViewGroup) findViewById(R.id.date_time_alarm_group);
- mDateTimeAlarmGroup.findViewById(R.id.empty_time_view).setVisibility(View.GONE);
- mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
- mDateTimeGroup.setPivotX(0);
- mDateTimeGroup.setPivotY(0);
- mDateTimeTranslation = res.getDimension(R.dimen.qs_date_time_translation);
- mShowFullAlarm = res.getBoolean(R.bool.quick_settings_show_full_alarm);
-
- mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
- mExpandIndicator.setVisibility(
- res.getBoolean(R.bool.config_showQuickSettingsExpandIndicator)
- ? VISIBLE : GONE);
-
- mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
- mHeaderQsPanel.setVisibility(res.getBoolean(R.bool.config_showQuickSettingsRow)
- ? VISIBLE : GONE);
-
- mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
- mSettingsContainer = findViewById(R.id.settings_button_container);
- mSettingsButton.setOnClickListener(this);
-
- mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
- mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
- mAlarmStatus.setOnClickListener(this);
-
- mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
- mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
- mAlwaysShowMultiUserSwitch = res.getBoolean(R.bool.config_alwaysShowMultiUserSwitcher);
-
- // RenderThread is doing more harm than good when touching the header (to expand quick
- // settings), so disable it for this view
- ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
-
- updateResources();
-
- // Set the light/dark theming on the header status UI to match the current theme.
- SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster);
- int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
- float intensity = colorForeground == Color.WHITE ? 0 : 1;
- cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
-
- BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery);
- battery.setForceShowPercent(true);
- int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
- battery.setRawColors(colorForeground, colorSecondary);
-
- mNextAlarmController = Dependency.get(NextAlarmController.class);
- mUserInfoController = Dependency.get(UserInfoController.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateResources();
- }
-
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- updateResources();
- }
-
- private void updateResources() {
- FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
- FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
-
- Builder builder = new Builder()
- .addFloat(mShowFullAlarm ? mAlarmStatus : findViewById(R.id.date), "alpha", 0, 1)
- .addFloat(mEmergencyOnly, "alpha", 0, 1);
- if (mShowFullAlarm) {
- builder.addFloat(mAlarmStatusCollapsed, "alpha", 1, 0);
- }
- mAnimator = builder.build();
-
- updateSettingsAnimator();
- }
-
- private void updateSettingsAnimator() {
- mSettingsAlpha = createSettingsAlphaAnimator();
-
- final boolean isRtl = isLayoutRtl();
- if (isRtl && mDateTimeGroup.getWidth() == 0) {
- mDateTimeGroup.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- mDateTimeGroup.setPivotX(getWidth());
- mDateTimeGroup.removeOnLayoutChangeListener(this);
- }
- });
- } else {
- mDateTimeGroup.setPivotX(isRtl ? mDateTimeGroup.getWidth() : 0);
- }
- }
-
- @Nullable
- private TouchAnimator createSettingsAlphaAnimator() {
- // If the settings icon is not shown and the user switcher is always shown, then there
- // is nothing to animate.
- if (!mShowEditIcon && mAlwaysShowMultiUserSwitch) {
- return null;
- }
-
- TouchAnimator.Builder animatorBuilder = new TouchAnimator.Builder();
-
- if (mShowEditIcon) {
- animatorBuilder.addFloat(mEdit, "alpha", 0, 1);
- }
-
- if (!mAlwaysShowMultiUserSwitch) {
- animatorBuilder.addFloat(mMultiUserSwitch, "alpha", 0, 1);
- }
-
- return animatorBuilder.build();
- }
-
- @Override
- public int getCollapsedHeight() {
- return getHeight();
- }
-
- @Override
- public int getExpandedHeight() {
- return getHeight();
- }
-
- @Override
- public void setExpanded(boolean expanded) {
- if (mExpanded == expanded) return;
- mExpanded = expanded;
- mHeaderQsPanel.setExpanded(expanded);
- updateEverything();
- }
-
- @Override
- public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
- mNextAlarm = nextAlarm;
- if (nextAlarm != null) {
- String alarmString = KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm);
- mAlarmStatus.setText(alarmString);
- mAlarmStatus.setContentDescription(mContext.getString(
- R.string.accessibility_quick_settings_alarm, alarmString));
- mAlarmStatusCollapsed.setContentDescription(mContext.getString(
- R.string.accessibility_quick_settings_alarm, alarmString));
- }
- if (mAlarmShowing != (nextAlarm != null)) {
- mAlarmShowing = nextAlarm != null;
- updateEverything();
- }
- }
-
- @Override
- public void setExpansion(float headerExpansionFraction) {
- mExpansionAmount = headerExpansionFraction;
- updateDateTimePosition();
- mAnimator.setPosition(headerExpansionFraction);
-
- if (mSettingsAlpha != null) {
- mSettingsAlpha.setPosition(headerExpansionFraction);
- }
-
- updateAlarmVisibilities();
-
- mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
- }
-
- @Override
- @VisibleForTesting
- public void onDetachedFromWindow() {
- setListening(false);
- super.onDetachedFromWindow();
- }
-
- private void updateAlarmVisibilities() {
- mAlarmStatus.setVisibility(mAlarmShowing && mShowFullAlarm ? View.VISIBLE : View.INVISIBLE);
- mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
- }
-
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mHeaderQsPanel.setListening(listening);
- mListening = listening;
- updateListeners();
- }
-
- @Override
- public View getExpandView() {
- return findViewById(R.id.expand_indicator);
- }
-
- @Override
- public void updateEverything() {
- post(() -> {
- updateVisibilities();
- setClickable(false);
- });
- }
-
- private void updateVisibilities() {
- updateAlarmVisibilities();
- updateDateTimePosition();
- mEmergencyOnly.setVisibility(mExpanded && (mShowEmergencyCallsOnly || mIsRoaming)
- ? View.VISIBLE : View.INVISIBLE);
- mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
- TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
- final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
-
- mMultiUserSwitch.setVisibility((mExpanded || mAlwaysShowMultiUserSwitch)
- && mMultiUserSwitch.hasMultipleUsers() && !isDemo
- ? View.VISIBLE : View.INVISIBLE);
-
- if (mShowEditIcon) {
- mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
- }
- }
-
- private void updateDateTimePosition() {
- mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly || mIsRoaming
- ? mExpansionAmount * mDateTimeTranslation : 0);
- }
-
- private void updateListeners() {
- if (mListening) {
- mNextAlarmController.addCallback(this);
- mUserInfoController.addCallback(this);
- if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
- Dependency.get(NetworkController.class).addEmergencyListener(this);
- Dependency.get(NetworkController.class).addCallback(this);
- }
- } else {
- mNextAlarmController.removeCallback(this);
- mUserInfoController.removeCallback(this);
- Dependency.get(NetworkController.class).removeEmergencyListener(this);
- Dependency.get(NetworkController.class).removeCallback(this);
- }
- }
-
- public void setQSPanel(final QSPanel qsPanel) {
- mQsPanel = qsPanel;
- setupHost(qsPanel.getHost());
- if (mQsPanel != null) {
- mMultiUserSwitch.setQsPanel(qsPanel);
- }
- }
-
- public void setupHost(final QSTileHost host) {
- mHost = host;
- //host.setHeaderView(mExpandIndicator);
- mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
- mHeaderQsPanel.setHost(host, null /* No customization in header */);
- }
-
- @Override
- public void onClick(View v) {
- if (v == mSettingsButton) {
- MetricsLogger.action(mContext,
- mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
- : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
- if (mSettingsButton.isTunerClick()) {
- Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
- if (TunerService.isTunerEnabled(mContext)) {
- TunerService.showResetRequest(mContext, () -> {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast,
- Toast.LENGTH_LONG).show();
- TunerService.setTunerEnabled(mContext, true);
- }
- startSettingsActivity();
-
- });
- } else {
- startSettingsActivity();
- }
- } else if (v == mAlarmStatus && mNextAlarm != null) {
- PendingIntent showIntent = mNextAlarm.getShowIntent();
- mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
- }
- }
-
- private void startSettingsActivity() {
- mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */);
- }
-
- @Override
- public void setCallback(Callback qsPanelCallback) {
- mHeaderQsPanel.setCallback(qsPanelCallback);
- }
-
- @Override
- public void setEmergencyCallsOnly(boolean show) {
- boolean changed = show != mShowEmergencyCallsOnly;
- if (changed) {
- mShowEmergencyCallsOnly = show;
- if (mExpanded) {
- updateEverything();
- }
- }
- }
-
- @Override
- public void setSubs(List<SubscriptionInfo> subs) {
- mRoamingsBySubId.clear();
- updateRoaming();
- }
-
- public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
- int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
- String description, boolean isWide, int subId, boolean roaming) {
- mRoamingsBySubId.put(subId, roaming);
- updateRoaming();
- }
-
- private void updateRoaming() {
- boolean isRoaming = calculateRoaming();
- if (mIsRoaming != isRoaming) {
- mIsRoaming = isRoaming;
- mEmergencyOnly.setText(mIsRoaming ? R.string.accessibility_data_connection_roaming
- : com.android.internal.R.string.emergency_calls_only);
- if (mExpanded) {
- updateEverything();
- }
- }
- }
-
- private boolean calculateRoaming() {
- for (int i = 0; i < mRoamingsBySubId.size(); i++) {
- if (mRoamingsBySubId.valueAt(i)) return true;
- }
- return false;
- }
-
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 816a39d..19be586 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -140,11 +140,11 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -204,10 +204,8 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
-import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -436,7 +434,6 @@
private QSPanel mQSPanel;
// top bar
- BaseStatusBarHeader mHeader;
protected KeyguardStatusBarView mKeyguardStatusBar;
KeyguardStatusView mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index bb0748c..f0af77d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -81,6 +81,7 @@
private static final int AM_PM_STYLE_GONE = 2;
private final int mAmPmStyle;
+ private final boolean mShowDark;
private boolean mShowSeconds;
private Handler mSecondsHandler;
@@ -100,6 +101,7 @@
0, 0);
try {
mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
+ mShowDark = a.getBoolean(R.styleable.Clock_showDark, true);
} finally {
a.recycle();
}
@@ -124,7 +126,9 @@
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
StatusBarIconController.ICON_BLACKLIST);
SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
- Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
+ if (mShowDark) {
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
+ }
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
@@ -147,7 +151,9 @@
Dependency.get(TunerService.class).removeTunable(this);
SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
.removeCallbacks(this);
- Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
+ if (mShowDark) {
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index a776e99..53671a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -57,7 +57,7 @@
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUISecondaryUserService;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -664,6 +664,27 @@
controller.addAdapter(new WeakReference<>(this));
}
+ public int getUserCount() {
+ boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
+ && mKeyguardMonitor.isSecure()
+ && !mKeyguardMonitor.canSkipBouncer();
+ if (!secureKeyguardShowing) {
+ return mController.getUsers().size();
+ }
+ // The lock screen is secure and showing. Filter out restricted records.
+ final int N = mController.getUsers().size();
+ int count = 0;
+ for (int i = 0; i < N; i++) {
+ if (mController.getUsers().get(i).isGuest) continue;
+ if (mController.getUsers().get(i).isRestricted) {
+ break;
+ } else {
+ count++;
+ }
+ }
+ return count;
+ }
+
@Override
public int getCount() {
boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
index 0d87d6b..9849800 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
@@ -21,8 +21,7 @@
import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
import com.android.systemui.plugins.annotations.Requires;
import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QS.HeightListener;
import org.junit.Rule;
@@ -95,7 +94,6 @@
}
@Requires(target = QS.class, version = QS.VERSION)
- @Requires(target = Callback.class, version = Callback.VERSION)
@Requires(target = HeightListener.class, version = HeightListener.VERSION)
@Requires(target = DetailAdapter.class, version = DetailAdapter.VERSION)
public static class QSImpl {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index e7fa799..7153340 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -19,15 +19,13 @@
import android.os.Looper;
+import com.android.keyguard.CarrierText;
import com.android.systemui.Dependency;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.R;
import com.android.systemui.SysUIRunner;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.LayoutInflaterBuilder;
import com.android.systemui.utils.TestableLooper;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
@@ -37,9 +35,6 @@
import org.junit.runner.RunWith;
import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.widget.FrameLayout;
@@ -58,6 +53,7 @@
.replace("com.android.systemui.statusbar.policy.SplitClockView",
FrameLayout.class)
.replace("TextClock", View.class)
+ .replace(CarrierText.class, View.class)
.build());
injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 2f6487b..e38c30f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -42,7 +42,7 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class QSFooterTest extends SysuiTestCase {
+public class QSSecurityFooterTest extends SysuiTestCase {
private final String MANAGING_ORGANIZATION = "organization";
private final String DEVICE_OWNER_PACKAGE = "TestDPC";
@@ -52,7 +52,7 @@
private TextView mFooterText;
private TestableImageView mFooterIcon;
private TestableImageView mFooterIcon2;
- private QSFooter mFooter;
+ private QSSecurityFooter mFooter;
private SecurityController mSecurityController = mock(SecurityController.class);
@Before
@@ -64,7 +64,7 @@
.replace("ImageView", TestableImageView.class)
.build());
Handler h = new Handler(Looper.getMainLooper());
- h.post(() -> mFooter = new QSFooter(null, mContext));
+ h.post(() -> mFooter = new QSSecurityFooter(null, mContext));
waitForIdleSync(h);
mRootView = (ViewGroup) mFooter.getView();
mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 308c779..11491a75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -34,7 +34,8 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.tileimpl.QSIconViewImpl;
+import com.android.systemui.qs.tileimpl.QSTileView;
import org.junit.Before;
import org.junit.Test;
@@ -59,7 +60,7 @@
private QSPanel.TileRecord createTileRecord() {
QSPanel.TileRecord tileRecord = new QSPanel.TileRecord();
tileRecord.tile = mock(QSTile.class);
- tileRecord.tileView = spy(new QSTileView(mContext, new QSIconView(mContext)));
+ tileRecord.tileView = spy(new QSTileView(mContext, new QSIconViewImpl(mContext)));
return tileRecord;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index b983820..d1e17f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -15,29 +15,27 @@
package com.android.systemui.qs.customize;
import static junit.framework.Assert.assertEquals;
-
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
-
import com.android.systemui.Dependency;
import com.android.systemui.SysUIRunner;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.QSTile.State;
-import com.android.systemui.statusbar.phone.QSTileHost;
-
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.utils.TestableLooper;
-import com.android.systemui.utils.TestableLooper.MessageHandler;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+
@SmallTest
@RunWith(SysUIRunner.class)
@RunWithLooper
@@ -65,7 +63,7 @@
public void testCompletionCalledAfterTilesFetched() {
QSTile mockTile = mock(QSTile.class);
State mockState = mock(State.class);
- when(mockTile.newTileState()).thenReturn(mockState);
+ when(mockState.copy()).thenReturn(mockState);
when(mockTile.getState()).thenReturn(mockState);
when(mockTile.isAvailable()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 70c7d3e..6d7b50f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -27,7 +27,7 @@
import com.android.systemui.SysUIRunner;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.utils.TestableLooper;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 9a477d2..3ccb160 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -24,6 +24,7 @@
import com.android.systemui.Prefs.Key;
import com.android.systemui.SysUIRunner;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.QSTileHost;
import org.junit.After;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java
deleted file mode 100644
index 99cecff..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStatusBarHeaderTest.java
+++ /dev/null
@@ -1,86 +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.statusbar.phone;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-import com.android.systemui.R.layout;
-import com.android.systemui.SysUIRunner;
-import com.android.systemui.utils.TestableLooper;
-import com.android.systemui.utils.TestableLooper.RunWithLooper;
-import com.android.systemui.utils.ViewUtils;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-
-@RunWith(SysUIRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-public class QuickStatusBarHeaderTest extends LeakCheckedTest {
-
- @Before
- public void setup() throws NoSuchFieldException, IllegalAccessException {
- injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- }
-
- @Test
- @Ignore("Flaky")
- public void testRoamingStuck() throws Exception {
- TestableLooper looper = TestableLooper.get(this);
- assertEquals(Looper.myLooper(), looper.getLooper());
- assertEquals(Looper.myLooper(), Looper.getMainLooper());
- QuickStatusBarHeader header = (QuickStatusBarHeader) LayoutInflater.from(mContext).inflate(
- layout.quick_status_bar_expanded_header, null);
- header.setExpanded(true);
-
- ViewUtils.attachView(header);
- looper.processMessages(1);
- TextView emergencyText = (TextView) header.findViewById(
- R.id.header_emergency_calls_only);
- int subId = 0;
- header.setMobileDataIndicators(null, null, 0, 0, false,
- false, null, null, false, subId, true);
- looper.processAllMessages();
- assertEquals(mContext.getString(R.string.accessibility_data_connection_roaming),
- emergencyText.getText());
- assertEquals(View.VISIBLE, emergencyText.getVisibility());
-
- header.setSubs(new ArrayList<>());
- subId = 1;
- header.setMobileDataIndicators(null, null, 0, 0, false,
- false, null, null, false, subId, false);
- looper.processAllMessages();
-
- assertNotEquals(View.VISIBLE, emergencyText.getVisibility());
- assertEquals(Looper.myLooper(), Looper.getMainLooper());
- ViewUtils.detachView(header);
- looper.processAllMessages();
- }
-
-}