summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorChris Crump <chris@cypheros.co>2019-09-30 16:47:42 -0400
committeralk3pInjection <webmaster@raspii.tech>2022-05-07 00:20:58 +0800
commit0e4ee09469f6452b576cea4e0ce8f57529d6c2d4 (patch)
tree717a3145eddb9f028da8bef91d5343cbfb128d09 /packages
parentb56b36abbdc4f34a924d106c0b954efb5d52bc3d (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 Author: alk3pInjection <webmaster@raspii.tech> Date: Sun Sep 5 22:46:40 2021 +0800 AlertSlider: Fix bad layout under 180° rotation * silly but it works Change-Id: I0c32980b9380cd5fc8b8204440ea93d73c6aabc4 Author: LibXZR <i@xzr.moe> Date: Fri Apr 8 22:56:39 2022 +0800 TriStateUi: Adapt new status bar height api com.android.internal.R.dimen.status_bar_height is no longer returning correct value due to api change. Change-Id: I5973de93ab237764fe5ea4baa8a2fd3a9598d2d0 Signed-off-by: LibXZR <i@xzr.moe> Change-Id: Ie1954a44cc5242c95a731abd7404379ea638fe70
Diffstat (limited to 'packages')
-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.java503
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java19
9 files changed, 764 insertions, 1 deletions
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..49b62f7cecbe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java
@@ -0,0 +1,503 @@
+/*
+ * 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.internal.policy.SystemBarUtils;
+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 += SystemBarUtils.getStatusBarHeight(mContext);
+ }
+ 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);
+ positionY2 = SystemBarUtils.getStatusBarHeight(mContext);
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ if (mTriStateMode != MODE_SILENT) {
+ if (mTriStateMode != MODE_VIBRATE) {
+ if (mTriStateMode == MODE_NORMAL) {
+ positionY2 += res.getDimensionPixelSize(
+ R.dimen.tri_state_down_dialog_position);
+ break;
+ }
+ }
+ positionY2 += res.getDimensionPixelSize(
+ R.dimen.tri_state_middle_dialog_position);
+ break;
+ }
+ positionY2 += res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position);
+ break;
+ 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 += SystemBarUtils.getStatusBarHeight(mContext);
+ }
+ 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)
+ + SystemBarUtils.getStatusBarHeight(mContext);
+ bg = R.drawable.dialog_tri_state_down_bg;
+ break;
+ }
+ }
+ positionY2 = res.getDimensionPixelSize(
+ R.dimen.tri_state_middle_dialog_position)
+ + SystemBarUtils.getStatusBarHeight(mContext);
+ bg = R.drawable.dialog_tri_state_middle_bg;
+ break;
+ }
+ positionY2 = res.getDimensionPixelSize(
+ R.dimen.tri_state_up_dialog_position)
+ + SystemBarUtils.getStatusBarHeight(mContext);
+ 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 c083c14a3730..2fb0f2286092 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -35,6 +35,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;
@@ -49,7 +51,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";
@@ -61,6 +63,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);
@@ -90,6 +93,8 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
mActivityStarter = activityStarter;
mController = volumeDialogController;
mController.setUserActivityListener(this);
+ boolean hasAlertSlider = mContext.getResources().
+ getBoolean(com.android.internal.R.bool.config_hasAlertSlider);
// Allow plugins to reference the VolumeDialogController.
pluginDependencyProvider.allowPluginDependency(VolumeDialogController.class);
extensionController.newExtension(VolumeDialog.class)
@@ -101,6 +106,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();
tunerService.addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
@@ -188,6 +200,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
mActivityStarter.startActivity(intent, true /* onlyProvisioned */, true /* dismissShade */);
}
+ @Override
+ public void onTriStateUserActivity() {
+ onUserActivity();
+ }
+
private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() {
@Override
public void onZenSettingsClicked() {