VolumeUI.java revision 031149cd5f22bd858142633c7a763450f42793f7
1package com.android.systemui.volume;
2
3import android.app.ActivityManagerNative;
4import android.content.Context;
5import android.content.Intent;
6import android.database.ContentObserver;
7import android.media.AudioManager;
8import android.media.IRemoteVolumeController;
9import android.media.IVolumeController;
10import android.media.session.ISessionController;
11import android.media.session.MediaController;
12import android.media.session.MediaSessionManager;
13import android.net.Uri;
14import android.os.AsyncTask;
15import android.os.Handler;
16import android.os.RemoteException;
17import android.os.UserHandle;
18import android.provider.Settings;
19import android.util.Log;
20
21import com.android.systemui.R;
22import com.android.systemui.SystemUI;
23import com.android.systemui.keyguard.KeyguardViewMediator;
24import com.android.systemui.statusbar.policy.ZenModeController;
25import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
26
27import java.io.FileDescriptor;
28import java.io.PrintWriter;
29
30/*
31 * Copyright (C) 2014 The Android Open Source Project
32 *
33 * Licensed under the Apache License, Version 2.0 (the "License");
34 * you may not use this file except in compliance with the License.
35 * You may obtain a copy of the License at
36 *
37 *      http://www.apache.org/licenses/LICENSE-2.0
38 *
39 * Unless required by applicable law or agreed to in writing, software
40 * distributed under the License is distributed on an "AS IS" BASIS,
41 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42 * See the License for the specific language governing permissions and
43 * limitations under the License.
44 */
45
46public class VolumeUI extends SystemUI {
47    private static final String TAG = "VolumeUI";
48    private static final String SETTING = "systemui_volume_controller";  // for testing
49    private static final Uri SETTING_URI = Settings.Global.getUriFor(SETTING);
50    private static final int DEFAULT = 1;  // enabled by default
51
52    private final Handler mHandler = new Handler();
53
54    private AudioManager mAudioManager;
55    private MediaSessionManager mMediaSessionManager;
56    private VolumeController mVolumeController;
57    private RemoteVolumeController mRemoteVolumeController;
58
59    private VolumePanel mPanel;
60    private int mDismissDelay;
61
62    @Override
63    public void start() {
64        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
65        mMediaSessionManager = (MediaSessionManager) mContext
66                .getSystemService(Context.MEDIA_SESSION_SERVICE);
67        initPanel();
68        mVolumeController = new VolumeController();
69        mRemoteVolumeController = new RemoteVolumeController();
70        putComponent(VolumeComponent.class, mVolumeController);
71        updateController();
72        mContext.getContentResolver().registerContentObserver(SETTING_URI, false, mObserver);
73    }
74
75    @Override
76    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
77        if (mPanel != null) {
78            mPanel.dump(fd, pw, args);
79        }
80    }
81
82    private void updateController() {
83        if (Settings.Global.getInt(mContext.getContentResolver(), SETTING, DEFAULT) != 0) {
84            Log.d(TAG, "Registering volume controller");
85            mAudioManager.setVolumeController(mVolumeController);
86            mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
87        } else {
88            Log.d(TAG, "Unregistering volume controller");
89            mAudioManager.setVolumeController(null);
90            mMediaSessionManager.setRemoteVolumeController(null);
91        }
92    }
93
94    private void initPanel() {
95        mDismissDelay = mContext.getResources().getInteger(R.integer.volume_panel_dismiss_delay);
96        mPanel = new VolumePanel(mContext, new ZenModeControllerImpl(mContext, mHandler));
97        mPanel.setCallback(new VolumePanel.Callback() {
98            @Override
99            public void onZenSettings() {
100                mHandler.removeCallbacks(mStartZenSettings);
101                mHandler.post(mStartZenSettings);
102            }
103
104            @Override
105            public void onInteraction() {
106                final KeyguardViewMediator kvm = getComponent(KeyguardViewMediator.class);
107                if (kvm != null) {
108                    kvm.userActivity();
109                }
110            }
111
112            @Override
113            public void onVisible(boolean visible) {
114                if (mAudioManager != null && mVolumeController != null) {
115                    mAudioManager.notifyVolumeControllerVisible(mVolumeController, visible);
116                }
117            }
118        });
119    }
120
121    private final ContentObserver mObserver = new ContentObserver(mHandler) {
122        public void onChange(boolean selfChange, Uri uri) {
123            if (SETTING_URI.equals(uri)) {
124                updateController();
125            }
126        }
127    };
128
129    private final Runnable mStartZenSettings = new Runnable() {
130        @Override
131        public void run() {
132            AsyncTask.execute(new Runnable() {
133                @Override
134                public void run() {
135                    try {
136                        // Dismiss the lock screen when Settings starts.
137                        ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
138                    } catch (RemoteException e) {
139                    }
140                    final Intent intent = ZenModePanel.ZEN_SETTINGS;
141                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
142                    mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
143
144                    // dismiss shade if showing
145                    mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
146                }
147            });
148            mPanel.postDismiss(mDismissDelay);
149        }
150    };
151
152    /** For now, simply host an unmodified base volume panel in this process. */
153    private final class VolumeController extends IVolumeController.Stub implements VolumeComponent {
154
155        @Override
156        public void displaySafeVolumeWarning(int flags) throws RemoteException {
157            mPanel.postDisplaySafeVolumeWarning(flags);
158        }
159
160        @Override
161        public void volumeChanged(int streamType, int flags)
162                throws RemoteException {
163            mPanel.postVolumeChanged(streamType, flags);
164        }
165
166        @Override
167        public void masterVolumeChanged(int flags) throws RemoteException {
168            mPanel.postMasterVolumeChanged(flags);
169        }
170
171        @Override
172        public void masterMuteChanged(int flags) throws RemoteException {
173            mPanel.postMasterMuteChanged(flags);
174        }
175
176        @Override
177        public void setLayoutDirection(int layoutDirection)
178                throws RemoteException {
179            mPanel.postLayoutDirection(layoutDirection);
180        }
181
182        @Override
183        public void dismiss() throws RemoteException {
184            mPanel.postDismiss(0);
185        }
186
187        @Override
188        public ZenModeController getZenController() {
189            return mPanel.getZenController();
190        }
191    }
192
193    private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
194
195        @Override
196        public void remoteVolumeChanged(ISessionController binder, int flags)
197                throws RemoteException {
198            MediaController controller = new MediaController(mContext, binder);
199            mPanel.postRemoteVolumeChanged(controller, flags);
200        }
201
202        @Override
203        public void updateRemoteController(ISessionController session) throws RemoteException {
204            mPanel.postRemoteSliderVisibility(session != null);
205            // TODO stash default session in case the slider can be opened other
206            // than by remoteVolumeChanged.
207        }
208    }
209}
210