1 /*
2  * Copyright (C) 2022 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.media.muteawait
18 
19 import android.annotation.SuppressLint
20 import android.media.AudioAttributes.USAGE_MEDIA
21 import android.media.AudioDeviceAttributes
22 import android.media.AudioManager
23 import com.android.systemui.CoreStartable
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.statusbar.commandline.Command
26 import com.android.systemui.statusbar.commandline.CommandRegistry
27 import dagger.Binds
28 import dagger.Module
29 import dagger.multibindings.ClassKey
30 import dagger.multibindings.IntoMap
31 import java.io.PrintWriter
32 import java.util.concurrent.TimeUnit
33 import javax.inject.Inject
34 
35 /** A command line interface to manually test [MediaMuteAwaitConnectionManager]. */
36 @SysUISingleton
37 class MediaMuteAwaitConnectionCli @Inject constructor(
38     private val commandRegistry: CommandRegistry,
39     private val audioManager: AudioManager,
40 ) : CoreStartable {
startnull41     override fun start() {
42         commandRegistry.registerCommand(MEDIA_MUTE_AWAIT_COMMAND) { MuteAwaitCommand() }
43     }
44 
45     inner class MuteAwaitCommand : Command {
46         @SuppressLint("MissingPermission")
executenull47         override fun execute(pw: PrintWriter, args: List<String>) {
48             val device = AudioDeviceAttributes(
49                 AudioDeviceAttributes.ROLE_OUTPUT,
50                 /* type= */ Integer.parseInt(args[0]),
51                 ADDRESS,
52                 /* name= */ args[1],
53                 listOf(),
54                 listOf(),
55             )
56             val startOrCancel = args[2]
57 
58             when (startOrCancel) {
59                 START ->
60                     audioManager.muteAwaitConnection(
61                             intArrayOf(USAGE_MEDIA), device, TIMEOUT, TIMEOUT_UNITS
62                     )
63                 CANCEL -> audioManager.cancelMuteAwaitConnection(device)
64                 else -> pw.println("Must specify `$START` or `$CANCEL`; was $startOrCancel")
65             }
66         }
helpnull67         override fun help(pw: PrintWriter) {
68             pw.println("Usage: adb shell cmd statusbar $MEDIA_MUTE_AWAIT_COMMAND " +
69                     "[type] [name] [$START|$CANCEL]")
70         }
71     }
72 
73     @Module
74     interface StartableModule {
75         @Binds
76         @IntoMap
77         @ClassKey(MediaMuteAwaitConnectionCli::class)
bindsMediaMuteAwaitConnectionClinull78         fun bindsMediaMuteAwaitConnectionCli(impl: MediaMuteAwaitConnectionCli): CoreStartable
79     }
80 }
81 
82 private const val MEDIA_MUTE_AWAIT_COMMAND = "media-mute-await"
83 private const val START = "start"
84 private const val CANCEL = "cancel"
85 private const val ADDRESS = "address"
86 private const val TIMEOUT = 5L
87 private val TIMEOUT_UNITS = TimeUnit.SECONDS
88