blob: 387aed0164605ffd4a725b42b2874dddd1133e02 [file] [log] [blame]
John Spurlock3346a802014-05-20 16:25:37 -04001/*
2 * Copyright (C) 2014 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
John Spurlockcdb57ae2015-02-11 19:04:11 -050017package com.android.systemui.volume;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.content.BroadcastReceiver;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.DialogInterface.OnClickListener;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.content.pm.ApplicationInfo;
30import android.content.res.Configuration;
31import android.media.AudioManager;
John Spurlockcdb57ae2015-02-11 19:04:11 -050032import android.media.session.MediaSessionManager;
John Spurlockcdb57ae2015-02-11 19:04:11 -050033import android.os.Handler;
John Spurlockf88d8082015-03-25 18:09:51 -040034import android.os.SystemProperties;
John Spurlockcdb57ae2015-02-11 19:04:11 -050035import android.provider.Settings;
36import android.text.TextUtils;
37import android.util.Log;
38
39import com.android.systemui.R;
40import com.android.systemui.SystemUI;
John Spurlock3c4076a2015-02-24 12:12:25 -050041import com.android.systemui.qs.tiles.DndTile;
John Spurlockcdb57ae2015-02-11 19:04:11 -050042import com.android.systemui.statusbar.ServiceMonitor;
John Spurlockcdb57ae2015-02-11 19:04:11 -050043import com.android.systemui.statusbar.phone.SystemUIDialog;
44import com.android.systemui.statusbar.policy.ZenModeController;
45import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
46
47import java.io.FileDescriptor;
48import java.io.PrintWriter;
49
John Spurlock3346a802014-05-20 16:25:37 -040050public class VolumeUI extends SystemUI {
51 private static final String TAG = "VolumeUI";
John Spurlockcdb57ae2015-02-11 19:04:11 -050052 private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock3346a802014-05-20 16:25:37 -040053
John Spurlockf88d8082015-03-25 18:09:51 -040054 private static final boolean USE_OLD_VOLUME = SystemProperties.getBoolean("volume.old", false);
55
John Spurlock86005342014-05-23 11:58:00 -040056 private final Handler mHandler = new Handler();
John Spurlockcdb57ae2015-02-11 19:04:11 -050057 private final Receiver mReceiver = new Receiver();
58 private final RestorationNotification mRestorationNotification = new RestorationNotification();
John Spurlock1dad2722014-07-11 11:07:53 -040059
John Spurlockf2565a82014-10-23 20:16:22 -040060 private boolean mEnabled;
John Spurlock3346a802014-05-20 16:25:37 -040061 private AudioManager mAudioManager;
John Spurlockcdb57ae2015-02-11 19:04:11 -050062 private NotificationManager mNotificationManager;
RoboErik19c95182014-06-23 15:38:48 -070063 private MediaSessionManager mMediaSessionManager;
John Spurlockcdb57ae2015-02-11 19:04:11 -050064 private ServiceMonitor mVolumeControllerService;
RoboErik19c95182014-06-23 15:38:48 -070065
John Spurlockf88d8082015-03-25 18:09:51 -040066 private VolumePanelComponent mOldVolume;
67 private VolumeDialogComponent mNewVolume;
John Spurlock3346a802014-05-20 16:25:37 -040068
69 @Override
70 public void start() {
John Spurlockf2565a82014-10-23 20:16:22 -040071 mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
72 if (!mEnabled) return;
John Spurlock3346a802014-05-20 16:25:37 -040073 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
John Spurlockcdb57ae2015-02-11 19:04:11 -050074 mNotificationManager =
75 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
RoboErik19c95182014-06-23 15:38:48 -070076 mMediaSessionManager = (MediaSessionManager) mContext
77 .getSystemService(Context.MEDIA_SESSION_SERVICE);
John Spurlockf88d8082015-03-25 18:09:51 -040078 final ZenModeController zenController = new ZenModeControllerImpl(mContext, mHandler);
79 mOldVolume = new VolumePanelComponent(this, mContext, mHandler, zenController);
80 mNewVolume = new VolumeDialogComponent(this, mContext, null, zenController);
81 putComponent(VolumeComponent.class, getVolumeComponent());
John Spurlockcdb57ae2015-02-11 19:04:11 -050082 mReceiver.start();
83 mVolumeControllerService = new ServiceMonitor(TAG, LOGD,
84 mContext, Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT,
85 new ServiceMonitorCallbacks());
86 mVolumeControllerService.start();
John Spurlock3346a802014-05-20 16:25:37 -040087 }
88
John Spurlockf88d8082015-03-25 18:09:51 -040089 private VolumeComponent getVolumeComponent() {
90 return USE_OLD_VOLUME ? mOldVolume : mNewVolume;
91 }
92
John Spurlockad494bc2014-07-19 15:56:19 -040093 @Override
John Spurlock7e6809a2014-08-06 16:03:14 -040094 protected void onConfigurationChanged(Configuration newConfig) {
95 super.onConfigurationChanged(newConfig);
John Spurlockf88d8082015-03-25 18:09:51 -040096 if (!mEnabled) return;
97 getVolumeComponent().onConfigurationChanged(newConfig);
John Spurlock7e6809a2014-08-06 16:03:14 -040098 }
99
100 @Override
John Spurlockad494bc2014-07-19 15:56:19 -0400101 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
John Spurlockf2565a82014-10-23 20:16:22 -0400102 pw.print("mEnabled="); pw.println(mEnabled);
John Spurlockf88d8082015-03-25 18:09:51 -0400103 if (!mEnabled) return;
John Spurlockcdb57ae2015-02-11 19:04:11 -0500104 pw.print("mVolumeControllerService="); pw.println(mVolumeControllerService.getComponent());
John Spurlockf88d8082015-03-25 18:09:51 -0400105 getVolumeComponent().dump(fd, pw, args);
John Spurlockad494bc2014-07-19 15:56:19 -0400106 }
107
John Spurlockf88d8082015-03-25 18:09:51 -0400108 private void setDefaultVolumeController(boolean register) {
John Spurlockcdb57ae2015-02-11 19:04:11 -0500109 if (register) {
John Spurlock3c4076a2015-02-24 12:12:25 -0500110 DndTile.setVisible(mContext, false);
John Spurlockf88d8082015-03-25 18:09:51 -0400111 if (LOGD) Log.d(TAG, "Registering default volume controller");
112 getVolumeComponent().register();
John Spurlock3346a802014-05-20 16:25:37 -0400113 } else {
John Spurlockc72d4cb2015-02-26 14:49:55 -0500114 if (LOGD) Log.d(TAG, "Unregistering default volume controller");
John Spurlock3346a802014-05-20 16:25:37 -0400115 mAudioManager.setVolumeController(null);
RoboErik19c95182014-06-23 15:38:48 -0700116 mMediaSessionManager.setRemoteVolumeController(null);
John Spurlock3346a802014-05-20 16:25:37 -0400117 }
118 }
119
John Spurlockcdb57ae2015-02-11 19:04:11 -0500120 private String getAppLabel(ComponentName component) {
121 final String pkg = component.getPackageName();
122 try {
123 final ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(pkg, 0);
124 final String rt = mContext.getPackageManager().getApplicationLabel(ai).toString();
125 if (!TextUtils.isEmpty(rt)) {
126 return rt;
John Spurlock3346a802014-05-20 16:25:37 -0400127 }
John Spurlockcdb57ae2015-02-11 19:04:11 -0500128 } catch (Exception e) {
129 Log.w(TAG, "Error loading app label", e);
John Spurlock3346a802014-05-20 16:25:37 -0400130 }
John Spurlockcdb57ae2015-02-11 19:04:11 -0500131 return pkg;
132 }
133
134 private void showServiceActivationDialog(final ComponentName component) {
135 final SystemUIDialog d = new SystemUIDialog(mContext);
136 d.setMessage(mContext.getString(R.string.volumeui_prompt_message, getAppLabel(component)));
137 d.setPositiveButton(R.string.volumeui_prompt_allow, new OnClickListener() {
138 @Override
139 public void onClick(DialogInterface dialog, int which) {
140 mVolumeControllerService.setComponent(component);
141 }
142 });
143 d.setNegativeButton(R.string.volumeui_prompt_deny, null);
144 d.show();
145 }
John Spurlock3346a802014-05-20 16:25:37 -0400146
John Spurlockcdb57ae2015-02-11 19:04:11 -0500147 private final class ServiceMonitorCallbacks implements ServiceMonitor.Callbacks {
148 @Override
149 public void onNoService() {
150 if (LOGD) Log.d(TAG, "onNoService");
John Spurlockf88d8082015-03-25 18:09:51 -0400151 setDefaultVolumeController(true);
John Spurlockcdb57ae2015-02-11 19:04:11 -0500152 mRestorationNotification.hide();
John Spurlockc72d4cb2015-02-26 14:49:55 -0500153 if (!mVolumeControllerService.isPackageAvailable()) {
154 mVolumeControllerService.setComponent(null);
155 }
John Spurlockcdb57ae2015-02-11 19:04:11 -0500156 }
157
158 @Override
159 public long onServiceStartAttempt() {
160 if (LOGD) Log.d(TAG, "onServiceStartAttempt");
John Spurlockc72d4cb2015-02-26 14:49:55 -0500161 // poke the setting to update the uid
162 mVolumeControllerService.setComponent(mVolumeControllerService.getComponent());
John Spurlockf88d8082015-03-25 18:09:51 -0400163 setDefaultVolumeController(false);
164 getVolumeComponent().dismissNow();
John Spurlockcdb57ae2015-02-11 19:04:11 -0500165 mRestorationNotification.show();
166 return 0;
167 }
168 }
169
170 private final class Receiver extends BroadcastReceiver {
171 private static final String ENABLE = "com.android.systemui.vui.ENABLE";
172 private static final String DISABLE = "com.android.systemui.vui.DISABLE";
173 private static final String EXTRA_COMPONENT = "component";
174
175 public void start() {
176 final IntentFilter filter = new IntentFilter();
177 filter.addAction(ENABLE);
178 filter.addAction(DISABLE);
179 mContext.registerReceiver(this, filter, null, mHandler);
180 }
181
182 @Override
183 public void onReceive(Context context, Intent intent) {
184 final String action = intent.getAction();
185 final ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
186 final boolean current = component.equals(mVolumeControllerService.getComponent());
187 if (ENABLE.equals(action) && component != null) {
188 if (!current) {
189 showServiceActivationDialog(component);
190 }
191 }
192 if (DISABLE.equals(action) && component != null) {
193 if (current) {
194 mVolumeControllerService.setComponent(null);
195 }
196 }
197 }
198 }
199
200 private final class RestorationNotification {
201 public void hide() {
202 mNotificationManager.cancel(R.id.notification_volumeui);
203 }
204
205 public void show() {
206 final ComponentName component = mVolumeControllerService.getComponent();
207 if (component == null) {
208 Log.w(TAG, "Not showing restoration notification, component not active");
209 return;
210 }
211 final Intent intent = new Intent(Receiver.DISABLE)
212 .putExtra(Receiver.EXTRA_COMPONENT, component);
213 mNotificationManager.notify(R.id.notification_volumeui,
214 new Notification.Builder(mContext)
215 .setSmallIcon(R.drawable.ic_ringer_audible)
216 .setWhen(0)
217 .setShowWhen(false)
218 .setOngoing(true)
219 .setContentTitle(mContext.getString(
220 R.string.volumeui_notification_title, getAppLabel(component)))
221 .setContentText(mContext.getString(R.string.volumeui_notification_text))
John Spurlock0c6ba182015-02-26 13:42:53 -0500222 .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
223 PendingIntent.FLAG_UPDATE_CURRENT))
John Spurlockcdb57ae2015-02-11 19:04:11 -0500224 .setPriority(Notification.PRIORITY_MIN)
225 .setVisibility(Notification.VISIBILITY_PUBLIC)
Alan Viverette4a357cd2015-03-18 18:37:18 -0700226 .setColor(mContext.getColor(
John Spurlockcdb57ae2015-02-11 19:04:11 -0500227 com.android.internal.R.color.system_notification_accent_color))
228 .build());
229 }
230 }
John Spurlock3346a802014-05-20 16:25:37 -0400231}