1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.volume;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.ActivityInfo;
22 import android.content.res.Configuration;
23 import android.media.AudioManager;
24 import android.media.VolumePolicy;
25 import android.os.Bundle;
26 import android.view.WindowManager.LayoutParams;
27 
28 import com.android.settingslib.applications.InterestingConfigChanges;
29 import com.android.systemui.Dependency;
30 import com.android.systemui.keyguard.KeyguardViewMediator;
31 import com.android.systemui.plugins.ActivityStarter;
32 import com.android.systemui.plugins.PluginDependencyProvider;
33 import com.android.systemui.plugins.VolumeDialog;
34 import com.android.systemui.plugins.VolumeDialogController;
35 import com.android.systemui.qs.tiles.DndTile;
36 import com.android.systemui.statusbar.policy.ExtensionController;
37 import com.android.systemui.tuner.TunerService;
38 
39 import java.io.FileDescriptor;
40 import java.io.PrintWriter;
41 
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 
45 /**
46  * Implementation of VolumeComponent backed by the new volume dialog.
47  */
48 @Singleton
49 public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable,
50         VolumeDialogControllerImpl.UserActivityListener{
51 
52     public static final String VOLUME_DOWN_SILENT = "sysui_volume_down_silent";
53     public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent";
54     public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
55 
56     public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = false;
57     public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
58     public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
59 
60     protected final Context mContext;
61     private final VolumeDialogControllerImpl mController;
62     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
63             ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
64             | ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
65     private final KeyguardViewMediator mKeyguardViewMediator;
66     private VolumeDialog mDialog;
67     private VolumePolicy mVolumePolicy = new VolumePolicy(
68             DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT,  // volumeDownToEnterSilent
69             DEFAULT_VOLUME_UP_TO_EXIT_SILENT,  // volumeUpToExitSilent
70             DEFAULT_DO_NOT_DISTURB_WHEN_SILENT,  // doNotDisturbWhenSilent
71             400    // vibrateToSilentDebounce
72     );
73 
74     @Inject
VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator, VolumeDialogControllerImpl volumeDialogController)75     public VolumeDialogComponent(Context context, KeyguardViewMediator keyguardViewMediator,
76             VolumeDialogControllerImpl volumeDialogController) {
77         mContext = context;
78         mKeyguardViewMediator = keyguardViewMediator;
79         mController = volumeDialogController;
80         mController.setUserActivityListener(this);
81         // Allow plugins to reference the VolumeDialogController.
82         Dependency.get(PluginDependencyProvider.class)
83                 .allowPluginDependency(VolumeDialogController.class);
84         Dependency.get(ExtensionController.class).newExtension(VolumeDialog.class)
85                 .withPlugin(VolumeDialog.class)
86                 .withDefault(this::createDefault)
87                 .withCallback(dialog -> {
88                     if (mDialog != null) {
89                         mDialog.destroy();
90                     }
91                     mDialog = dialog;
92                     mDialog.init(LayoutParams.TYPE_VOLUME_OVERLAY, mVolumeDialogCallback);
93                 }).build();
94         applyConfiguration();
95         Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
96                 VOLUME_SILENT_DO_NOT_DISTURB);
97     }
98 
createDefault()99     protected VolumeDialog createDefault() {
100         VolumeDialogImpl impl = new VolumeDialogImpl(mContext);
101         impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
102         impl.setAutomute(true);
103         impl.setSilentMode(false);
104         return impl;
105     }
106 
107     @Override
onTuningChanged(String key, String newValue)108     public void onTuningChanged(String key, String newValue) {
109         boolean volumeDownToEnterSilent = mVolumePolicy.volumeDownToEnterSilent;
110         boolean volumeUpToExitSilent = mVolumePolicy.volumeUpToExitSilent;
111         boolean doNotDisturbWhenSilent = mVolumePolicy.doNotDisturbWhenSilent;
112 
113         if (VOLUME_DOWN_SILENT.equals(key)) {
114             volumeDownToEnterSilent =
115                 TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT);
116         } else if (VOLUME_UP_SILENT.equals(key)) {
117             volumeUpToExitSilent =
118                 TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_UP_TO_EXIT_SILENT);
119         } else if (VOLUME_SILENT_DO_NOT_DISTURB.equals(key)) {
120             doNotDisturbWhenSilent =
121                 TunerService.parseIntegerSwitch(newValue, DEFAULT_DO_NOT_DISTURB_WHEN_SILENT);
122         }
123 
124         setVolumePolicy(volumeDownToEnterSilent, volumeUpToExitSilent, doNotDisturbWhenSilent,
125                 mVolumePolicy.vibrateToSilentDebounce);
126     }
127 
setVolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent, boolean doNotDisturbWhenSilent, int vibrateToSilentDebounce)128     private void setVolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent,
129             boolean doNotDisturbWhenSilent, int vibrateToSilentDebounce) {
130         mVolumePolicy = new VolumePolicy(volumeDownToEnterSilent, volumeUpToExitSilent,
131                 doNotDisturbWhenSilent, vibrateToSilentDebounce);
132         mController.setVolumePolicy(mVolumePolicy);
133     }
134 
setEnableDialogs(boolean volumeUi, boolean safetyWarning)135     void setEnableDialogs(boolean volumeUi, boolean safetyWarning) {
136         mController.setEnableDialogs(volumeUi, safetyWarning);
137     }
138 
139     @Override
onUserActivity()140     public void onUserActivity() {
141         mKeyguardViewMediator.userActivity();
142     }
143 
applyConfiguration()144     private void applyConfiguration() {
145         mController.setVolumePolicy(mVolumePolicy);
146         mController.showDndTile(true);
147     }
148 
149     @Override
onConfigurationChanged(Configuration newConfig)150     public void onConfigurationChanged(Configuration newConfig) {
151         if (mConfigChanges.applyNewConfig(mContext.getResources())) {
152             mController.mCallbacks.onConfigurationChanged();
153         }
154     }
155 
156     @Override
dismissNow()157     public void dismissNow() {
158         mController.dismiss();
159     }
160 
161     @Override
dispatchDemoCommand(String command, Bundle args)162     public void dispatchDemoCommand(String command, Bundle args) {
163         // noop
164     }
165 
166     @Override
register()167     public void register() {
168         mController.register();
169         DndTile.setCombinedIcon(mContext, true);
170     }
171 
172     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)173     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
174     }
175 
startSettings(Intent intent)176     private void startSettings(Intent intent) {
177         Dependency.get(ActivityStarter.class).startActivity(intent,
178                 true /* onlyProvisioned */, true /* dismissShade */);
179     }
180 
181     private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() {
182         @Override
183         public void onZenSettingsClicked() {
184             startSettings(ZenModePanel.ZEN_SETTINGS);
185         }
186 
187         @Override
188         public void onZenPrioritySettingsClicked() {
189             startSettings(ZenModePanel.ZEN_PRIORITY_SETTINGS);
190         }
191     };
192 
193 }
194