Merge "Volume dialog: Add zen mode icons and notification access." into lmp-mr1-dev

This commit is contained in:
John Spurlock
2014-11-10 14:08:51 +00:00
committed by Android (Google) Code Review
34 changed files with 318 additions and 345 deletions

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_quad"
android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@integer/zen_toast_animation_duration" />

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad"
android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@integer/zen_toast_animation_duration" />

View File

@@ -17,7 +17,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/white"/> <item android:state_selected="true" android:color="@color/segmented_button_selected"/>
<item android:color="@color/segmented_button_text_inactive"/> <item android:color="@color/segmented_button_unselected"/>
</selector> </selector>

View File

@@ -16,6 +16,10 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android" <ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight"> android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask" <item android:id="@android:id/mask">
android:drawable="@android:color/white" /> <shape>
<corners android:radius="@dimen/borderless_button_radius" />
<solid android:color="@android:color/white" />
</shape>
</item>
</ripple> </ripple>

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32.0dp" android:width="28.0dp"
android:height="32.0dp" android:height="28.0dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">
<path <path

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32.0dp" android:width="28.0dp"
android:height="32.0dp" android:height="28.0dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">
<path <path

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M26.0,11.8l3.8,3.8l-3.2,3.2l2.8,2.8l6.0,-6.0L24.0,4.2l-2.0,0.0l0.0,10.1l4.0,4.0L26.0,11.8zM10.8,8.2L8.0,11.0l13.2,13.2L10.0,35.3l2.8,2.8L22.0,29.0l0.0,15.2l2.0,0.0l8.6,-8.6l4.6,4.6l2.8,-2.8L10.8,8.2zM26.0,36.5L26.0,29.0l3.8,3.8L26.0,36.5z"/>
</vector>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2014, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@*android:drawable/ic_audio_phone_am_alpha"
android:autoMirrored="true"
android:tint="#ffffffff" />

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32.0dp" android:width="28.0dp"
android:height="32.0dp" android:height="28.0dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">
<path <path

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32.0dp" android:width="28.0dp"
android:height="32.0dp" android:height="28.0dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">
<path <path

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="28dp"
android:height="32dp" android:height="28dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="28dp"
android:height="32dp" android:height="28dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">
<path <path

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="28dp"
android:height="32dp" android:height="28dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="18dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.6,3.6L5.2,2.2C2.8,4.0 1.2,6.8 1.0,10.0l2.0,0.0C3.2,7.3 4.5,5.0 6.6,3.6zM20.0,10.0l2.0,0.0c-0.2,-3.2 -1.7,-6.0 -4.1,-7.8l-1.4,1.4C18.5,5.0 19.8,7.3 20.0,10.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0l-2.0,-2.0L18.0,10.5zM11.5,22.0c0.1,0.0 0.3,0.0 0.4,0.0c0.7,-0.1 1.2,-0.6 1.4,-1.2c0.1,-0.2 0.2,-0.5 0.2,-0.8l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0z"/>
</vector>

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="18dp"
android:height="32dp" android:height="18dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">

View File

@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License. limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="18dp"
android:height="32dp" android:height="18dp"
android:viewportWidth="48.0" android:viewportWidth="48.0"
android:viewportHeight="48.0"> android:viewportHeight="48.0">

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/system_primary_color" />
<corners android:radius="@dimen/notification_material_rounded_rect_radius" />
</shape>

View File

@@ -19,8 +19,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/segmented_button_spacing" android:layout_marginStart="@dimen/segmented_button_spacing"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal|top"
android:textColor="@color/segmented_button_text_selector" android:textColor="@color/segmented_button_text_selector"
android:background="@drawable/btn_borderless_rect" android:background="@drawable/btn_borderless_rect"
android:textAppearance="@style/TextAppearance.QS.SegmentedButton" android:textAppearance="@style/TextAppearance.QS.SegmentedButton"
android:minHeight="36dp" android:minHeight="64dp"
android:padding="4dp" /> android:paddingTop="11dp"
android:drawablePadding="6dp" />

View File

@@ -55,4 +55,20 @@
android:paddingTop="0dp" /> android:paddingTop="0dp" />
</FrameLayout> </FrameLayout>
<View
android:id="@+id/divider"
android:layout_width="1dp"
android:layout_height="32dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="@color/volume_panel_divider" />
<ImageView
android:id="@+id/secondary_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:scaleType="center"
android:background="@drawable/btn_borderless_rect"
android:contentDescription="@null" />
</LinearLayout> </LinearLayout>

