Move to Android N-MR1 SDK.
[android_tools.git] / sdk / sources / android-25 / com / android / commands / media / Media.java
blobd7f23cb440989beb23f27d3cc3ec737e70d347f6
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
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.
18 package com.android.commands.media;
20 import android.app.ActivityManager;
21 import android.content.Context;
22 import android.content.pm.ParceledListSlice;
23 import android.media.MediaMetadata;
24 import android.media.session.ISessionController;
25 import android.media.session.ISessionControllerCallback;
26 import android.media.session.ISessionManager;
27 import android.media.session.ParcelableVolumeInfo;
28 import android.media.session.PlaybackState;
29 import android.os.Bundle;
30 import android.os.HandlerThread;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.os.ServiceManager;
34 import android.os.SystemClock;
35 import android.util.AndroidException;
36 import android.view.InputDevice;
37 import android.view.KeyCharacterMap;
38 import android.view.KeyEvent;
40 import com.android.internal.os.BaseCommand;
42 import java.io.BufferedReader;
43 import java.io.IOException;
44 import java.io.InputStreamReader;
45 import java.io.PrintStream;
46 import java.util.List;
48 public class Media extends BaseCommand {
49 private ISessionManager mSessionService;
51 /**
52 * Command-line entry point.
54 * @param args The command-line arguments
56 public static void main(String[] args) {
57 (new Media()).run(args);
60 public void onShowUsage(PrintStream out) {
61 out.println(
62 "usage: media [subcommand] [options]\n" +
63 " media dispatch KEY\n" +
64 " media list-sessions\n" +
65 " media monitor <tag>\n" +
66 "\n" +
67 "media dispatch: dispatch a media key to the system.\n" +
68 " KEY may be: play, pause, play-pause, mute, headsethook,\n" +
69 " stop, next, previous, rewind, record, fast-forword.\n" +
70 "media list-sessions: print a list of the current sessions.\n" +
71 "media monitor: monitor updates to the specified session.\n" +
72 " Use the tag from list-sessions.\n"
76 public void onRun() throws Exception {
77 mSessionService = ISessionManager.Stub.asInterface(ServiceManager.checkService(
78 Context.MEDIA_SESSION_SERVICE));
79 if (mSessionService == null) {
80 System.err.println(NO_SYSTEM_ERROR_CODE);
81 throw new AndroidException(
82 "Can't connect to media session service; is the system running?");
85 String op = nextArgRequired();
87 if (op.equals("dispatch")) {
88 runDispatch();
89 } else if (op.equals("list-sessions")) {
90 runListSessions();
91 } else if (op.equals("monitor")) {
92 runMonitor();
93 } else {
94 showError("Error: unknown command '" + op + "'");
95 return;
99 private void sendMediaKey(KeyEvent event) {
100 try {
101 mSessionService.dispatchMediaKeyEvent(event, false);
102 } catch (RemoteException e) {
106 private void runMonitor() throws Exception {
107 String id = nextArgRequired();
108 if (id == null) {
109 showError("Error: must include a session id");
110 return;
112 boolean success = false;
113 try {
114 List<IBinder> sessions = mSessionService
115 .getSessions(null, ActivityManager.getCurrentUser());
116 for (IBinder session : sessions) {
117 ISessionController controller = ISessionController.Stub.asInterface(session);
118 try {
119 if (controller != null && id.equals(controller.getTag())) {
120 ControllerMonitor monitor = new ControllerMonitor(controller);
121 monitor.run();
122 success = true;
123 break;
125 } catch (RemoteException e) {
126 // ignore
129 } catch (Exception e) {
130 System.out.println("***Error monitoring session*** " + e.getMessage());
132 if (!success) {
133 System.out.println("No session found with id " + id);
137 private void runDispatch() throws Exception {
138 String cmd = nextArgRequired();
139 int keycode;
140 if ("play".equals(cmd)) {
141 keycode = KeyEvent.KEYCODE_MEDIA_PLAY;
142 } else if ("pause".equals(cmd)) {
143 keycode = KeyEvent.KEYCODE_MEDIA_PAUSE;
144 } else if ("play-pause".equals(cmd)) {
145 keycode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
146 } else if ("mute".equals(cmd)) {
147 keycode = KeyEvent.KEYCODE_MUTE;
148 } else if ("headsethook".equals(cmd)) {
149 keycode = KeyEvent.KEYCODE_HEADSETHOOK;
150 } else if ("stop".equals(cmd)) {
151 keycode = KeyEvent.KEYCODE_MEDIA_STOP;
152 } else if ("next".equals(cmd)) {
153 keycode = KeyEvent.KEYCODE_MEDIA_NEXT;
154 } else if ("previous".equals(cmd)) {
155 keycode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
156 } else if ("rewind".equals(cmd)) {
157 keycode = KeyEvent.KEYCODE_MEDIA_REWIND;
158 } else if ("record".equals(cmd)) {
159 keycode = KeyEvent.KEYCODE_MEDIA_RECORD;
160 } else if ("fast-forward".equals(cmd)) {
161 keycode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
162 } else {
163 showError("Error: unknown dispatch code '" + cmd + "'");
164 return;
167 final long now = SystemClock.uptimeMillis();
168 sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
169 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
170 sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0, 0,
171 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
174 class ControllerMonitor extends ISessionControllerCallback.Stub {
175 private final ISessionController mController;
177 public ControllerMonitor(ISessionController controller) {
178 mController = controller;
181 @Override
182 public void onSessionDestroyed() {
183 System.out.println("onSessionDestroyed. Enter q to quit.");
187 @Override
188 public void onEvent(String event, Bundle extras) {
189 System.out.println("onSessionEvent event=" + event + ", extras=" + extras);
192 @Override
193 public void onPlaybackStateChanged(PlaybackState state) {
194 System.out.println("onPlaybackStateChanged " + state);
197 @Override
198 public void onMetadataChanged(MediaMetadata metadata) {
199 String mmString = metadata == null ? null : "title=" + metadata
200 .getDescription();
201 System.out.println("onMetadataChanged " + mmString);
204 @Override
205 public void onQueueChanged(ParceledListSlice queue) throws RemoteException {
206 System.out.println("onQueueChanged, "
207 + (queue == null ? "null queue" : " size=" + queue.getList().size()));
210 @Override
211 public void onQueueTitleChanged(CharSequence title) throws RemoteException {
212 System.out.println("onQueueTitleChange " + title);
215 @Override
216 public void onExtrasChanged(Bundle extras) throws RemoteException {
217 System.out.println("onExtrasChanged " + extras);
220 @Override
221 public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
222 System.out.println("onVolumeInfoChanged " + info);
225 void printUsageMessage() {
226 try {
227 System.out.println("V2Monitoring session " + mController.getTag()
228 + "... available commands: play, pause, next, previous");
229 } catch (RemoteException e) {
230 System.out.println("Error trying to monitor session!");
232 System.out.println("(q)uit: finish monitoring");
235 void run() throws RemoteException {
236 printUsageMessage();
237 HandlerThread cbThread = new HandlerThread("MediaCb") {
238 @Override
239 protected void onLooperPrepared() {
240 try {
241 mController.registerCallbackListener(ControllerMonitor.this);
242 } catch (RemoteException e) {
243 System.out.println("Error registering monitor callback");
247 cbThread.start();
249 try {
250 InputStreamReader converter = new InputStreamReader(System.in);
251 BufferedReader in = new BufferedReader(converter);
252 String line;
254 while ((line = in.readLine()) != null) {
255 boolean addNewline = true;
256 if (line.length() <= 0) {
257 addNewline = false;
258 } else if ("q".equals(line) || "quit".equals(line)) {
259 break;
260 } else if ("play".equals(line)) {
261 mController.play();
262 } else if ("pause".equals(line)) {
263 mController.pause();
264 } else if ("next".equals(line)) {
265 mController.next();
266 } else if ("previous".equals(line)) {
267 mController.previous();
268 } else {
269 System.out.println("Invalid command: " + line);
272 synchronized (this) {
273 if (addNewline) {
274 System.out.println("");
276 printUsageMessage();
279 } catch (IOException e) {
280 e.printStackTrace();
281 } finally {
282 cbThread.getLooper().quit();
283 try {
284 mController.unregisterCallbackListener(this);
285 } catch (Exception e) {
286 // ignoring
292 private void runListSessions() {
293 System.out.println("Sessions:");
294 try {
295 List<IBinder> sessions = mSessionService
296 .getSessions(null, ActivityManager.getCurrentUser());
297 for (IBinder session : sessions) {
299 ISessionController controller = ISessionController.Stub.asInterface(session);
300 if (controller != null) {
301 try {
302 System.out.println(" tag=" + controller.getTag()
303 + ", package=" + controller.getPackageName());
304 } catch (RemoteException e) {
305 // ignore
309 } catch (Exception e) {
310 System.out.println("***Error listing sessions***");