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

Commit 722b8086 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

Handle media button events during phone calls and when ringing

Add functionality in AudioManager/AudioService to register a
 media button receiver for telephony that, when registered, gets
 priority for media button key events during a phone call or
 when ringing.

Bug 6484717

Change-Id: I0835fc02cb24d06ca59af5a32c3ba0ae93e54442
parent c1c14065
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -1999,6 +1999,37 @@ public class AudioManager {
        }
    }

    /**
     * @hide
     * Used internally by telephony package to register an intent receiver for ACTION_MEDIA_BUTTON.
     * @param eventReceiver the component that will receive the media button key events,
     *          no-op if eventReceiver is null
     */
    public void registerMediaButtonEventReceiverForCalls(ComponentName eventReceiver) {
        if (eventReceiver == null) {
            return;
        }
        IAudioService service = getService();
        try {
            // eventReceiver != null
            service.registerMediaButtonEventReceiverForCalls(eventReceiver);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in registerMediaButtonEventReceiverForCalls", e);
        }
    }

    /**
     * @hide
     */
    public void unregisterMediaButtonEventReceiverForCalls() {
        IAudioService service = getService();
        try {
            service.unregisterMediaButtonEventReceiverForCalls();
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiverForCalls", e);
        }
    }

    /**
     * Unregister the receiver of MEDIA_BUTTON intents.
     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
+61 −5
Original line number Diff line number Diff line
@@ -3625,14 +3625,16 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            Log.e(TAG, "not dispatching invalid media key event " + keyEvent);
            return;
        }
        // event filtering based on audio mode
        // event filtering for telephony
        synchronized(mRingingLock) {
            if (mIsRinging || (getMode() == AudioSystem.MODE_IN_CALL) ||
                    (getMode() == AudioSystem.MODE_IN_COMMUNICATION) ||
                    (getMode() == AudioSystem.MODE_RINGTONE) ) {
            synchronized(mRCStack) {
                if ((mMediaReceiverForCalls != null) &&
                        (mIsRinging || (getMode() == AudioSystem.MODE_IN_CALL))) {
                    dispatchMediaKeyEventForCalls(keyEvent, needWakeLock);
                    return;
                }
            }
        }
        // event filtering based on voice-based interactions
        if (isValidVoiceInputKeyCode(keyEvent.getKeyCode())) {
            filterVoiceInputKeyEvent(keyEvent, needWakeLock);
@@ -3641,6 +3643,25 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
    }

    /**
     * Handles the dispatching of the media button events to the telephony package.
     * Precondition: mMediaReceiverForCalls != null
     * @param keyEvent a non-null KeyEvent whose key code is one of the supported media buttons
     * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held while this key event
     *     is dispatched.
     */
    private void dispatchMediaKeyEventForCalls(KeyEvent keyEvent, boolean needWakeLock) {
        Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
        keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
        keyIntent.setPackage(mMediaReceiverForCalls.getPackageName());
        if (needWakeLock) {
            mMediaEventWakeLock.acquire();
            keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED);
        }
        mContext.sendOrderedBroadcast(keyIntent, null, mKeyEventDone,
                mAudioHandler, Activity.RESULT_OK, null, null);
    }

    /**
     * Handles the dispatching of the media button events to one of the registered listeners,
     * or if there was none, broadcast an ACTION_MEDIA_BUTTON intent to the rest of the system.
@@ -4027,6 +4048,12 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
     */
    private final Stack<RemoteControlStackEntry> mRCStack = new Stack<RemoteControlStackEntry>();

    /**
     * The component the telephony package can register so telephony calls have priority to
     * handle media button events
     */
    private ComponentName mMediaReceiverForCalls = null;

    /**
     * Helper function:
     * Display in the log the current entries in the remote control focus stack
@@ -4380,6 +4407,35 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
    }

    /**
     * see AudioManager.registerMediaButtonEventReceiverForCalls(ComponentName c)
     * precondition: c != null
     */
    public void registerMediaButtonEventReceiverForCalls(ComponentName c) {
        if (mContext.checkCallingPermission("android.permission.MODIFY_PHONE_STATE")
                != PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "Invalid permissions to register media button receiver for calls");
            return;
        }
        synchronized(mRCStack) {
            mMediaReceiverForCalls = c;
        }
    }

    /**
     * see AudioManager.unregisterMediaButtonEventReceiverForCalls()
     */
    public void unregisterMediaButtonEventReceiverForCalls() {
        if (mContext.checkCallingPermission("android.permission.MODIFY_PHONE_STATE")
                != PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "Invalid permissions to unregister media button receiver for calls");
            return;
        }
        synchronized(mRCStack) {
            mMediaReceiverForCalls = null;
        }
    }

    /**
     * see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...)
     * Note: using this method with rcClient == null is a way to "disable" the IRemoteControlClient
+3 −0
Original line number Diff line number Diff line
@@ -109,6 +109,9 @@ interface IAudioService {
    oneway void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c);
    oneway void unregisterMediaButtonIntent(in PendingIntent pi,  in ComponentName c);

    oneway void registerMediaButtonEventReceiverForCalls(in ComponentName c);
    oneway void unregisterMediaButtonEventReceiverForCalls();

    oneway void registerRemoteControlClient(in PendingIntent mediaIntent,
           in IRemoteControlClient rcClient, in String callingPackageName);
    oneway void unregisterRemoteControlClient(in PendingIntent mediaIntent,