1cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/* 2cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 4cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * you may not use this file except in compliance with the License. 6cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * You may obtain a copy of the License at 7cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 8cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 10cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Unless required by applicable law or agreed to in writing, software 11cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * See the License for the specific language governing permissions and 14cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * limitations under the License. 15cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 16cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 17cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpackage android.media; 18cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 19cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport dalvik.system.CloseGuard; 20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 22cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.view.Surface; 23cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 24cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 25cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Listens for Wifi remote display connections managed by the media server. 26cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 27cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @hide 28cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 29cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpublic final class RemoteDisplay { 30cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /* these constants must be kept in sync with IRemoteDisplayClient.h */ 31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 32cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public static final int DISPLAY_FLAG_SECURE = 1 << 0; 33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public static final int DISPLAY_ERROR_UNKOWN = 1; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public static final int DISPLAY_ERROR_CONNECTION_DROPPED = 2; 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final CloseGuard mGuard = CloseGuard.get(); 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Listener mListener; 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Handler mHandler; 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 41075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private long mPtr; 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 43075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native long nativeListen(String iface); 44075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativeDispose(long ptr); 45075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativePause(long ptr); 46075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativeResume(long ptr); 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private RemoteDisplay(Listener listener, Handler handler) { 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener = listener; 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler = handler; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown protected void finalize() throws Throwable { 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown try { 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown dispose(true); 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } finally { 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.finalize(); 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Starts listening for displays to be connected on the specified interface. 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param iface The interface address and port in the form "x.x.x.x:y". 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param listener The listener to invoke when displays are connected or disconnected. 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param handler The handler on which to invoke the listener. 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public static RemoteDisplay listen(String iface, Listener listener, Handler handler) { 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (iface == null) { 71cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("iface must not be null"); 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (listener == null) { 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("listener must not be null"); 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (handler == null) { 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("handler must not be null"); 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown RemoteDisplay display = new RemoteDisplay(listener, handler); 81cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown display.startListening(iface); 82cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return display; 83cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 84cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 85cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 86cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Disconnects the remote display and stops listening for new connections. 87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dispose() { 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown dispose(false); 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 921f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void pause() { 931f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang nativePause(mPtr); 941f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 951f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 961f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void resume() { 971f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang nativeResume(mPtr); 981f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 991f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void dispose(boolean finalized) { 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mPtr != 0) { 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mGuard != null) { 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (finalized) { 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.warnIfOpen(); 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.close(); 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown nativeDispose(mPtr); 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mPtr = 0; 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void startListening(String iface) { 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mPtr = nativeListen(iface); 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mPtr == 0) { 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalStateException("Could not start listening for " 119cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "remote display connection on \"" + iface + "\""); 120cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 121cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.open("dispose"); 122cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 123cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 124cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 125cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayConnected(final Surface surface, 1261f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang final int width, final int height, final int flags, final int session) { 127cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 128cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 129cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 1301f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mListener.onDisplayConnected(surface, width, height, flags, session); 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayDisconnected() { 137cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 138cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 140cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener.onDisplayDisconnected(); 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 145cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 146cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayError(final int error) { 147cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener.onDisplayError(error); 151cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Listener invoked when the remote display connection changes state. 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public interface Listener { 1591f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang void onDisplayConnected(Surface surface, 1601f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang int width, int height, int flags, int session); 161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayDisconnected(); 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayError(int error); 163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 165