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; 40fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov private final String mOpPackageName; 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 42075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private long mPtr; 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 44fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov private native long nativeListen(String iface, String opPackageName); 45075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativeDispose(long ptr); 46075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativePause(long ptr); 47075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private native void nativeResume(long ptr); 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 49fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov private RemoteDisplay(Listener listener, Handler handler, String opPackageName) { 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener = listener; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler = handler; 52fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov mOpPackageName = opPackageName; 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown protected void finalize() throws Throwable { 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown try { 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown dispose(true); 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } finally { 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.finalize(); 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Starts listening for displays to be connected on the specified interface. 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param iface The interface address and port in the form "x.x.x.x:y". 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param listener The listener to invoke when displays are connected or disconnected. 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * @param handler The handler on which to invoke the listener. 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 71fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov public static RemoteDisplay listen(String iface, Listener listener, Handler handler, 72fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov String opPackageName) { 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (iface == null) { 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("iface must not be null"); 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (listener == null) { 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("listener must not be null"); 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (handler == null) { 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalArgumentException("handler must not be null"); 81cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 82cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 83fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov RemoteDisplay display = new RemoteDisplay(listener, handler, opPackageName); 84cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown display.startListening(iface); 85cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return display; 86cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Disconnects the remote display and stops listening for new connections. 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dispose() { 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown dispose(false); 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 951f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void pause() { 961f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang nativePause(mPtr); 971f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 981f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 991f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void resume() { 1001f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang nativeResume(mPtr); 1011f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 1021f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void dispose(boolean finalized) { 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mPtr != 0) { 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mGuard != null) { 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (finalized) { 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.warnIfOpen(); 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.close(); 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown nativeDispose(mPtr); 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mPtr = 0; 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void startListening(String iface) { 119fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov mPtr = nativeListen(iface, mOpPackageName); 120cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mPtr == 0) { 121cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown throw new IllegalStateException("Could not start listening for " 122cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "remote display connection on \"" + iface + "\""); 123cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 124cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mGuard.open("dispose"); 125cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 126cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 127cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 128cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayConnected(final Surface surface, 1291f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang final int width, final int height, final int flags, final int session) { 130cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 1331f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mListener.onDisplayConnected(surface, width, height, flags, session); 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 137cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 138cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayDisconnected() { 140cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener.onDisplayDisconnected(); 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 145cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 146cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 147cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called from native. 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void notifyDisplayError(final int error) { 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.post(new Runnable() { 151cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener.onDisplayError(error); 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Listener invoked when the remote display connection changes state. 160cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public interface Listener { 1621f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang void onDisplayConnected(Surface surface, 1631f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang int width, int height, int flags, int session); 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayDisconnected(); 165cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayError(int error); 166cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 167cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 168