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