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