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

Commit 001c59c6 authored by RoboErik's avatar RoboErik
Browse files

Route volume keys directly to the audio system on TVs

This routes volume and mute keys directly to the audio system when
on a television instead of letting apps or sessions intercept them.

Change-Id: I2af47e30c7842aca96d045a6cc9ca025b94e546a
parent 4197cb60
Loading
Loading
Loading
Loading
+24 −12
Original line number Original line Diff line number Diff line
@@ -153,11 +153,11 @@ public class AudioService extends IAudioService.Stub {
    private final AppOpsManager mAppOps;
    private final AppOpsManager mAppOps;


    // the platform has no specific capabilities
    // the platform has no specific capabilities
    private static final int PLATFORM_DEFAULT = 0;
    public static final int PLATFORM_DEFAULT = 0;
    // the platform is voice call capable (a phone)
    // the platform is voice call capable (a phone)
    private static final int PLATFORM_VOICE = 1;
    public static final int PLATFORM_VOICE = 1;
    // the platform is a television or a set-top box
    // the platform is a television or a set-top box
    private static final int PLATFORM_TELEVISION = 2;
    public static final int PLATFORM_TELEVISION = 2;
    // the platform type affects volume and silent mode behavior
    // the platform type affects volume and silent mode behavior
    private final int mPlatformType;
    private final int mPlatformType;


@@ -546,15 +546,7 @@ public class AudioService extends IAudioService.Stub {
        mContentResolver = context.getContentResolver();
        mContentResolver = context.getContentResolver();
        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);


        if (mContext.getResources().getBoolean(
        mPlatformType = getPlatformType(context);
                com.android.internal.R.bool.config_voice_capable)) {
            mPlatformType = PLATFORM_VOICE;
        } else if (context.getPackageManager().hasSystemFeature(
                                                            PackageManager.FEATURE_LEANBACK)) {
            mPlatformType = PLATFORM_TELEVISION;
        } else {
            mPlatformType = PLATFORM_DEFAULT;
        }


        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
        mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
@@ -667,6 +659,26 @@ public class AudioService extends IAudioService.Stub {
        LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
        LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
    }
    }


    /**
     * Return the platform type that this is running on. One of:
     * <ul>
     * <li>{@link #PLATFORM_VOICE}</li>
     * <li>{@link #PLATFORM_TELEVISION}</li>
     * <li>{@link #PLATFORM_DEFAULT}</li>
     * </ul>
     */
    public static int getPlatformType(Context context) {
        if (context.getResources().getBoolean(
                com.android.internal.R.bool.config_voice_capable)) {
            return PLATFORM_VOICE;
        } else if (context.getPackageManager().hasSystemFeature(
                                                            PackageManager.FEATURE_LEANBACK)) {
            return PLATFORM_TELEVISION;
        } else {
            return PLATFORM_DEFAULT;
        }
    }

    public void systemReady() {
    public void systemReady() {
        sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
        sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
                0, 0, null, 0);
                0, 0, null, 0);
+1 −1
Original line number Original line Diff line number Diff line
@@ -221,7 +221,7 @@ public class MediaSessionLegacyHelper {
                mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                        direction, flags);
                        direction, flags);
            } else if (isMute) {
            } else if (isMute) {
                if (down) {
                if (down && keyEvent.getRepeatCount() == 0) {
                    mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                    mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                            AudioManager.ADJUST_TOGGLE_MUTE, flags);
                            AudioManager.ADJUST_TOGGLE_MUTE, flags);
                }
                }
+73 −5
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Rect;
import android.media.AudioAttributes;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManager;
import android.media.AudioService;
import android.media.IAudioService;
import android.media.IAudioService;
import android.media.Ringtone;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.RingtoneManager;
@@ -376,6 +377,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    boolean mHasSoftInput = false;
    boolean mHasSoftInput = false;
    boolean mTranslucentDecorEnabled = true;
    boolean mTranslucentDecorEnabled = true;
    boolean mUseTvRouting;
    boolean mUseMasterVolume;


    int mPointerLocationMode = 0; // guarded by mLock
    int mPointerLocationMode = 0; // guarded by mLock


@@ -1262,6 +1265,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
                com.android.internal.R.integer.config_triplePressOnPowerBehavior);


        mUseTvRouting = AudioService.getPlatformType(mContext) == AudioService.PLATFORM_TELEVISION;
        mUseMasterVolume = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_useMasterVolume);

        readConfigurationDependentBehaviors();
        readConfigurationDependentBehaviors();


        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -4534,6 +4541,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                if (mUseTvRouting) {
                    // On TVs volume keys never go to the foreground app
                    result &= ~ACTION_PASS_TO_USER;
                }
                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                    if (down) {
                    if (down) {
                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
                        if (interactive && !mScreenshotChordVolumeDownKeyTriggered
@@ -4595,11 +4606,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    }
                    }


                    if ((result & ACTION_PASS_TO_USER) == 0) {
                    if ((result & ACTION_PASS_TO_USER) == 0) {
                        if (mUseTvRouting) {
                            dispatchDirectAudioEvent(event);
                        } else {
                            // If we aren't passing to the user and no one else
                            // If we aren't passing to the user and no one else
                        // handled it send it to the session manager to figure
                            // handled it send it to the session manager to
                        // out.
                            // figure out.
                            MediaSessionLegacyHelper.getHelper(mContext)
                            MediaSessionLegacyHelper.getHelper(mContext)
                                    .sendVolumeKeyEvent(event, true);
                                    .sendVolumeKeyEvent(event, true);
                        }
                        break;
                        break;
                    }
                    }
                }
                }
@@ -4844,6 +4859,59 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return false;
        return false;
    }
    }


    private void dispatchDirectAudioEvent(KeyEvent event) {
        if (event.getAction() != KeyEvent.ACTION_DOWN) {
            return;
        }
        int keyCode = event.getKeyCode();
        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND;
        String pkgName = mContext.getOpPackageName();
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
                try {
                    if (mUseMasterVolume) {
                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_RAISE, flags,
                                pkgName);
                    } else {
                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
                }
                break;
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                try {
                    if (mUseMasterVolume) {
                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_LOWER, flags,
                                pkgName);
                    } else {
                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
                }
                break;
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                try {
                    if (event.getRepeatCount() == 0) {
                        if (mUseMasterVolume) {
                            getAudioService().adjustMasterVolume(AudioManager.ADJUST_TOGGLE_MUTE,
                                    flags, pkgName);
                        } else {
                            getAudioService().adjustSuggestedStreamVolume(
                                    AudioManager.ADJUST_TOGGLE_MUTE,
                                    AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
                        }
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
                }
                break;
        }
    }

    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
    void dispatchMediaKeyWithWakeLock(KeyEvent event) {
        if (DEBUG_INPUT) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
            Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);