View File

@@ -25,7 +25,7 @@
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="12dp" android:minHeight="8dp"
android:elevation="4dp" android:elevation="4dp"
android:background="@drawable/qs_background_secondary" > android:background="@drawable/qs_background_secondary" >
@@ -33,9 +33,8 @@
android:id="@+id/zen_buttons" android:id="@+id/zen_buttons"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/qs_panel_padding" android:layout_marginLeft="8dp"
android:layout_marginRight="@dimen/qs_panel_padding" android:layout_marginRight="8dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:clipChildren="false" /> android:clipChildren="false" />
</FrameLayout> </FrameLayout>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/zen_toast_background"
android:translationZ="@dimen/volume_panel_z"
android:padding="18dp"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageView
android:id="@android:id/icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:scaleType="center" />
<TextView
android:id="@android:id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:lineSpacingExtra="4dp"
android:gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.QS.ZenToast" />
</LinearLayout>

View File

@@ -101,8 +101,6 @@
<!-- The color of the circle around the primary user in the user switcher --> <!-- The color of the circle around the primary user in the user switcher -->
<color name="current_user_border_color">@color/system_accent_color</color> <color name="current_user_border_color">@color/system_accent_color</color>
<color name="segmented_button_text_inactive">#99afbdc4</color><!-- 60% -->
<!-- The "inside" of a notification, reached via longpress --> <!-- The "inside" of a notification, reached via longpress -->
<color name="notification_guts_bg_color">@color/system_secondary_color</color> <color name="notification_guts_bg_color">@color/system_secondary_color</color>
<color name="notification_guts_title_color">#FFFFFFFF</color> <color name="notification_guts_title_color">#FFFFFFFF</color>
@@ -124,9 +122,11 @@
<!-- Shadow color for the furthest pixels around the fake shadow for recents. --> <!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
<color name="fake_shadow_end_color">#03000000</color> <color name="fake_shadow_end_color">#03000000</color>
<!-- 25% deep teal 200 --> <color name="screen_pinning_nav_icon_highlight_outer">#4080cbc4</color><!-- 25% deep teal 200 -->
<color name="screen_pinning_nav_icon_highlight_outer">#4080cbc4</color> <color name="screen_pinning_request_bg">#ff009688</color><!-- deep teal 500 -->
<!-- deep teal 500 -->
<color name="screen_pinning_request_bg">#ff009688</color>
<color name="screen_pinning_request_window_bg">#80000000</color> <color name="screen_pinning_request_window_bg">#80000000</color>
<color name="segmented_button_selected">#FFFFFFFF</color>
<color name="segmented_button_unselected">#B3B0BEC5</color><!-- 70% blue grey 200 -->
<color name="volume_panel_divider">#1FFFFFFF</color><!-- 12% white -->
</resources> </resources>

View File

@@ -250,12 +250,6 @@
<!-- Number of times to show the strong alarm warning text in the volume dialog --> <!-- Number of times to show the strong alarm warning text in the volume dialog -->
<integer name="zen_mode_alarm_warning_threshold">5</integer> <integer name="zen_mode_alarm_warning_threshold">5</integer>
<!-- Zen toast fade in/out duration -->
<integer name="zen_toast_animation_duration">500</integer>
<!-- Zen toast visibility duration -->
<integer name="zen_toast_visible_duration">500</integer>
<!-- Enable the default volume dialog --> <!-- Enable the default volume dialog -->
<bool name="enable_volume_ui">true</bool> <bool name="enable_volume_ui">true</bool>
</resources> </resources>

View File

@@ -191,17 +191,14 @@
<dimen name="qs_data_usage_text_size">14sp</dimen> <dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen> <dimen name="qs_data_usage_usage_text_size">36sp</dimen>
<dimen name="segmented_button_spacing">4dp</dimen> <dimen name="segmented_button_spacing">8dp</dimen>
<dimen name="segmented_button_radius">2dp</dimen> <dimen name="borderless_button_radius">2dp</dimen>
<!-- How far the expanded QS panel peeks from the header in collapsed state. --> <!-- How far the expanded QS panel peeks from the header in collapsed state. -->
<dimen name="qs_peek_height">8dp</dimen> <dimen name="qs_peek_height">8dp</dimen>
<dimen name="zen_mode_condition_detail_button_padding">8dp</dimen> <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
<!-- Explicit width of the zen toast window -->
<dimen name="zen_toast_width">224dp</dimen>
<!-- used by DessertCase --> <!-- used by DessertCase -->
<dimen name="dessert_case_cell_size">192dp</dimen> <dimen name="dessert_case_cell_size">192dp</dimen>

