summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Crump <chris@cypheros.co>2019-09-30 16:47:42 -0400
committeralk3pInjection <webmaster@raspii.tech>2021-09-27 21:17:05 +0800
commitbaa0cb5f1a5285c7f119ffc1dadfc5f845dff241 (patch)
tree1cf9127a7e4ae946f831d4aabdec06360bda988d
parentf31faa200d2ca8b2e30969989c4935eb52f2fd79 (diff)
[aospa][quartz] SystemUI: Introduce user interface for Alert Sliders
Ported from OxygenOS and reworked for our alert slider implementation. We target AudioManager instead of Zen, icons are also the same as aosp and the dialog uses the material theme as well as support for our themes. To use, the alert slider config must be enabled. By default, the dialog shows on the left side. To move it to the right side, set the location config to 1. Change-Id: Ie1954a44cc5242c95a731abd7404379ea638fe70
-rw-r--r--core/res/res/values/lineage_config.xml5
-rw-r--r--core/res/res/values/lineage_symbols.xml1
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml29
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml29
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_navigation_bg.xml29
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_triangle_right.xml27
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_triangle_top.xml27
-rw-r--r--packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml29
-rw-r--r--packages/SystemUI/res/layout/tri_state_dialog.xml62
-rw-r--r--packages/SystemUI/res/values/pa_dimens.xml51
-rw-r--r--packages/SystemUI/res/values/pa_styles.xml24
-rw-r--r--packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java476
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java19
14 files changed, 839 insertions, 1 deletions
diff --git a/core/res/res/values/lineage_config.xml b/core/res/res/values/lineage_config.xml
index 60b256e45db1..c19eb90bd802 100644
--- a/core/res/res/values/lineage_config.xml
+++ b/core/res/res/values/lineage_config.xml
@@ -37,4 +37,9 @@
<!-- Whether device has an alert slider. -->
<bool name="config_hasAlertSlider">false</bool>
+
+ <!-- The location of the device's alert slider:
+ 0: Left side
+ 1: Right side -->
+ <integer name="config_alertSliderLocation">1</integer>
</resources>
diff --git a/core/res/res/values/lineage_symbols.xml b/core/res/res/values/lineage_symbols.xml
index 826062e7b715..dfbf09de1789 100644
--- a/core/res/res/values/lineage_symbols.xml
+++ b/core/res/res/values/lineage_symbols.xml
@@ -30,4 +30,5 @@
<java-symbol type="string" name="alert_slider_state_path" />
<java-symbol type="string" name="alert_slider_uevent_match_path" />
<java-symbol type="bool" name="config_hasAlertSlider" />
+ <java-symbol type="integer" name="config_alertSliderLocation" />
</resources>
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml
new file mode 100644
index 000000000000..7dddc9d0e930
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="#ff1d1d1d" />
+ <corners
+ android:topLeftRadius="@dimen/tri_state_down_top_left_radius"
+ android:topRightRadius="@dimen/tri_state_down_top_right_radius"
+ android:bottomLeftRadius="@dimen/tri_state_down_bottom_left_radius"
+ android:bottomRightRadius="@dimen/tri_state_down_bottom_right_radius" />
+ </shape>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml
new file mode 100644
index 000000000000..7cde6be2808c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="#ff1d1d1d" />
+ <corners
+ android:topLeftRadius="@dimen/tri_state_mid_top_left_radius"
+ android:topRightRadius="@dimen/tri_state_mid_top_right_radius"
+ android:bottomLeftRadius="@dimen/tri_state_mid_bottom_left_radius"
+ android:bottomRightRadius="@dimen/tri_state_mid_bottom_right_radius" />
+ </shape>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_navigation_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_navigation_bg.xml
new file mode 100644
index 000000000000..93011a323a5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_navigation_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="#e6208de3" />
+ <corners
+ android:topLeftRadius="10.0dip"
+ android:topRightRadius="10.0dip"
+ android:bottomLeftRadius="10.0dip"
+ android:bottomRightRadius="10.0dip" />
+ </shape>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_triangle_right.xml b/packages/SystemUI/res/drawable/dialog_tri_state_triangle_right.xml
new file mode 100644
index 000000000000..ab90683bea54
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_triangle_right.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/shape_id" android:height="42.0px">
+ <rotate android:layout_width="fill_parent" android:layout_height="wrap_content" android:fromDegrees="45.0" android:pivotX="0.0%" android:pivotY="0.0%">
+ <shape android:shape="rectangle">
+ <solid android:color="#ff000000" />
+ <size android:height="29.695984px" android:width="29.695984px" />
+ </shape>
+ </rotate>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_triangle_top.xml b/packages/SystemUI/res/drawable/dialog_tri_state_triangle_top.xml
new file mode 100644
index 000000000000..e8566465d61b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_triangle_top.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/shape_id" android:width="42.0px">
+ <rotate android:layout_width="fill_parent" android:layout_height="wrap_content" android:fromDegrees="45.0" android:pivotX="0.0%" android:pivotY="100.0%">
+ <shape android:shape="rectangle">
+ <solid android:color="#ff000000" />
+ <size android:height="29.695984px" android:width="29.695984px" />
+ </shape>
+ </rotate>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml
new file mode 100644
index 000000000000..69757a77ee86
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="#ff1d1d1d" />
+ <corners
+ android:topLeftRadius="@dimen/tri_state_up_top_left_radius"
+ android:topRightRadius="@dimen/tri_state_up_top_right_radius"
+ android:bottomLeftRadius="@dimen/tri_state_up_bottom_left_radius"
+ android:bottomRightRadius="@dimen/tri_state_up_bottom_right_radius" />
+ </shape>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/tri_state_dialog.xml b/packages/SystemUI/res/layout/tri_state_dialog.xml
new file mode 100644
index 000000000000..177ed9b80521
--- /dev/null
+++ b/packages/SystemUI/res/layout/tri_state_dialog.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 CypherOS
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingLeft="@dimen/tri_state_dialog_padding"
+ android:paddingTop="@dimen/tri_state_dialog_padding"
+ android:paddingRight="@dimen/tri_state_dialog_padding"
+ android:paddingBottom="@dimen/tri_state_dialog_padding"
+ android:clipToPadding="false"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true">
+
+ <LinearLayout
+ android:layout_gravity="center|right"
+ android:orientation="horizontal"
+ android:id="@+id/tri_state_layout"
+ android:background="@drawable/dialog_tri_state_middle_bg"
+ android:layout_width="wrap_content"
+ android:layout_height="126.0px"
+ android:translationZ="5.0px">
+
+ <FrameLayout
+ android:layout_width="126.0px"
+ android:layout_height="fill_parent">
+
+ <ImageView
+ android:layout_gravity="center"
+ android:id="@+id/tri_state_icon"
+ android:layout_width="63.0px"
+ android:layout_height="63.0px" />
+ </FrameLayout>
+
+ <TextView
+ android:textSize="34.125px"
+ android:textColor="#ffffffff"
+ android:gravity="center_vertical"
+ android:id="@+id/tri_state_text"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:text="slience"
+ style="@style/TriStateUiText" />
+
+ <FrameLayout
+ android:layout_width="63.0px"
+ android:layout_height="fill_parent" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/pa_dimens.xml b/packages/SystemUI/res/values/pa_dimens.xml
new file mode 100644
index 000000000000..fdc1b75dc5e6
--- /dev/null
+++ b/packages/SystemUI/res/values/pa_dimens.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014-2020 Paranoid Android
+
+ 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Tri-state UI -->
+ <dimen name="tri_state_down_dialog_padding_edge">8.0dip</dimen>
+ <dimen name="tri_state_down_dialog_padding_edge_deep">21.0px</dimen>
+ <dimen name="tri_state_down_dialog_position">423.0px</dimen>
+ <dimen name="tri_state_down_dialog_position_l">270.375px</dimen>
+ <dimen name="tri_state_middle_dialog_position">296.0px</dimen>
+ <dimen name="tri_state_middle_dialog_position_l">270.375px</dimen>
+ <dimen name="tri_state_up_dialog_position">165.0px</dimen>
+ <item type="dimen" name="tri_state_up_dialog_position_deep">@dimen/tri_state_down_dialog_padding_edge_deep</item>
+ <item type="dimen" name="tri_state_up_dialog_position_deep_land">@dimen/tri_state_down_dialog_padding_edge_deep</item>
+ <dimen name="tri_state_up_dialog_position_l">270.375px</dimen>
+ <dimen name="tri_state_dialog_elevation">2.0dip</dimen>
+ <dimen name="tri_state_dialog_icon_out_width">126.0px</dimen>
+ <dimen name="tri_state_dialog_icon_size">63.0px</dimen>
+ <dimen name="tri_state_dialog_inner_height">126.0px</dimen>
+ <dimen name="tri_state_dialog_padding">14.0px</dimen>
+ <dimen name="tri_state_dialog_text_size">34.125px</dimen>
+ <dimen name="tri_state_dialog_triangle_long">189.0px</dimen>
+ <dimen name="tri_state_dialog_triangle_short">63.0px</dimen>
+ <dimen name="tri_state_down_bottom_left_radius">63.0px</dimen>
+ <dimen name="tri_state_down_bottom_right_radius">63.0px</dimen>
+ <dimen name="tri_state_down_top_left_radius">63.0px</dimen>
+ <dimen name="tri_state_down_top_right_radius">0.0px</dimen>
+ <dimen name="tri_state_mid_bottom_left_radius">63.0px</dimen>
+ <dimen name="tri_state_mid_bottom_right_radius">63.0px</dimen>
+ <dimen name="tri_state_mid_top_left_radius">63.0px</dimen>
+ <dimen name="tri_state_mid_top_right_radius">63.0px</dimen>
+ <dimen name="tri_state_up_bottom_left_radius">63.0px</dimen>
+ <dimen name="tri_state_up_bottom_right_radius">0.0px</dimen>
+ <dimen name="tri_state_up_top_left_radius">63.0px</dimen>
+ <dimen name="tri_state_up_top_right_radius">63.0px</dimen>
+
+</resources>
diff --git a/packages/SystemUI/res/values/pa_styles.xml b/packages/SystemUI/res/values/pa_styles.xml
new file mode 100644
index 000000000000..de7ddeefdfe8
--- /dev/null
+++ b/packages/SystemUI/res/values/pa_styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2014-2020 Paranoid Android
+
+ 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.
+-->
+<resources>
+
+ <style name="TriStateUiText">
+ <item name="android:textSize">11.0sp</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
+ </style>
+
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java
new file mode 100644
index 000000000000..bc9c438dd37b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 CypherOS
+ * Copyright 2014-2020 Paranoid Android
+ *
+ * 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.tristate;
+
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.VolumeDialog.Callback;
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+@DependsOn(target = Callback.class)
+@ProvidesInterface(action = "com.android.systemui.action.PLUGIN_TRI_STATE_UI", version = 1)
+public interface TriStateUiController extends Plugin {
+
+ public interface UserActivityListener {
+ void onTriStateUserActivity();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java
new file mode 100644
index 000000000000..9419b673fc6e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2019 CypherOS
+ * Copyright 2014-2020 Paranoid Android
+ *
+ * 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.tristate;
+
+import static android.view.Surface.ROTATION_90;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.ColorDrawable;
+import android.hardware.display.DisplayManagerGlobal;
+import android.media.AudioManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Display;
+import android.view.OrientationEventListener;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager.LayoutParams;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.tristate.TriStateUiController;
+import com.android.systemui.tristate.TriStateUiController.UserActivityListener;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.VolumeDialogController.Callbacks;
+import com.android.systemui.plugins.VolumeDialogController.State;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+
+public class TriStateUiControllerImpl implements ConfigurationListener, TriStateUiController {
+
+ private static String TAG = "TriStateUiControllerImpl";
+
+ private static final int MSG_DIALOG_SHOW = 1;
+ private static final int MSG_DIALOG_DISMISS = 2;
+ private static final int MSG_RESET_SCHEDULE = 3;
+ private static final int MSG_STATE_CHANGE = 4;
+
+ private static final int MODE_NORMAL = AudioManager.RINGER_MODE_NORMAL;
+ private static final int MODE_SILENT = AudioManager.RINGER_MODE_SILENT;
+ private static final int MODE_VIBRATE = AudioManager.RINGER_MODE_VIBRATE;
+
+ private static final int TRI_STATE_UI_POSITION_LEFT = 0;
+ private static final int TRI_STATE_UI_POSITION_RIGHT = 1;
+
+ private static final int DIALOG_TIMEOUT = 2000;
+
+ private Context mContext;
+ private final VolumeDialogController mVolumeDialogController;
+ private final Callbacks mVolumeDialogCallback = new Callbacks() {
+ @Override
+ public void onShowRequested(int reason) { }
+
+ @Override
+ public void onDismissRequested(int reason) { }
+
+ @Override
+ public void onScreenOff() { }
+
+ @Override
+ public void onStateChanged(State state) { }
+
+ @Override
+ public void onLayoutDirectionChanged(int layoutDirection) { }
+
+ @Override
+ public void onShowVibrateHint() { }
+
+ @Override
+ public void onShowSilentHint() { }
+
+ @Override
+ public void onShowSafetyWarning(int flags) { }
+
+ @Override
+ public void onAccessibilityModeChanged(Boolean showA11yStream) { }
+
+ @Override
+ public void onCaptionComponentStateChanged(
+ Boolean isComponentEnabled, Boolean fromTooltip) {}
+
+ @Override
+ public void onConfigurationChanged() {
+ updateTheme();
+ updateTriStateLayout();
+ }
+ };
+
+ private int mDensity;
+ private Dialog mDialog;
+ private int mDialogPosition;
+ private ViewGroup mDialogView;
+ private final H mHandler;
+ private UserActivityListener mListener;
+ OrientationEventListener mOrientationListener;
+ private int mOrientationType = 0;
+ private boolean mShowing = false;
+ private int mBackgroundColor = 0;
+ private int mThemeMode = 0;
+ private int mIconColor = 0;
+ private int mTextColor = 0;
+ private ImageView mTriStateIcon;
+ private TextView mTriStateText;
+ private int mTriStateMode = -1;
+ private Window mWindow;
+ private LayoutParams mWindowLayoutParams;
+ private int mWindowType;
+
+ private final BroadcastReceiver mRingerStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateRingerModeChanged();
+ }
+ };
+
+ private final class H extends Handler {
+ private TriStateUiControllerImpl mUiController;
+
+ public H(TriStateUiControllerImpl uiController) {
+ super(Looper.getMainLooper());
+ mUiController = uiController;
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_DIALOG_SHOW:
+ mUiController.handleShow();
+ return;
+ case MSG_DIALOG_DISMISS:
+ mUiController.handleDismiss();
+ return;
+ case MSG_RESET_SCHEDULE:
+ mUiController.handleResetTimeout();
+ return;
+ case MSG_STATE_CHANGE:
+ mUiController.handleStateChanged();
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+ public TriStateUiControllerImpl(Context context) {
+ mContext = context;
+ mHandler = new H(this);
+ mOrientationListener = new OrientationEventListener(mContext, 3) {
+ @Override
+ public void onOrientationChanged(int orientation) {
+ checkOrientationType();
+ }
+ };
+ mVolumeDialogController = (VolumeDialogController) Dependency.get(VolumeDialogController.class);
+ IntentFilter ringerChanged = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
+ mContext.registerReceiver(mRingerStateReceiver, ringerChanged);
+ }
+
+ private void checkOrientationType() {
+ Display display = DisplayManagerGlobal.getInstance().getRealDisplay(0);
+ if (display != null) {
+ int rotation = display.getRotation();
+ if (rotation != mOrientationType) {
+ mOrientationType = rotation;
+ updateTriStateLayout();
+ }
+ }
+ }
+
+ public void init(int windowType, UserActivityListener listener) {
+ mWindowType = windowType;
+ mDensity = mContext.getResources().getConfiguration().densityDpi;
+ mListener = listener;
+ ((ConfigurationController) Dependency.get(ConfigurationController.class)).addCallback(this);
+ mVolumeDialogController.addCallback(mVolumeDialogCallback, mHandler);
+ initDialog();
+ }
+
+ public void destroy() {
+ ((ConfigurationController) Dependency.get(ConfigurationController.class)).removeCallback(this);
+ mVolumeDialogController.removeCallback(mVolumeDialogCallback);
+ mContext.unregisterReceiver(mRingerStateReceiver);
+ }
+
+ private void initDialog() {
+ mDialog = new Dialog(mContext);
+ mShowing = false;
+ mWindow = mDialog.getWindow();
+ mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+ mWindow.setBackgroundDrawable(new ColorDrawable(0));
+ mWindow.clearFlags(LayoutParams.FLAG_DIM_BEHIND);
+ mWindow.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE
+ | LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ mDialog.setCanceledOnTouchOutside(false);
+ mWindowLayoutParams = mWindow.getAttributes();
+ mWindowLayoutParams.type = mWindowType;
+ mWindowLayoutParams.format = -3;
+ mWindowLayoutParams.setTitle(TriStateUiControllerImpl.class.getSimpleName());
+ mWindowLayoutParams.gravity = 53;
+ mWindowLayoutParams.y = mDialogPosition;
+ mWindow.setAttributes(mWindowLayoutParams);
+ mWindow.setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+ mDialog.setContentView(R.layout.tri_state_dialog);
+ mDialogView = (ViewGroup) mDialog.findViewById(R.id.tri_state_layout);
+ mTriStateIcon = (ImageView) mDialog.findViewById(R.id.tri_state_icon);
+ mTriStateText = (TextView) mDialog.findViewById(R.id.tri_state_text);
+ updateTheme();
+ }
+
+ public void show() {
+ mHandler.obtainMessage(MSG_DIALOG_SHOW, 0, 0).sendToTarget();
+ }
+
+ private void registerOrientationListener(boolean enable) {
+ if (mOrientationListener.canDetectOrientation() && enable) {
+ Log.v(TAG, "Can detect orientation");
+ mOrientationListener.enable();
+ return;
+ }
+ Log.v(TAG, "Cannot detect orientation");
+ mOrientationListener.disable();
+ }
+
+ private void updateTriStateLayout() {
+ if (mContext != null) {
+ int iconId = 0;
+ int textId = 0;
+ int bg = 0;
+ Resources res = mContext.getResources();
+ if (res != null) {
+ int positionY;
+ int positionY2 = mWindowLayoutParams.y;
+ int positionX = mWindowLayoutParams.x;
+ int gravity = mWindowLayoutParams.gravity;
+ switch (mTriStateMode) {
+ case MODE_SILENT:
+ iconId = R.drawable.ic_volume_ringer_mute;
+ textId = R.string.volume_ringer_status_silent;
+ break;
+ case MODE_VIBRATE:
+ iconId = R.drawable.ic_volume_ringer_vibrate;
+ textId = R.string.volume_ringer_status_vibrate;
+ break;
+ case MODE_NORMAL:
+ iconId = R.drawable.ic_volume_ringer;
+ textId = R.string.volume_ringer_status_normal;
+ break;
+ }
+ int triStatePos = res.getInteger(com.android.internal.R.integer.config_alertSliderLocation);
+ boolean isTsKeyRight = true;
+ if (triStatePos == TRI_STATE_UI_POSITION_LEFT) {
+ isTsKeyRight = false;
+ } else if (triStatePos == TRI_STATE_UI_POSITION_RIGHT) {
+ isTsKeyRight = true;
+ }
+ switch (mOrientationType) {
+ case ROTATION_90:
+ if (isTsKeyRight) {
+ gravity = 51;
+ } else {
+ gravity = 83;
+ }
+ positionY2 = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_deep_land);
+ if (isTsKeyRight) {
+ positionY2 += res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+ if (mTriStateMode == MODE_SILENT) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_l);
+ } else if (mTriStateMode == MODE_VIBRATE) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_middle_dialog_position_l);
+ } else if (mTriStateMode == MODE_NORMAL) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_down_dialog_position_l);
+ }
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ break;
+ case ROTATION_180:
+ if (isTsKeyRight) {
+ gravity = 83;
+ } else {
+ gravity = 85;
+ }
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_deep);
+ if (mTriStateMode != MODE_SILENT) {
+ if (mTriStateMode != MODE_VIBRATE) {
+ if (mTriStateMode == MODE_NORMAL) {
+ positionY = res.getDimensionPixelSize(R.dimen.tri_state_down_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ break;
+ }
+ positionY = res.getDimensionPixelSize(R.dimen.tri_state_middle_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ } else {
+ positionY = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+ positionY2 = positionY;
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ case ROTATION_270:
+ if (isTsKeyRight) {
+ gravity = 85;
+ } else {
+ gravity = 53;
+ }
+ positionY2 = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_deep_land);
+ if (!isTsKeyRight) {
+ positionY2 += res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+ if (mTriStateMode == MODE_SILENT) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_l);
+ } else if (mTriStateMode == MODE_VIBRATE) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_middle_dialog_position_l);
+ } else if (mTriStateMode == MODE_NORMAL) {
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_down_dialog_position_l);
+ }
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ break;
+ default:
+ if (isTsKeyRight) {
+ gravity = 53;
+ } else {
+ gravity = 51;
+ }
+ positionX = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position_deep);
+ if (mTriStateMode != MODE_SILENT) {
+ if (mTriStateMode != MODE_VIBRATE) {
+ if (mTriStateMode == MODE_NORMAL) {
+ positionY2 = res.getDimensionPixelSize(R.dimen.tri_state_down_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ bg = R.drawable.dialog_tri_state_down_bg;
+ break;
+ }
+ }
+ positionY2 = res.getDimensionPixelSize(R.dimen.tri_state_middle_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ break;
+ }
+ positionY2 = res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position) + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ bg = R.drawable.dialog_tri_state_up_bg;
+ break;
+ }
+ if (mTriStateMode != -1) {
+ if (mTriStateIcon != null) {
+ mTriStateIcon.setImageResource(iconId);
+ }
+ if (mTriStateText != null) {
+ String inputText = res.getString(textId);
+ if (inputText != null && mTriStateText.length() == inputText.length()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(inputText);
+ sb.append(" ");
+ inputText = sb.toString();
+ }
+ mTriStateText.setText(inputText);
+ }
+ if (mDialogView != null) {
+ mDialogView.setBackgroundDrawable(res.getDrawable(bg));
+ }
+ mDialogPosition = positionY2;
+ }
+ positionY = res.getDimensionPixelSize(R.dimen.tri_state_dialog_padding);
+ mWindowLayoutParams.gravity = gravity;
+ mWindowLayoutParams.y = positionY2 - positionY;
+ mWindowLayoutParams.x = positionX - positionY;
+ mWindow.setAttributes(mWindowLayoutParams);
+ handleResetTimeout();
+ }
+ }
+ }
+
+ private void updateRingerModeChanged() {
+ mHandler.obtainMessage(MSG_STATE_CHANGE, 0, 0).sendToTarget();
+ if (mTriStateMode != -1) {
+ show();
+ }
+ }
+
+ private void handleShow() {
+ mHandler.removeMessages(MSG_DIALOG_SHOW);
+ mHandler.removeMessages(MSG_DIALOG_DISMISS);
+ handleResetTimeout();
+ if (!mShowing) {
+ updateTheme();
+ registerOrientationListener(true);
+ checkOrientationType();
+ mShowing = true;
+ mDialog.show();
+ if (mListener != null) {
+ mListener.onTriStateUserActivity();
+ }
+ }
+ }
+
+ private void handleDismiss() {
+ mHandler.removeMessages(MSG_DIALOG_SHOW);
+ mHandler.removeMessages(MSG_DIALOG_DISMISS);
+ if (mShowing) {
+ registerOrientationListener(false);
+ mShowing = false;
+ mDialog.dismiss();
+ }
+ }
+
+ private void handleStateChanged() {
+ AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ int ringerMode = am.getRingerModeInternal();
+ if (ringerMode != mTriStateMode) {
+ mTriStateMode = ringerMode;
+ updateTriStateLayout();
+ if (mListener != null) {
+ mListener.onTriStateUserActivity();
+ }
+ }
+ }
+
+ public void handleResetTimeout() {
+ mHandler.removeMessages(MSG_DIALOG_DISMISS);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_DIALOG_DISMISS, MSG_RESET_SCHEDULE, 0), (long) DIALOG_TIMEOUT);
+ if (mListener != null) {
+ mListener.onTriStateUserActivity();
+ }
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ handleDismiss();
+ initDialog();
+ updateTriStateLayout();
+ }
+
+ private void updateTheme() {
+ // Todo: Add some logic to update the theme only when a new theme is applied
+ mIconColor = getAttrColor(android.R.attr.colorAccent);
+ mTextColor = getAttrColor(android.R.attr.textColorPrimary);
+ mBackgroundColor = getAttrColor(android.R.attr.colorPrimary);
+ mDialogView.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
+ mTriStateIcon.setColorFilter(mIconColor);
+ mTriStateText.setTextColor(mTextColor);
+ }
+
+ public int getAttrColor(int attr) {
+ TypedArray ta = mContext.obtainStyledAttributes(new int[]{attr});
+ int colorAccent = ta.getColor(0, 0);
+ ta.recycle();
+ return colorAccent;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 1c2a2fa53bea..c310c5c8e941 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -27,6 +27,8 @@ import android.view.WindowManager.LayoutParams;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
+import com.android.systemui.tristate.TriStateUiController;
+import com.android.systemui.tristate.TriStateUiControllerImpl;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -47,7 +49,7 @@ import javax.inject.Singleton;
*/
@Singleton
public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable,
- VolumeDialogControllerImpl.UserActivityListener{
+ VolumeDialogControllerImpl.UserActivityListener, TriStateUiController.UserActivityListener {
public static final String VOLUME_DOWN_SILENT = "sysui_volume_down_silent";
public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent";
@@ -59,6 +61,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
protected final Context mContext;
private final VolumeDialogControllerImpl mController;
+ private TriStateUiControllerImpl mTriStateController;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
| ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
@@ -78,6 +81,8 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
mKeyguardViewMediator = keyguardViewMediator;
mController = volumeDialogController;
mController.setUserActivityListener(this);
+ boolean hasAlertSlider = mContext.getResources().
+ getBoolean(com.android.internal.R.bool.config_hasAlertSlider);
// Allow plugins to reference the VolumeDialogController.
Dependency.get(PluginDependencyProvider.class)
.allowPluginDependency(VolumeDialogController.class);
@@ -90,6 +95,13 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
}
mDialog = dialog;
mDialog.init(LayoutParams.TYPE_VOLUME_OVERLAY, mVolumeDialogCallback);
+ if (hasAlertSlider) {
+ if (mTriStateController != null) {
+ mTriStateController.destroy();
+ }
+ mTriStateController = new TriStateUiControllerImpl(mContext);
+ mTriStateController.init(LayoutParams.TYPE_VOLUME_OVERLAY, this);
+ }
}).build();
applyConfiguration();
Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
@@ -178,6 +190,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
true /* onlyProvisioned */, true /* dismissShade */);
}
+ @Override
+ public void onTriStateUserActivity() {
+ onUserActivity();
+ }
+
private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() {
@Override
public void onZenSettingsClicked() {