1 /* 2 ** 3 ** Copyright 2013, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 package com.android.commands.media; 19 20 import android.app.PendingIntent; 21 import android.content.Context; 22 import android.graphics.Bitmap; 23 import android.media.IAudioService; 24 import android.media.IRemoteControlDisplay; 25 import android.os.Bundle; 26 import android.os.RemoteException; 27 import android.os.ServiceManager; 28 import android.os.SystemClock; 29 import android.util.AndroidException; 30 import android.view.InputDevice; 31 import android.view.KeyCharacterMap; 32 import android.view.KeyEvent; 33 import com.android.internal.os.BaseCommand; 34 35 import java.io.BufferedReader; 36 import java.io.IOException; 37 import java.io.InputStreamReader; 38 import java.io.PrintStream; 39 40 public class Media extends BaseCommand { 41 42 private IAudioService mAudioService; 43 44 /** 45 * Command-line entry point. 46 * 47 * @param args The command-line arguments 48 */ 49 public static void main(String[] args) { 50 (new Media()).run(args); 51 } 52 53 public void onShowUsage(PrintStream out) { 54 out.println( 55 "usage: media [subcommand] [options]\n" + 56 " media dispatch KEY\n" + 57 " media remote-display\n" + 58 "\n" + 59 "media dispatch: dispatch a media key to the current media client.\n" + 60 " KEY may be: play, pause, play-pause, mute, headsethook,\n" + 61 " stop, next, previous, rewind, recordm fast-forword.\n" + 62 "media remote-display: monitor remote display updates.\n" 63 ); 64 } 65 66 public void onRun() throws Exception { 67 mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService( 68 Context.AUDIO_SERVICE)); 69 if (mAudioService == null) { 70 System.err.println(NO_SYSTEM_ERROR_CODE); 71 throw new AndroidException("Can't connect to audio service; is the system running?"); 72 } 73 74 String op = nextArgRequired(); 75 76 if (op.equals("dispatch")) { 77 runDispatch(); 78 } else if (op.equals("remote-display")) { 79 runRemoteDisplay(); 80 } else { 81 showError("Error: unknown command '" + op + "'"); 82 return; 83 } 84 } 85 86 private void sendMediaKey(KeyEvent event) { 87 try { 88 mAudioService.dispatchMediaKeyEvent(event); 89 } catch (RemoteException e) { 90 } 91 } 92 93 private void runDispatch() throws Exception { 94 String cmd = nextArgRequired(); 95 int keycode; 96 if ("play".equals(cmd)) { 97 keycode = KeyEvent.KEYCODE_MEDIA_PLAY; 98 } else if ("pause".equals(cmd)) { 99 keycode = KeyEvent.KEYCODE_MEDIA_PAUSE; 100 } else if ("play-pause".equals(cmd)) { 101 keycode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; 102 } else if ("mute".equals(cmd)) { 103 keycode = KeyEvent.KEYCODE_MUTE; 104 } else if ("headsethook".equals(cmd)) { 105 keycode = KeyEvent.KEYCODE_HEADSETHOOK; 106 } else if ("stop".equals(cmd)) { 107 keycode = KeyEvent.KEYCODE_MEDIA_STOP; 108 } else if ("next".equals(cmd)) { 109 keycode = KeyEvent.KEYCODE_MEDIA_NEXT; 110 } else if ("previous".equals(cmd)) { 111 keycode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; 112 } else if ("rewind".equals(cmd)) { 113 keycode = KeyEvent.KEYCODE_MEDIA_REWIND; 114 } else if ("record".equals(cmd)) { 115 keycode = KeyEvent.KEYCODE_MEDIA_RECORD; 116 } else if ("fast-forward".equals(cmd)) { 117 keycode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; 118 } else { 119 showError("Error: unknown dispatch code '" + cmd + "'"); 120 return; 121 } 122 123 final long now = SystemClock.uptimeMillis(); 124 sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0, 125 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); 126 sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0, 0, 127 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); 128 } 129 130 class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub { 131 RemoteDisplayMonitor() { 132 } 133 134 135 @Override 136 public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent, 137 boolean clearing) { 138 System.out.println("New client: id=" + clientGeneration 139 + " intent=" + clientMediaIntent + " clearing=" + clearing); 140 } 141 142 @Override 143 public void setEnabled(boolean enabled) { 144 System.out.println("New enable state= " + (enabled ? "enabled" : "disabled")); 145 } 146 147 @Override 148 public void setPlaybackState(int generationId, int state, long stateChangeTimeMs, 149 long currentPosMs, float speed) { 150 System.out.println("New state: id=" + generationId + " state=" + state 151 + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed); 152 } 153 154 @Override 155 public void setTransportControlInfo(int generationId, int transportControlFlags, 156 int posCapabilities) { 157 System.out.println("New control info: id=" + generationId 158 + " flags=0x" + Integer.toHexString(transportControlFlags) 159 + " cap=0x" + Integer.toHexString(posCapabilities)); 160 } 161 162 @Override 163 public void setMetadata(int generationId, Bundle metadata) { 164 System.out.println("New metadata: id=" + generationId 165 + " data=" + metadata); 166 } 167 168 @Override 169 public void setArtwork(int generationId, Bitmap artwork) { 170 System.out.println("New artwork: id=" + generationId 171 + " art=" + artwork); 172 } 173 174 @Override 175 public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) { 176 System.out.println("New metadata+artwork: id=" + generationId 177 + " data=" + metadata + " art=" + artwork); 178 } 179 180 void printUsageMessage() { 181 System.out.println("Monitoring remote control displays... available commands:"); 182 System.out.println("(q)uit: finish monitoring"); 183 } 184 185 void run() throws RemoteException { 186 printUsageMessage(); 187 188 mAudioService.registerRemoteControlDisplay(this, 0, 0); 189 190 try { 191 InputStreamReader converter = new InputStreamReader(System.in); 192 BufferedReader in = new BufferedReader(converter); 193 String line; 194 195 while ((line = in.readLine()) != null) { 196 boolean addNewline = true; 197 if (line.length() <= 0) { 198 addNewline = false; 199 } else if ("q".equals(line) || "quit".equals(line)) { 200 break; 201 } else { 202 System.out.println("Invalid command: " + line); 203 } 204 205 synchronized (this) { 206 if (addNewline) { 207 System.out.println(""); 208 } 209 printUsageMessage(); 210 } 211 } 212 213 } catch (IOException e) { 214 e.printStackTrace(); 215 } finally { 216 mAudioService.unregisterRemoteControlDisplay(this); 217 } 218 } 219 } 220 221 private void runRemoteDisplay() throws Exception { 222 RemoteDisplayMonitor monitor = new RemoteDisplayMonitor(); 223 monitor.run(); 224 } 225 } 226