• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.keyguard.domain.interactor
18 
19 import android.media.AudioManager
20 import android.view.KeyEvent
21 import com.android.settingslib.volume.data.repository.AudioRepository
22 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.lifecycle.ExclusiveActivatable
25 import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
26 import javax.inject.Inject
27 
28 /** Handle media key events while on keyguard or bouncer. */
29 @SysUISingleton
30 class KeyguardMediaKeyInteractor
31 @Inject
32 constructor(
33     private val telephonyInteractor: TelephonyInteractor,
34     private val audioRepository: AudioRepository,
35 ) : ExclusiveActivatable() {
36 
37     /**
38      * Allows the media keys to work when the keyguard is showing. Forwards the relevant media keys
39      * to [AudioManager].
40      *
41      * @param event The key event
42      * @return whether the event was consumed as a media key.
43      */
processMediaKeyEventnull44     fun processMediaKeyEvent(event: KeyEvent): Boolean {
45         if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) {
46             return false
47         }
48         val keyCode = event.keyCode
49         if (event.action == KeyEvent.ACTION_DOWN) {
50             when (keyCode) {
51                 KeyEvent.KEYCODE_MEDIA_PLAY,
52                 KeyEvent.KEYCODE_MEDIA_PAUSE,
53                 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
54                     /* Suppress PLAY/PAUSE toggle when phone is ringing or
55                      * in-call to avoid music playback */
56                     // suppress key event
57                     return telephonyInteractor.isInCall.value
58                 }
59 
60                 KeyEvent.KEYCODE_MUTE,
61                 KeyEvent.KEYCODE_HEADSETHOOK,
62                 KeyEvent.KEYCODE_MEDIA_STOP,
63                 KeyEvent.KEYCODE_MEDIA_NEXT,
64                 KeyEvent.KEYCODE_MEDIA_PREVIOUS,
65                 KeyEvent.KEYCODE_MEDIA_REWIND,
66                 KeyEvent.KEYCODE_MEDIA_RECORD,
67                 KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
68                 KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK -> {
69                     audioRepository.dispatchMediaKeyEvent(event)
70                     return true
71                 }
72 
73                 KeyEvent.KEYCODE_VOLUME_UP,
74                 KeyEvent.KEYCODE_VOLUME_DOWN,
75                 KeyEvent.KEYCODE_VOLUME_MUTE -> return false
76             }
77         } else if (event.action == KeyEvent.ACTION_UP) {
78             when (keyCode) {
79                 KeyEvent.KEYCODE_MUTE,
80                 KeyEvent.KEYCODE_HEADSETHOOK,
81                 KeyEvent.KEYCODE_MEDIA_PLAY,
82                 KeyEvent.KEYCODE_MEDIA_PAUSE,
83                 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
84                 KeyEvent.KEYCODE_MEDIA_STOP,
85                 KeyEvent.KEYCODE_MEDIA_NEXT,
86                 KeyEvent.KEYCODE_MEDIA_PREVIOUS,
87                 KeyEvent.KEYCODE_MEDIA_REWIND,
88                 KeyEvent.KEYCODE_MEDIA_RECORD,
89                 KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
90                 KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK -> {
91                     audioRepository.dispatchMediaKeyEvent(event)
92                     return true
93                 }
94             }
95         }
96         return false
97     }
98 
onActivatednull99     override suspend fun onActivated(): Nothing {
100         // Collect to keep this flow hot for this interactor.
101         telephonyInteractor.isInCall.collect {}
102     }
103 }
104