View File

@@ -167,14 +167,8 @@
<item name="android:textColor">@color/qs_subhead</item> <item name="android:textColor">@color/qs_subhead</item>
</style> </style>
<style name="TextAppearance.QS.ZenToast">
<item name="android:textSize">14sp</item>
</style>
<style name="TextAppearance.QS.SegmentedButton"> <style name="TextAppearance.QS.SegmentedButton">
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style> </style>
<style name="TextAppearance.QS.DataUsage"> <style name="TextAppearance.QS.DataUsage">
@@ -266,9 +260,4 @@
<style name="UserDetailView"> <style name="UserDetailView">
<item name="numColumns">3</item> <item name="numColumns">3</item>
</style> </style>
<style name="ZenToastAnimations">
<item name="android:windowEnterAnimation">@anim/zen_toast_enter</item>
<item name="android:windowExitAnimation">@anim/zen_toast_exit</item>
</style>
</resources> </resources>

View File

@@ -32,4 +32,5 @@ public interface DemoMode {
public static final String COMMAND_BARS = "bars"; public static final String COMMAND_BARS = "bars";
public static final String COMMAND_STATUS = "status"; public static final String COMMAND_STATUS = "status";
public static final String COMMAND_NOTIFICATIONS = "notifications"; public static final String COMMAND_NOTIFICATIONS = "notifications";
public static final String COMMAND_VOLUME = "volume";
} }

View File

@@ -3444,6 +3444,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
dispatchDemoCommand(COMMAND_ENTER, new Bundle()); dispatchDemoCommand(COMMAND_ENTER, new Bundle());
} }
boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT);
if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) {
mVolumeComponent.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_CLOCK)) { if (modeChange || command.equals(COMMAND_CLOCK)) {
dispatchDemoCommandToView(command, args, R.id.clock); dispatchDemoCommandToView(command, args, R.id.clock);
} }

View File

