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