Home | History | Annotate | Download | only in volume
      1 package com.android.systemui.volume;
      2 
      3 import android.content.Context;
      4 import android.content.res.Configuration;
      5 import android.database.ContentObserver;
      6 import android.media.AudioManager;
      7 import android.media.IRemoteVolumeController;
      8 import android.media.IVolumeController;
      9 import android.media.session.ISessionController;
     10 import android.media.session.MediaController;
     11 import android.media.session.MediaSessionManager;
     12 import android.net.Uri;
     13 import android.os.Bundle;
     14 import android.os.Handler;
     15 import android.os.RemoteException;
     16 import android.provider.Settings;
     17 import android.util.Log;
     18 
     19 import com.android.systemui.R;
     20 import com.android.systemui.SystemUI;
     21 import com.android.systemui.keyguard.KeyguardViewMediator;
     22 import com.android.systemui.statusbar.phone.PhoneStatusBar;
     23 import com.android.systemui.statusbar.policy.ZenModeController;
     24 import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
     25 
     26 import java.io.FileDescriptor;
     27 import java.io.PrintWriter;
     28 
     29 /*
     30  * Copyright (C) 2014 The Android Open Source Project
     31  *
     32  * Licensed under the Apache License, Version 2.0 (the "License");
     33  * you may not use this file except in compliance with the License.
     34  * You may obtain a copy of the License at
     35  *
     36  *      http://www.apache.org/licenses/LICENSE-2.0
     37  *
     38  * Unless required by applicable law or agreed to in writing, software
     39  * distributed under the License is distributed on an "AS IS" BASIS,
     40  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     41  * See the License for the specific language governing permissions and
     42  * limitations under the License.
     43  */
     44 
     45 public class VolumeUI extends SystemUI {
     46     private static final String TAG = "VolumeUI";
     47     private static final String SETTING = "systemui_volume_controller";  // for testing
     48     private static final Uri SETTING_URI = Settings.Global.getUriFor(SETTING);
     49     private static final int DEFAULT = 1;  // enabled by default
     50 
     51     private final Handler mHandler = new Handler();
     52 
     53     private boolean mEnabled;
     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         mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
     65         if (!mEnabled) return;
     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         pw.print("mEnabled="); pw.println(mEnabled);
     88         if (mPanel != null) {
     89             mPanel.dump(fd, pw, args);
     90         }
     91     }
     92 
     93     private void updateController() {
     94         if (Settings.Global.getInt(mContext.getContentResolver(), SETTING, DEFAULT) != 0) {
     95             Log.d(TAG, "Registering volume controller");
     96             mAudioManager.setVolumeController(mVolumeController);
     97             mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
     98         } else {
     99             Log.d(TAG, "Unregistering volume controller");
    100             mAudioManager.setVolumeController(null);
    101             mMediaSessionManager.setRemoteVolumeController(null);
    102         }
    103     }
    104 
    105     private void initPanel() {
    106         mDismissDelay = mContext.getResources().getInteger(R.integer.volume_panel_dismiss_delay);
    107         mPanel = new VolumePanel(mContext, new ZenModeControllerImpl(mContext, mHandler));
    108         mPanel.setCallback(new VolumePanel.Callback() {
    109             @Override
    110             public void onZenSettings() {
    111                 mHandler.removeCallbacks(mStartZenSettings);
    112                 mHandler.post(mStartZenSettings);
    113             }
    114 
    115             @Override
    116             public void onInteraction() {
    117                 final KeyguardViewMediator kvm = getComponent(KeyguardViewMediator.class);
    118                 if (kvm != null) {
    119                     kvm.userActivity();
    120                 }
    121             }
    122 
    123             @Override
    124             public void onVisible(boolean visible) {
    125                 if (mAudioManager != null && mVolumeController != null) {
    126                     mAudioManager.notifyVolumeControllerVisible(mVolumeController, visible);
    127                 }
    128             }
    129         });
    130     }
    131 
    132     private final ContentObserver mObserver = new ContentObserver(mHandler) {
    133         public void onChange(boolean selfChange, Uri uri) {
    134             if (SETTING_URI.equals(uri)) {
    135                 updateController();
    136             }
    137         }
    138     };
    139 
    140     private final Runnable mStartZenSettings = new Runnable() {
    141         @Override
    142         public void run() {
    143             getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
    144                     ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
    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             dismissNow();
    182         }
    183 
    184         @Override
    185         public ZenModeController getZenController() {
    186             return mPanel.getZenController();
    187         }
    188 
    189         @Override
    190         public void dispatchDemoCommand(String command, Bundle args) {
    191             mPanel.dispatchDemoCommand(command, args);
    192         }
    193 
    194         @Override
    195         public void dismissNow() {
    196             mPanel.postDismiss(0);
    197         }
    198     }
    199 
    200     private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
    201 
    202         @Override
    203         public void remoteVolumeChanged(ISessionController binder, int flags)
    204                 throws RemoteException {
    205             MediaController controller = new MediaController(mContext, binder);
    206             mPanel.postRemoteVolumeChanged(controller, flags);
    207         }
    208 
    209         @Override
    210         public void updateRemoteController(ISessionController session) throws RemoteException {
    211             mPanel.postRemoteSliderVisibility(session != null);
    212             // TODO stash default session in case the slider can be opened other
    213             // than by remoteVolumeChanged.
    214         }
    215     }
    216 }
    217