@@ -17,7 +17,6 @@
package com.android.systemui.volume; package com.android.systemui.volume;
import android.content.Context; import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -30,8 +29,6 @@ import com.android.systemui.R;
import java.util.Objects; import java.util.Objects;
public class SegmentedButtons extends LinearLayout { public class SegmentedButtons extends LinearLayout {
private static final Typeface MEDIUM = Typeface.create("sans-serif-medium", Typeface.NORMAL);
private static final Typeface BOLD = Typeface.create("sans-serif", Typeface.BOLD);
private static final int LABEL_RES_KEY = R.id.label; private static final int LABEL_RES_KEY = R.id.label;
private final Context mContext; private final Context mContext;
@@ -63,15 +60,17 @@ public class SegmentedButtons extends LinearLayout {
final Object tag = c.getTag(); final Object tag = c.getTag();
final boolean selected = Objects.equals(mSelectedValue, tag); final boolean selected = Objects.equals(mSelectedValue, tag);
c.setSelected(selected); c.setSelected(selected);
c.setTypeface(selected ? BOLD : MEDIUM); c.getCompoundDrawables()[1].setTint(mContext.getResources().getColor(selected
? R.color.segmented_button_selected : R.color.segmented_button_unselected));
} }
fireOnSelected(); fireOnSelected();
} }
public void addButton(int labelResId, Object value) { public void addButton(int labelResId, int iconResId, Object value) {
final Button b = (Button) mInflater.inflate(R.layout.segmented_button, this, false); final Button b = (Button) mInflater.inflate(R.layout.segmented_button, this, false);
b.setTag(LABEL_RES_KEY, labelResId); b.setTag(LABEL_RES_KEY, labelResId);
b.setText(labelResId); b.setText(labelResId);
b.setCompoundDrawablesWithIntrinsicBounds(0, iconResId, 0, 0);
final LayoutParams lp = (LayoutParams) b.getLayoutParams(); final LayoutParams lp = (LayoutParams) b.getLayoutParams();
if (getChildCount() == 0) { if (getChildCount() == 0) {
lp.leftMargin = lp.rightMargin = 0; // first button has no margin lp.leftMargin = lp.rightMargin = 0; // first button has no margin

View File

@@ -16,8 +16,9 @@
package com.android.systemui.volume; package com.android.systemui.volume;
import com.android.systemui.DemoMode;
import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeController;
public interface VolumeComponent { public interface VolumeComponent extends DemoMode {
ZenModeController getZenController(); ZenModeController getZenController();
} }

View File

@@ -16,6 +16,9 @@
package com.android.systemui.volume; package com.android.systemui.volume;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -42,6 +45,8 @@ import android.media.VolumeProvider;
import android.media.session.MediaController; import android.media.session.MediaController;
import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaController.PlaybackInfo;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@@ -59,12 +64,15 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView; import android.widget.TextView;
import com.android.internal.R; import com.android.internal.R;
import com.android.systemui.DemoMode;
import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeController;
@@ -76,7 +84,7 @@ import java.io.PrintWriter;
* *
* @hide * @hide
*/ */
public class VolumePanel extends Handler { public class VolumePanel extends Handler implements DemoMode {
private static final String TAG = "VolumePanel"; private static final String TAG = "VolumePanel";
private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
@@ -129,6 +137,8 @@ public class VolumePanel extends Handler {
private static final int IC_AUDIO_VOL = com.android.systemui.R.drawable.ic_audio_vol; private static final int IC_AUDIO_VOL = com.android.systemui.R.drawable.ic_audio_vol;
private static final int IC_AUDIO_VOL_MUTE = com.android.systemui.R.drawable.ic_audio_vol_mute; private static final int IC_AUDIO_VOL_MUTE = com.android.systemui.R.drawable.ic_audio_vol_mute;
private static final int IC_AUDIO_BT = com.android.systemui.R.drawable.ic_audio_bt;
private static final int IC_AUDIO_BT_MUTE = com.android.systemui.R.drawable.ic_audio_bt_mute;
private final String mTag; private final String mTag;
protected final Context mContext; protected final Context mContext;
@@ -142,6 +152,7 @@ public class VolumePanel extends Handler {
private float mDisabledAlpha; private float mDisabledAlpha;
private int mLastRingerMode = AudioManager.RINGER_MODE_NORMAL; private int mLastRingerMode = AudioManager.RINGER_MODE_NORMAL;
private int mLastRingerProgress = 0; private int mLastRingerProgress = 0;
private int mDemoIcon;
// True if we want to play tones on the system stream when the master stream is specified. // True if we want to play tones on the system stream when the master stream is specified.
private final boolean mPlayMasterStreamTones; private final boolean mPlayMasterStreamTones;
@@ -166,12 +177,13 @@ public class VolumePanel extends Handler {
/** All the slider controls mapped by stream type */ /** All the slider controls mapped by stream type */
private SparseArray<StreamControl> mStreamControls; private SparseArray<StreamControl> mStreamControls;
private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager;
private final SecondaryIconTransition mSecondaryIconTransition;
private enum StreamResources { private enum StreamResources {
BluetoothSCOStream(AudioManager.STREAM_BLUETOOTH_SCO, BluetoothSCOStream(AudioManager.STREAM_BLUETOOTH_SCO,
R.string.volume_icon_description_bluetooth, R.string.volume_icon_description_bluetooth,
R.drawable.ic_audio_bt, IC_AUDIO_BT,
R.drawable.ic_audio_bt, IC_AUDIO_BT_MUTE,
false), false),
RingerStream(AudioManager.STREAM_RING, RingerStream(AudioManager.STREAM_RING,
R.string.volume_icon_description_ringer, R.string.volume_icon_description_ringer,
@@ -180,8 +192,8 @@ public class VolumePanel extends Handler {
false), false),
VoiceStream(AudioManager.STREAM_VOICE_CALL, VoiceStream(AudioManager.STREAM_VOICE_CALL,
R.string.volume_icon_description_incall, R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone, com.android.systemui.R.drawable.ic_audio_phone,
R.drawable.ic_audio_phone, com.android.systemui.R.drawable.ic_audio_phone,
false), false),
AlarmStream(AudioManager.STREAM_ALARM, AlarmStream(AudioManager.STREAM_ALARM,
R.string.volume_alarm, R.string.volume_alarm,
@@ -246,6 +258,8 @@ public class VolumePanel extends Handler {
ImageView icon; ImageView icon;
SeekBar seekbarView; SeekBar seekbarView;
TextView suppressorView; TextView suppressorView;
View divider;
ImageView secondaryIcon;
int iconRes; int iconRes;
int iconMuteRes; int iconMuteRes;
int iconSuppressedRes; int iconSuppressedRes;
@@ -339,6 +353,7 @@ public class VolumePanel extends Handler {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAccessibilityManager = (AccessibilityManager) context.getSystemService( mAccessibilityManager = (AccessibilityManager) context.getSystemService(
Context.ACCESSIBILITY_SERVICE); Context.ACCESSIBILITY_SERVICE);
mSecondaryIconTransition = new SecondaryIconTransition();
// For now, only show master volume if master volume is supported // For now, only show master volume if master volume is supported
final Resources res = context.getResources(); final Resources res = context.getResources();
@@ -381,6 +396,8 @@ public class VolumePanel extends Handler {
mActiveStreamType = -1; mActiveStreamType = -1;
mAudioManager.forceVolumeControlStream(mActiveStreamType); mAudioManager.forceVolumeControlStream(mActiveStreamType);
setZenPanelVisible(false); setZenPanelVisible(false);
mDemoIcon = 0;
mSecondaryIconTransition.cancel();
} }
}); });
@@ -604,10 +621,12 @@ public class VolumePanel extends Handler {
mStreamControls = new SparseArray<StreamControl>(STREAMS.length); mStreamControls = new SparseArray<StreamControl>(STREAMS.length);
final StreamResources notificationStream = StreamResources.NotificationStream;
for (int i = 0; i < STREAMS.length; i++) { for (int i = 0; i < STREAMS.length; i++) {
StreamResources streamRes = STREAMS[i]; StreamResources streamRes = STREAMS[i];
final int streamType = streamRes.streamType; final int streamType = streamRes.streamType;
final boolean isNotification = isNotificationOrRing(streamType);
final StreamControl sc = new StreamControl(); final StreamControl sc = new StreamControl();
sc.streamType = streamType; sc.streamType = streamType;
@@ -620,8 +639,8 @@ public class VolumePanel extends Handler {
sc.iconRes = streamRes.iconRes; sc.iconRes = streamRes.iconRes;
sc.iconMuteRes = streamRes.iconMuteRes; sc.iconMuteRes = streamRes.iconMuteRes;
sc.icon.setImageResource(sc.iconRes); sc.icon.setImageResource(sc.iconRes);
sc.icon.setClickable(isNotificationOrRing(streamType)); sc.icon.setClickable(isNotification);
if (sc.icon.isClickable()) { if (isNotification) {
sc.icon.setSoundEffectsEnabled(false); sc.icon.setSoundEffectsEnabled(false);
sc.icon.setOnClickListener(new OnClickListener() { sc.icon.setOnClickListener(new OnClickListener() {
@Override @Override
@@ -636,6 +655,23 @@ public class VolumePanel extends Handler {
sc.suppressorView = sc.suppressorView =
(TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor); (TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor);
sc.suppressorView.setVisibility(View.GONE); sc.suppressorView.setVisibility(View.GONE);
final boolean showSecondary = !isNotification && notificationStream.show;
sc.divider = sc.group.findViewById(com.android.systemui.R.id.divider);
sc.secondaryIcon = (ImageView) sc.group
.findViewById(com.android.systemui.R.id.secondary_icon);
sc.secondaryIcon.setImageResource(com.android.systemui.R.drawable.ic_ringer_audible);
sc.secondaryIcon.setContentDescription(res.getString(notificationStream.descRes));
sc.secondaryIcon.setClickable(showSecondary);
sc.divider.setVisibility(showSecondary ? View.VISIBLE : View.GONE);
sc.secondaryIcon.setVisibility(showSecondary ? View.VISIBLE : View.GONE);
if (showSecondary) {
sc.secondaryIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSecondaryIconTransition.start(sc);
}
});
}
final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0; streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne); sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
@@ -696,7 +732,7 @@ public class VolumePanel extends Handler {
} }
muted = ringerMode == AudioManager.RINGER_MODE_VIBRATE; muted = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
} }
sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes); sc.icon.setImageResource(mDemoIcon != 0 ? mDemoIcon : muted ? sc.iconMuteRes : sc.iconRes);
} }
private void updateSliderSupressor(StreamControl sc) { private void updateSliderSupressor(StreamControl sc) {
@@ -800,7 +836,8 @@ public class VolumePanel extends Handler {
} }
private void updateTimeoutDelay() { private void updateTimeoutDelay() {
mTimeoutDelay = sSafetyWarning != null ? TIMEOUT_DELAY_SAFETY_WARNING mTimeoutDelay = mDemoIcon != 0 ? TIMEOUT_DELAY_EXPANDED
: sSafetyWarning != null ? TIMEOUT_DELAY_SAFETY_WARNING
: mActiveStreamType == AudioManager.STREAM_MUSIC ? TIMEOUT_DELAY_SHORT : mActiveStreamType == AudioManager.STREAM_MUSIC ? TIMEOUT_DELAY_SHORT
: mZenPanelExpanded ? TIMEOUT_DELAY_EXPANDED : mZenPanelExpanded ? TIMEOUT_DELAY_EXPANDED
: isZenPanelVisible() ? TIMEOUT_DELAY_COLLAPSED : isZenPanelVisible() ? TIMEOUT_DELAY_COLLAPSED
@@ -995,7 +1032,7 @@ public class VolumePanel extends Handler {
(AudioManager.DEVICE_OUT_BLUETOOTH_A2DP | (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) { AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute); setMusicIcon(IC_AUDIO_BT, IC_AUDIO_BT_MUTE);
} else { } else {
setMusicIcon(IC_AUDIO_VOL, IC_AUDIO_VOL_MUTE); setMusicIcon(IC_AUDIO_VOL, IC_AUDIO_VOL_MUTE);
} }
@@ -1075,6 +1112,12 @@ public class VolumePanel extends Handler {
updateSliderProgress(sc, index); updateSliderProgress(sc, index);
updateSliderEnabled(sc, isMuted(streamType), updateSliderEnabled(sc, isMuted(streamType),
(flags & AudioManager.FLAG_FIXED_VOLUME) != 0); (flags & AudioManager.FLAG_FIXED_VOLUME) != 0);
// check for secondary-icon transition completion
if (isNotificationOrRing(streamType) && mSecondaryIconTransition.isRunning()) {
mSecondaryIconTransition.cancel(); // safe to reset
sc.seekbarView.setAlpha(0); sc.seekbarView.animate().alpha(1);
mZenPanel.setAlpha(0); mZenPanel.animate().alpha(1);
}
} }
if (!isShowing()) { if (!isShowing()) {
@@ -1406,6 +1449,22 @@ public class VolumePanel extends Handler {
return mZenController; return mZenController;
} }
@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!COMMAND_VOLUME.equals(command)) return;
String icon = args.getString("icon");
final String iconMute = args.getString("iconmute");
final boolean mute = iconMute != null;
icon = mute ? iconMute : icon;
icon = icon.endsWith("Stream") ? icon : (icon + "Stream");
final StreamResources sr = StreamResources.valueOf(icon);
mDemoIcon = mute ? sr.iconMuteRes : sr.iconRes;
final int forcedStreamType = StreamResources.MediaStream.streamType;
mAudioManager.forceVolumeControlStream(forcedStreamType);
mAudioManager.adjustStreamVolume(forcedStreamType, AudioManager.ADJUST_SAME,
AudioManager.FLAG_SHOW_UI);
}
private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
@Override @Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@@ -1445,6 +1504,80 @@ public class VolumePanel extends Handler {
} }
}; };
private final class SecondaryIconTransition extends AnimatorListenerAdapter
implements Runnable {
private static final int ANIMATION_TIME = 400;
private static final int WAIT_FOR_SWITCH_TIME = 1000;
private final int mAnimationTime = (int)(ANIMATION_TIME * ValueAnimator.getDurationScale());
private final int mFadeOutTime = mAnimationTime / 2;
private final int mDelayTime = mAnimationTime / 3;
private final Interpolator mIconInterpolator =
AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_slow_in);
private StreamControl mTarget;
public void start(StreamControl sc) {
if (sc == null) throw new IllegalArgumentException();
if (mTarget != null) {
cancel();
}
mTarget = sc;
mTimeoutDelay = mAnimationTime + WAIT_FOR_SWITCH_TIME;
resetTimeout();
mTarget.secondaryIcon.setClickable(false);
final int N = mTarget.group.getChildCount();
for (int i = 0; i < N; i++) {
final View child = mTarget.group.getChildAt(i);
if (child != mTarget.secondaryIcon) {
child.animate().alpha(0).setDuration(mFadeOutTime).start();
}
}
mTarget.secondaryIcon.animate()
.translationXBy(mTarget.icon.getX() - mTarget.secondaryIcon.getX())
.setInterpolator(mIconInterpolator)
.setStartDelay(mDelayTime)
.setDuration(mAnimationTime - mDelayTime)
.setListener(this)
.start();
}
public boolean isRunning() {
return mTarget != null;
}
public void cancel() {
if (mTarget == null) return;
mTarget.secondaryIcon.setClickable(true);
final int N = mTarget.group.getChildCount();
for (int i = 0; i < N; i++) {
final View child = mTarget.group.getChildAt(i);
if (child != mTarget.secondaryIcon) {
child.animate().cancel();
child.setAlpha(1);
}
}
mTarget.secondaryIcon.animate().cancel();
mTarget.secondaryIcon.setTranslationX(0);
mTarget = null;
}
@Override
public void onAnimationEnd(Animator animation) {
if (mTarget == null) return;
AsyncTask.execute(this);
}
@Override
public void run() {
if (mTarget == null) return;
mAudioManager.forceVolumeControlStream(StreamResources.NotificationStream.streamType);
mAudioManager.adjustStreamVolume(StreamResources.NotificationStream.streamType,
AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
}
}
public interface Callback { public interface Callback {
void onZenSettings(); void onZenSettings();
void onInteraction(); void onInteraction();

View File

@@ -10,6 +10,7 @@ import android.media.session.ISessionController;
import android.media.session.MediaController; import android.media.session.MediaController;
import android.media.session.MediaSessionManager; import android.media.session.MediaSessionManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.provider.Settings; import android.provider.Settings;
@@ -184,6 +185,11 @@ public class VolumeUI extends SystemUI {
public ZenModeController getZenController() { public ZenModeController getZenController() {
return mPanel.getZenController(); return mPanel.getZenController();
} }
@Override
public void dispatchDemoCommand(String command, Bundle args) {
mPanel.dispatchDemoCommand(command, args);
}
} }
private final class RemoteVolumeController extends IRemoteVolumeController.Stub { private final class RemoteVolumeController extends IRemoteVolumeController.Stub {

View File

@@ -80,7 +80,6 @@ public class ZenModePanel extends LinearLayout {
private final Interpolator mFastOutSlowInInterpolator; private final Interpolator mFastOutSlowInInterpolator;
private final int mSubheadWarningColor; private final int mSubheadWarningColor;
private final int mSubheadColor; private final int mSubheadColor;
private final ZenToast mZenToast;
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this)); private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
@@ -115,7 +114,6 @@ public class ZenModePanel extends LinearLayout {
final Resources res = mContext.getResources(); final Resources res = mContext.getResources();
mSubheadWarningColor = res.getColor(R.color.system_warning_color); mSubheadWarningColor = res.getColor(R.color.system_warning_color);
mSubheadColor = res.getColor(R.color.qs_subhead); mSubheadColor = res.getColor(R.color.qs_subhead);
mZenToast = new ZenToast(mContext);
if (DEBUG) Log.d(mTag, "new ZenModePanel"); if (DEBUG) Log.d(mTag, "new ZenModePanel");
} }
@@ -124,10 +122,12 @@ public class ZenModePanel extends LinearLayout {
super.onFinishInflate(); super.onFinishInflate();
mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons); mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS); mZenButtons.addButton(R.string.interruption_level_none, R.drawable.ic_zen_none,
mZenButtons.addButton(R.string.interruption_level_priority, Global.ZEN_MODE_NO_INTERRUPTIONS);
mZenButtons.addButton(R.string.interruption_level_priority, R.drawable.ic_zen_important,
Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF); mZenButtons.addButton(R.string.interruption_level_all, R.drawable.ic_zen_all,
Global.ZEN_MODE_OFF);
mZenButtons.setCallback(mZenButtonsCallback); mZenButtons.setCallback(mZenButtonsCallback);
mZenSubhead = findViewById(R.id.zen_subhead); mZenSubhead = findViewById(R.id.zen_subhead);
@@ -160,7 +160,6 @@ public class ZenModePanel extends LinearLayout {
protected void onAttachedToWindow() { protected void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
if (DEBUG) Log.d(mTag, "onAttachedToWindow"); if (DEBUG) Log.d(mTag, "onAttachedToWindow");
mZenToast.hide();
mAttachedZen = getSelectedZen(-1); mAttachedZen = getSelectedZen(-1);
mSessionZen = mAttachedZen; mSessionZen = mAttachedZen;
mSessionExitCondition = copy(mExitCondition); mSessionExitCondition = copy(mExitCondition);
@@ -193,10 +192,6 @@ public class ZenModePanel extends LinearLayout {
if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) { if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
mPrefs.trackNoneSelected(); mPrefs.trackNoneSelected();
} }
if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS
|| selectedZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
mZenToast.show(selectedZen);
}
} }
} }

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.volume;
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.R;
public class ZenToast {
private static final String ACTION_SHOW = ZenToast.class.getName() + ".SHOW";
private static final String ACTION_HIDE = ZenToast.class.getName() + ".HIDE";
private static final String EXTRA_ZEN = "zen";
private static final String EXTRA_TEXT = "text";
private static final int MSG_SHOW = 1;
private static final int MSG_HIDE = 2;
private final Context mContext;
private final WindowManager mWindowManager;
private View mZenToast;
public ZenToast(Context context) {
mContext = context;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SHOW);
filter.addAction(ACTION_HIDE);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
}
public void show(int zen) {
mHandler.removeMessages(MSG_HIDE);
mHandler.removeMessages(MSG_SHOW);
mHandler.obtainMessage(MSG_SHOW, zen, 0).sendToTarget();
}
public void hide() {
mHandler.removeMessages(MSG_HIDE);
mHandler.removeMessages(MSG_SHOW);
mHandler.obtainMessage(MSG_HIDE).sendToTarget();
}
private void handleShow(int zen, String overrideText) {
handleHide();
String text;
final int iconRes;
switch (zen) {
case ZEN_MODE_NO_INTERRUPTIONS:
text = mContext.getString(R.string.zen_no_interruptions);
iconRes = R.drawable.ic_zen_none;
break;
case ZEN_MODE_IMPORTANT_INTERRUPTIONS:
text = mContext.getString(R.string.zen_important_interruptions);
iconRes = R.drawable.ic_zen_important;
break;
default:
return;
}
if (overrideText != null) {
text = overrideText;
}
final Resources res = mContext.getResources();
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = res.getDimensionPixelSize(R.dimen.zen_toast_width);
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = R.style.ZenToastAnimations;
params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
params.setTitle(getClass().getSimpleName());
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
params.gravity = Gravity.CENTER;
params.packageName = mContext.getPackageName();
mZenToast = LayoutInflater.from(mContext).inflate(R.layout.zen_toast, null);
final TextView message = (TextView) mZenToast.findViewById(android.R.id.message);
message.setText(text);
final ImageView icon = (ImageView) mZenToast.findViewById(android.R.id.icon);
icon.setImageResource(iconRes);
mZenToast.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewDetachedFromWindow(View v) {
// noop
}
@Override
public void onViewAttachedToWindow(View v) {
mZenToast.announceForAccessibility(message.getText());
}
});
mWindowManager.addView(mZenToast, params);
final int animDuration = res.getInteger(R.integer.zen_toast_animation_duration);
final int visibleDuration = res.getInteger(R.integer.zen_toast_visible_duration);
mHandler.sendEmptyMessageDelayed(MSG_HIDE, animDuration + visibleDuration);
}
private void handleHide() {
if (mZenToast != null) {
mWindowManager.removeView(mZenToast);
mZenToast = null;
}
}
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SHOW:
handleShow(msg.arg1, null);
break;
case MSG_HIDE:
handleHide();
break;
}
}
};
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_SHOW.equals(intent.getAction())) {
final int zen = intent.getIntExtra(EXTRA_ZEN, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
final String text = intent.getStringExtra(EXTRA_TEXT);
handleShow(zen, text);
} else if (ACTION_HIDE.equals(intent.getAction())) {
handleHide();
}
}
};
}