1/* 2 * Copyright (C) 2012 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 17package android.media; 18 19import dalvik.system.CloseGuard; 20 21import android.os.Handler; 22import android.view.Surface; 23 24/** 25 * Listens for Wifi remote display connections managed by the media server. 26 * 27 * @hide 28 */ 29public final class RemoteDisplay { 30 /* these constants must be kept in sync with IRemoteDisplayClient.h */ 31 32 public static final int DISPLAY_FLAG_SECURE = 1 << 0; 33 34 public static final int DISPLAY_ERROR_UNKOWN = 1; 35 public static final int DISPLAY_ERROR_CONNECTION_DROPPED = 2; 36 37 private final CloseGuard mGuard = CloseGuard.get(); 38 private final Listener mListener; 39 private final Handler mHandler; 40 41 private long mPtr; 42 43 private native long nativeListen(String iface); 44 private native void nativeDispose(long ptr); 45 private native void nativePause(long ptr); 46 private native void nativeResume(long ptr); 47 48 private RemoteDisplay(Listener listener, Handler handler) { 49 mListener = listener; 50 mHandler = handler; 51 } 52 53 @Override 54 protected void finalize() throws Throwable { 55 try { 56 dispose(true); 57 } finally { 58 super.finalize(); 59 } 60 } 61 62 /** 63 * Starts listening for displays to be connected on the specified interface. 64 * 65 * @param iface The interface address and port in the form "x.x.x.x:y". 66 * @param listener The listener to invoke when displays are connected or disconnected. 67 * @param handler The handler on which to invoke the listener. 68 */ 69 public static RemoteDisplay listen(String iface, Listener listener, Handler handler) { 70 if (iface == null) { 71 throw new IllegalArgumentException("iface must not be null"); 72 } 73 if (listener == null) { 74 throw new IllegalArgumentException("listener must not be null"); 75 } 76 if (handler == null) { 77 throw new IllegalArgumentException("handler must not be null"); 78 } 79 80 RemoteDisplay display = new RemoteDisplay(listener, handler); 81 display.startListening(iface); 82 return display; 83 } 84 85 /** 86 * Disconnects the remote display and stops listening for new connections. 87 */ 88 public void dispose() { 89 dispose(false); 90 } 91 92 public void pause() { 93 nativePause(mPtr); 94 } 95 96 public void resume() { 97 nativeResume(mPtr); 98 } 99 100 private void dispose(boolean finalized) { 101 if (mPtr != 0) { 102 if (mGuard != null) { 103 if (finalized) { 104 mGuard.warnIfOpen(); 105 } else { 106 mGuard.close(); 107 } 108 } 109 110 nativeDispose(mPtr); 111 mPtr = 0; 112 } 113 } 114 115 private void startListening(String iface) { 116 mPtr = nativeListen(iface); 117 if (mPtr == 0) { 118 throw new IllegalStateException("Could not start listening for " 119 + "remote display connection on \"" + iface + "\""); 120 } 121 mGuard.open("dispose"); 122 } 123 124 // Called from native. 125 private void notifyDisplayConnected(final Surface surface, 126 final int width, final int height, final int flags, final int session) { 127 mHandler.post(new Runnable() { 128 @Override 129 public void run() { 130 mListener.onDisplayConnected(surface, width, height, flags, session); 131 } 132 }); 133 } 134 135 // Called from native. 136 private void notifyDisplayDisconnected() { 137 mHandler.post(new Runnable() { 138 @Override 139 public void run() { 140 mListener.onDisplayDisconnected(); 141 } 142 }); 143 } 144 145 // Called from native. 146 private void notifyDisplayError(final int error) { 147 mHandler.post(new Runnable() { 148 @Override 149 public void run() { 150 mListener.onDisplayError(error); 151 } 152 }); 153 } 154 155 /** 156 * Listener invoked when the remote display connection changes state. 157 */ 158 public interface Listener { 159 void onDisplayConnected(Surface surface, 160 int width, int height, int flags, int session); 161 void onDisplayDisconnected(); 162 void onDisplayError(int error); 163 } 164} 165