Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce952c8e authored by Mike Lockwood's avatar Mike Lockwood Committed by Mike Lockwood
Browse files

AudioManager: Add support for master mute

parent a5abdb9e
Loading
Loading
Loading
Loading
+33 −4
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
    private static final int MSG_VIBRATE = 4;
    private static final int MSG_TIMEOUT = 5;
    private static final int MSG_RINGER_MODE_CHANGED = 6;
    private static final int MSG_MUTE_CHANGED = 7;

    // Pseudo stream type for master volume
    private static final int STREAM_MASTER = -100;
@@ -295,8 +296,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

    private boolean isMuted(int streamType) {
        if (streamType == STREAM_MASTER) {
            // master volume mute not yet supported
            return false;
            return mAudioService.isMasterMute();
        } else {
            return mAudioService.isStreamMute(streamType);
        }
@@ -328,8 +328,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie

    private int getLastAudibleStreamVolume(int streamType) {
        if (streamType == STREAM_MASTER) {
            // master volume mute not yet supported
            return getStreamVolume(STREAM_MASTER);
            return mAudioService.getLastAudibleMasterVolume();
        } else {
            return mAudioService.getLastAudibleStreamVolume(streamType);
        }
@@ -452,6 +451,19 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        postVolumeChanged(STREAM_MASTER, flags);
    }

    public void postMuteChanged(int streamType, int flags) {
        if (hasMessages(MSG_VOLUME_CHANGED)) return;
        if (mStreamControls == null) {
            createSliders();
        }
        removeMessages(MSG_FREE_RESOURCES);
        obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget();
    }

    public void postMasterMuteChanged(int flags) {
        postMuteChanged(STREAM_MASTER, flags);
    }

    /**
     * Override this if you have other work to do when the volume changes (for
     * example, vibrating, playing a sound, etc.). Make sure to call through to
@@ -485,6 +497,18 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
        resetTimeout();
    }

    protected void onMuteChanged(int streamType, int flags) {

        if (LOGD) Log.d(TAG, "onMuteChanged(streamType: " + streamType + ", flags: " + flags + ")");

        StreamControl sc = mStreamControls.get(streamType);
        if (sc != null) {
            sc.icon.setImageResource(isMuted(sc.streamType) ? sc.iconMuteRes : sc.iconRes);
        }

        onVolumeChanged(streamType, flags);
    }

    protected void onShowVolumeChanged(int streamType, int flags) {
        int index = isMuted(streamType) ?
                getLastAudibleStreamVolume(streamType)
@@ -683,6 +707,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
                break;
            }

            case MSG_MUTE_CHANGED: {
                onMuteChanged(msg.arg1, msg.arg2);
                break;
            }

            case MSG_FREE_RESOURCES: {
                onFreeResources();
                break;
+43 −8
Original line number Diff line number Diff line
@@ -372,11 +372,12 @@ public class AudioManager {
    /**
     * @hide
     */
    public void preDispatchKeyEvent(int keyCode, int stream) {
    public void preDispatchKeyEvent(KeyEvent event, int stream) {
        /*
         * If the user hits another key within the play sound delay, then
         * cancel the sound
         */
        int keyCode = event.getKeyCode();
        if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
                && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
                && mVolumeKeyUpTime + VolumePanel.PLAY_SOUND_DELAY
@@ -397,7 +398,8 @@ public class AudioManager {
    /**
     * @hide
     */
    public void handleKeyDown(int keyCode, int stream) {
    public void handleKeyDown(KeyEvent event, int stream) {
        int keyCode = event.getKeyCode();
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -426,7 +428,13 @@ public class AudioManager {
                }
                break;
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                if (event.getRepeatCount() == 0) {
                    if (mUseMasterVolume) {
                        setMasterMute(!isMasterMute());
                    } else {
                        // TODO: Actually handle MUTE.
                    }
                }
                break;
        }
    }
@@ -434,7 +442,8 @@ public class AudioManager {
    /**
     * @hide
     */
    public void handleKeyUp(int keyCode, int stream) {
    public void handleKeyUp(KeyEvent event, int stream) {
        int keyCode = event.getKeyCode();
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -460,9 +469,6 @@ public class AudioManager {

                mVolumeKeyUpTime = SystemClock.uptimeMillis();
                break;
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                // TODO: Actually handle MUTE.
                break;
        }
    }

@@ -657,7 +663,7 @@ public class AudioManager {
        IAudioService service = getService();
        try {
            if (mUseMasterVolume) {
                return service.getMasterVolume();
                return service.getLastAudibleMasterVolume();
            } else {
                return service.getLastAudibleStreamVolume(streamType);
            }
@@ -783,6 +789,35 @@ public class AudioManager {
        }
    }

    /**
     * set master mute state.
     *
     * @hide
     */
    public void setMasterMute(boolean state) {
        IAudioService service = getService();
        try {
            service.setMasterMute(state, mICallBack);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in setMasterMute", e);
        }
    }

    /**
     * get master mute state.
     *
     * @hide
     */
    public boolean isMasterMute() {
        IAudioService service = getService();
        try {
            return service.isMasterMute();
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in isMasterMute", e);
            return false;
        }
    }

    /**
     * forces the stream controlled by hard volume keys
     * specifying streamType == -1 releases control to the
+135 −1
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ public class AudioService extends IAudioService.Stub {
    private AudioHandler mAudioHandler;
    /** @see VolumeStreamState */
    private VolumeStreamState[] mStreamStates;
    private MasterMuteState mMasterMuteState;
    private SettingsObserver mSettingsObserver;

    private int mMode;
@@ -446,6 +447,7 @@ public class AudioService extends IAudioService.Stub {
        for (int i = 0; i < numStreamTypes; i++) {
            streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[STREAM_VOLUME_ALIAS[i]], i);
        }
        mMasterMuteState = new MasterMuteState();

        // Correct stream index values for streams with aliases
        for (int i = 0; i < numStreamTypes; i++) {
@@ -762,6 +764,16 @@ public class AudioService extends IAudioService.Stub {
        return (mStreamStates[streamType].muteCount() != 0);
    }

    /** @see AudioManager#setMasterMute(boolean, IBinder) */
    public void setMasterMute(boolean state, IBinder cb) {
        mMasterMuteState.mute(cb, state);
    }

    /** get master mute state. */
    public boolean isMasterMute() {
        return (mMasterMuteState.muteCount() != 0);
    }

    /** @see AudioManager#getStreamVolume(int) */
    public int getStreamVolume(int streamType) {
        ensureValidStreamType(streamType);
@@ -770,7 +782,8 @@ public class AudioService extends IAudioService.Stub {
    }

    public int getMasterVolume() {
        return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
        if (isMasterMute()) return 0;
        return getLastAudibleMasterVolume();
    }

    public void setMasterVolume(int volume, int flags) {
@@ -794,6 +807,11 @@ public class AudioService extends IAudioService.Stub {
        return (mStreamStates[streamType].getIndex(device, true  /* lastAudible */) + 5) / 10;
    }

    /** Get last audible master volume before it was muted. */
    public int getLastAudibleMasterVolume() {
        return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
    }

    /** @see AudioManager#getRingerMode() */
    public int getRingerMode() {
        synchronized(mSettingsLock) {
@@ -2231,6 +2249,122 @@ public class AudioService extends IAudioService.Stub {
        }
    }

    public class MasterMuteState {

        private ArrayList<MasterMuteDeathHandler> mDeathHandlers;

        private MasterMuteState() {
            mDeathHandlers = new ArrayList<MasterMuteDeathHandler>();
        }

        public void mute(IBinder cb, boolean state) {
            MasterMuteDeathHandler handler = getDeathHandler(cb, state);
            if (handler == null) {
                Log.e(TAG, "Could not get client death handler for master volume");
                return;
            }
            handler.mute(state);
        }

        private class MasterMuteDeathHandler implements IBinder.DeathRecipient {
            private IBinder mICallback; // To be notified of client's death
            private int mMuteCount; // Number of active mutes for this client

            MasterMuteDeathHandler(IBinder cb) {
                mICallback = cb;
            }

            public void mute(boolean state) {
                synchronized(mDeathHandlers) {
                    if (state) {
                        if (mMuteCount == 0) {
                            // Register for client death notification
                            try {
                                // mICallback can be 0 if muted by AudioService
                                if (mICallback != null) {
                                    mICallback.linkToDeath(this, 0);
                                }
                                mDeathHandlers.add(this);
                                // If the stream is not yet muted by any client, set lvel to 0
                                if (muteCount() == 0) {
                                    AudioSystem.setMasterMute(true);
                                    mVolumePanel.postMasterMuteChanged(AudioManager.FLAG_SHOW_UI);
                                }
                            } catch (RemoteException e) {
                                // Client has died!
                                binderDied();
                                mDeathHandlers.notify();
                                return;
                            }
                        } else {
                            Log.w(TAG, "master volume was already muted by this client");
                        }
                        mMuteCount++;
                    } else {
                        if (mMuteCount == 0) {
                            Log.e(TAG, "unexpected unmute for master volume");
                        } else {
                            mMuteCount--;
                            if (mMuteCount == 0) {
                                // Unregistr from client death notification
                                mDeathHandlers.remove(this);
                                // mICallback can be 0 if muted by AudioService
                                if (mICallback != null) {
                                    mICallback.unlinkToDeath(this, 0);
                                }
                                if (muteCount() == 0) {
                                    AudioSystem.setMasterMute(false);
                                    mVolumePanel.postMasterMuteChanged(AudioManager.FLAG_SHOW_UI);
                                }
                            }
                        }
                    }
                    mDeathHandlers.notify();
                }
            }

            public void binderDied() {
                Log.w(TAG, "Volume service client died for master volume");
                if (mMuteCount != 0) {
                    // Reset all active mute requests from this client.
                    mMuteCount = 1;
                    mute(false);
                }
            }
        }

        private int muteCount() {
            int count = 0;
            int size = mDeathHandlers.size();
            for (int i = 0; i < size; i++) {
                count += mDeathHandlers.get(i).mMuteCount;
            }
            return count;
        }

        private MasterMuteDeathHandler getDeathHandler(IBinder cb, boolean state) {
            synchronized(mDeathHandlers) {
                MasterMuteDeathHandler handler;
                int size = mDeathHandlers.size();
                for (int i = 0; i < size; i++) {
                    handler = mDeathHandlers.get(i);
                    if (cb == handler.mICallback) {
                        return handler;
                    }
                }
                // If this is the first mute request for this client, create a new
                // client death handler. Otherwise, it is an out of sequence unmute request.
                if (state) {
                    handler = new MasterMuteDeathHandler(cb);
                } else {
                    Log.w(TAG, "stream was not muted by this client");
                    handler = null;
                }
                return handler;
            }
        }
    }

    /** Thread that handles native AudioSystem control. */
    private class AudioSystemThread extends Thread {
        AudioSystemThread() {
+6 −0
Original line number Diff line number Diff line
@@ -45,6 +45,10 @@ interface IAudioService {

    boolean isStreamMute(int streamType);

    void setMasterMute(boolean state, IBinder cb);

    boolean isMasterMute();

    int getStreamVolume(int streamType);

    int getMasterVolume();
@@ -55,6 +59,8 @@ interface IAudioService {
    
    int getLastAudibleStreamVolume(int streamType);

    int getLastAudibleMasterVolume();

    void setRingerMode(int ringerMode);
    
    int getRingerMode();
+3 −5
Original line number Diff line number Diff line
@@ -52,8 +52,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
    }

    public void preDispatchKeyEvent(KeyEvent event) {
        getAudioManager().preDispatchKeyEvent(event.getKeyCode(),
                AudioManager.USE_DEFAULT_STREAM_TYPE);
        getAudioManager().preDispatchKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
    }

    public boolean dispatchKeyEvent(KeyEvent event) {
@@ -79,7 +78,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                getAudioManager().handleKeyDown(keyCode, AudioManager.USE_DEFAULT_STREAM_TYPE);
                getAudioManager().handleKeyDown(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
                return true;
            }

@@ -197,8 +196,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
                    AudioManager audioManager = (AudioManager)mContext.getSystemService(
                            Context.AUDIO_SERVICE);
                    if (audioManager != null) {
                        getAudioManager().handleKeyUp(keyCode,
                                AudioManager.USE_DEFAULT_STREAM_TYPE);
                        getAudioManager().handleKeyUp(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
                    }
                }
                return true;
Loading