1 /* 2 * Copyright (C) 2019 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.server.media; 18 19 import android.content.Context; 20 import android.media.AudioManager; 21 import android.media.AudioSystem; 22 import android.media.IAudioService; 23 import android.os.ServiceManager; 24 import android.util.AndroidException; 25 26 import com.android.internal.os.BaseCommand; 27 28 /** 29 * Command line tool to exercise AudioService.setStreamVolume() 30 * and AudioService.adjustStreamVolume() 31 */ 32 public class VolumeCtrl { 33 34 private static final String TAG = "VolumeCtrl"; 35 private static final String LOG_V = "[V]"; 36 private static final String LOG_E = "[E]"; 37 38 // --stream affects --set, --adj or --get options. 39 // --show affects --set and --adj options. 40 // --get can be used with --set, --adj or by itself. 41 public static final String USAGE = new String("the options are as follows: \n" 42 + "\t\t--stream STREAM selects the stream to control, see AudioManager.STREAM_*\n" 43 + "\t\t controls AudioManager.STREAM_MUSIC if no stream is specified\n" 44 + "\t\t--set INDEX sets the volume index value\n" 45 + "\t\t--adj DIRECTION adjusts the volume, use raise|same|lower for the direction\n" 46 + "\t\t--get outputs the current volume\n" 47 + "\t\t--show shows the UI during the volume change\n" 48 + "\texamples:\n" 49 + "\t\tadb shell media volume --show --stream 3 --set 11\n" 50 + "\t\tadb shell media volume --stream 0 --adj lower\n" 51 + "\t\tadb shell media volume --stream 3 --get\n" 52 ); 53 54 private static final int VOLUME_CONTROL_MODE_SET = 1; 55 private static final int VOLUME_CONTROL_MODE_ADJUST = 2; 56 57 private static final String ADJUST_LOWER = "lower"; 58 private static final String ADJUST_SAME = "same"; 59 private static final String ADJUST_RAISE = "raise"; 60 61 /** 62 * Runs a given MediaShellCommand 63 */ run(MediaShellCommand cmd)64 public static void run(MediaShellCommand cmd) throws Exception { 65 //---------------------------------------- 66 // Default parameters 67 int stream = AudioManager.STREAM_MUSIC; 68 int volIndex = 5; 69 int mode = 0; 70 int adjDir = AudioManager.ADJUST_RAISE; 71 boolean showUi = false; 72 boolean doGet = false; 73 74 //---------------------------------------- 75 // read options 76 String option; 77 String adjustment = null; 78 while ((option = cmd.getNextOption()) != null) { 79 switch (option) { 80 case "--show": 81 showUi = true; 82 break; 83 case "--get": 84 doGet = true; 85 cmd.log(LOG_V, "will get volume"); 86 break; 87 case "--stream": 88 stream = Integer.decode(cmd.getNextArgRequired()).intValue(); 89 cmd.log(LOG_V, 90 "will control stream=" + stream + " (" + streamName(stream) + ")"); 91 break; 92 case "--set": 93 volIndex = Integer.decode(cmd.getNextArgRequired()).intValue(); 94 mode = VOLUME_CONTROL_MODE_SET; 95 cmd.log(LOG_V, "will set volume to index=" + volIndex); 96 break; 97 case "--adj": 98 mode = VOLUME_CONTROL_MODE_ADJUST; 99 adjustment = cmd.getNextArgRequired(); 100 cmd.log(LOG_V, "will adjust volume"); 101 break; 102 default: 103 throw new IllegalArgumentException("Unknown argument " + option); 104 } 105 } 106 107 //------------------------------ 108 // Read options: validation 109 if (mode == VOLUME_CONTROL_MODE_ADJUST) { 110 if (adjustment == null) { 111 cmd.showError("Error: no valid volume adjustment (null)"); 112 return; 113 } 114 switch (adjustment) { 115 case ADJUST_RAISE: adjDir = AudioManager.ADJUST_RAISE; break; 116 case ADJUST_SAME: adjDir = AudioManager.ADJUST_SAME; break; 117 case ADJUST_LOWER: adjDir = AudioManager.ADJUST_LOWER; break; 118 default: 119 cmd.showError("Error: no valid volume adjustment, was " + adjustment 120 + ", expected " + ADJUST_LOWER + "|" + ADJUST_SAME + "|" 121 + ADJUST_RAISE); 122 return; 123 } 124 } 125 126 //---------------------------------------- 127 // Test initialization 128 cmd.log(LOG_V, "Connecting to AudioService"); 129 IAudioService audioService = IAudioService.Stub.asInterface(ServiceManager.checkService( 130 Context.AUDIO_SERVICE)); 131 if (audioService == null) { 132 cmd.log(LOG_E, BaseCommand.NO_SYSTEM_ERROR_CODE); 133 throw new AndroidException( 134 "Can't connect to audio service; is the system running?"); 135 } 136 137 if (mode == VOLUME_CONTROL_MODE_SET) { 138 if ((volIndex > audioService.getStreamMaxVolume(stream)) 139 || (volIndex < audioService.getStreamMinVolume(stream))) { 140 cmd.showError(String.format("Error: invalid volume index %d for stream %d " 141 + "(should be in [%d..%d])", volIndex, stream, 142 audioService.getStreamMinVolume(stream), 143 audioService.getStreamMaxVolume(stream))); 144 return; 145 } 146 } 147 148 //---------------------------------------- 149 // Non-interactive test 150 final int flag = showUi ? AudioManager.FLAG_SHOW_UI : 0; 151 final String pack = cmd.getClass().getPackage().getName(); 152 if (mode == VOLUME_CONTROL_MODE_SET) { 153 audioService.setStreamVolume(stream, volIndex, flag, pack/*callingPackage*/); 154 } else if (mode == VOLUME_CONTROL_MODE_ADJUST) { 155 audioService.adjustStreamVolume(stream, adjDir, flag, pack); 156 } 157 if (doGet) { 158 cmd.log(LOG_V, "volume is " + audioService.getStreamVolume(stream) 159 + " in range [" + audioService.getStreamMinVolume(stream) 160 + ".." + audioService.getStreamMaxVolume(stream) + "]"); 161 } 162 } 163 streamName(int stream)164 static String streamName(int stream) { 165 try { 166 return AudioSystem.STREAM_NAMES[stream]; 167 } catch (ArrayIndexOutOfBoundsException e) { 168 return "invalid stream"; 169 } 170 } 171 } 172