summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Crump <chris@cypheros.co>2019-09-30 16:47:42 -0400
committeralk3pInjection <webmaster@raspii.tech>2022-02-18 09:36:24 +0800
commitbd7a90ab8ddb31a227c1fb57e46bb0cd2c3066db (patch)
treec0080c9d0388df24c3b3b858dc6231fc971d04cc
parenta6bd819ea9dad87ecfc79820498d7dc26c47aa3c (diff)
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. also squashed with the following changes: Author: Anushek Prasal <anushekprasal@gmail.com> Date: Tue Nov 12 15:41:19 2019 +0530 [aospa][quartz] SystemUI: Improve alert slider dialog - Convert px to dip - Modify the dialog to match toast - Fix positioning for OP7 Pro slider - Remove unused dimens and drawables Edit: set position values to 0 for neutrality. They should be adapted by overriding in each device tree. Change-Id: I0dfb705843f52cdea470993d05a7bdedc10750f4 Author: Pranav Vashi <neobuddy89@gmail.com> Date: Sun Feb 7 02:08:38 2021 +0530 [crdroid][11.0] AlertSlider: Prevent crash in case of incomplete broadcast * In intent extra EXTRA_SLIDER_POSITION_VALUE is not received and slider is changed, SystemUI will crash "No resource found". This patch should prevent such ice-cold havoc. Signed-off-by: Pranav Vashi <neobuddy89@gmail.com> Change-Id: Ifc21327f785959db2e7cb0d03e07c0b061dfd569 Author: idoybh <idoybh2@gmail.com> Date: Sun Aug 8 15:49:16 2021 +0200 [crdroid][11.0] AlertSlider: check for existing dialog before creating new Change-Id: I582586e54d25b668c5e51fcc92942b37bda4a014 Change-Id: Ie1954a44cc5242c95a731abd7404379ea638fe70
-rw-r--r--core/res/res/values/ice_config.xml5
-rw-r--r--core/res/res/values/ice_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_up_bg.xml29
-rw-r--r--packages/SystemUI/res/layout/tri_state_dialog.xml60
-rw-r--r--packages/SystemUI/res/values/ice_dimens.xml42
-rw-r--r--packages/SystemUI/res/values/ice_styles.xml23
-rw-r--r--packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java479
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java19
11 files changed, 746 insertions, 1 deletions
diff --git a/core/res/res/values/ice_config.xml b/core/res/res/values/ice_config.xml
index 4653c7410805..898b0692ca0f 100644
--- a/core/res/res/values/ice_config.xml
+++ b/core/res/res/values/ice_config.xml
@@ -54,4 +54,9 @@
<string name="alert_slider_state_path" translatable="false"></string>
<string name="alert_slider_uevent_match_path" translatable="false"></string>
+ <!-- The location of the device's alert slider:
+ 0: Left side
+ 1: Right side -->
+ <integer name="config_alertSliderLocation">0</integer>
+
</resources>
diff --git a/core/res/res/values/ice_symbols.xml b/core/res/res/values/ice_symbols.xml
index b1978e66f339..a0fe829a1df5 100644
--- a/core/res/res/values/ice_symbols.xml
+++ b/core/res/res/values/ice_symbols.xml
@@ -37,5 +37,6 @@
<java-symbol type="bool" name="config_hasAlertSlider" />
<java-symbol type="string" name="alert_slider_state_path" />
<java-symbol type="string" name="alert_slider_uevent_match_path" />
+ <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_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..cf3890d59a88
--- /dev/null
+++ b/packages/SystemUI/res/layout/tri_state_dialog.xml
@@ -0,0 +1,60 @@
+<?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="48.0dip"
+ android:translationZ="@dimen/tri_state_dialog_elevation">
+
+ <FrameLayout
+ android:layout_width="54.0dip"
+ android:layout_height="fill_parent">
+
+ <ImageView
+ android:layout_gravity="center"
+ android:id="@+id/tri_state_icon"
+ android:layout_marginLeft="2.0dip"
+ android:layout_width="@dimen/tri_state_dialog_icon_size"
+ android:layout_height="@dimen/tri_state_dialog_icon_size" />
+ </FrameLayout>
+
+ <TextView
+ android:gravity="center_vertical"
+ android:id="@+id/tri_state_text"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ style="@style/TriStateUiText" />
+
+ <FrameLayout
+ android:layout_width="18.0dip"
+ android:layout_height="fill_parent" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/ice_dimens.xml b/packages/SystemUI/res/values/ice_dimens.xml
new file mode 100644
index 000000000000..f81dc4ae7797
--- /dev/null
+++ b/packages/SystemUI/res/values/ice_dimens.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 Project ICE
+
+ 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">
+ <!-- Alert Slider -->
+ <dimen name="tri_state_down_dialog_position">0px</dimen>
+ <dimen name="tri_state_down_dialog_position_l">0px</dimen>
+ <dimen name="tri_state_middle_dialog_position">0px</dimen>
+ <dimen name="tri_state_middle_dialog_position_l">0px</dimen>
+ <dimen name="tri_state_up_dialog_position">0px</dimen>
+ <dimen name="tri_state_up_dialog_position_l">0px</dimen>
+ <dimen name="tri_state_up_dialog_position_deep">0px</dimen>
+ <dimen name="tri_state_up_dialog_position_deep_land">0px</dimen>
+ <dimen name="tri_state_dialog_elevation">4.0dip</dimen>
+ <dimen name="tri_state_dialog_icon_size">24.0dip</dimen>
+ <dimen name="tri_state_dialog_padding">8.0dip</dimen>
+ <dimen name="tri_state_down_bottom_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_down_bottom_right_radius">24.0dip</dimen>
+ <dimen name="tri_state_down_top_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_down_top_right_radius">0.0dip</dimen>
+ <dimen name="tri_state_mid_bottom_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_mid_bottom_right_radius">24.0dip</dimen>
+ <dimen name="tri_state_mid_top_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_mid_top_right_radius">24.0dip</dimen>
+ <dimen name="tri_state_up_bottom_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_up_bottom_right_radius">0.0dip</dimen>
+ <dimen name="tri_state_up_top_left_radius">24.0dip</dimen>
+ <dimen name="tri_state_up_top_right_radius">24.0dip</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values/ice_styles.xml b/packages/SystemUI/res/values/ice_styles.xml
new file mode 100644
index 000000000000..652258a68746
--- /dev/null
+++ b/packages/SystemUI/res/values/ice_styles.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 Project ICE
+
+ 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>
+ <!-- Alert Slider -->
+ <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..5fed8858c34d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 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..098f0c474ab8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2019 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() {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ 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 && iconId != 0) {
+ mTriStateIcon.setImageResource(iconId);
+ }
+ if (mTriStateText != null && textId != 0) {
+ 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 && bg != 0) {
+ 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 56f1c092efd9..72f50bfb1c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -37,6 +37,8 @@ import com.android.systemui.plugins.VolumeDialog;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.tristate.TriStateUiController;
+import com.android.systemui.tristate.TriStateUiControllerImpl;
import com.android.systemui.tuner.TunerService;
import java.io.FileDescriptor;
@@ -51,7 +53,7 @@ import javax.inject.Inject;
*/
@SysUISingleton
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";
@@ -63,6 +65,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);
@@ -85,6 +88,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);
@@ -97,6 +102,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,
@@ -193,6 +205,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() {