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