/* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.android.server.display; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.media.RemoteDisplay; import android.os.Handler; import android.util.Slog; import android.content.Context; class ExtendedRemoteDisplayHelper { private static final String TAG = "ExtendedRemoteDisplayHelper"; // ExtendedRemoteDisplay class // ExtendedRemoteDisplay is an enhanced RemoteDisplay. It has // similar interface as RemoteDisplay class private static Class sExtRemoteDisplayClass; // Method object for the API ExtendedRemoteDisplay.Listen // ExtendedRemoteDisplay.Listen has the same API signature as // RemoteDisplay.Listen except for an additional argument to pass the // Context private static Method sExtRemoteDisplayListen; // Method Object for the API ExtendedRemoteDisplay.Dispose // ExtendedRemoteDisplay.Dispose follows the same API signature as // RemoteDisplay.Dispose private static Method sExtRemoteDisplayDispose; static { //Check availability of ExtendedRemoteDisplay runtime try { sExtRemoteDisplayClass = Class.forName("com.qualcomm.wfd.ExtendedRemoteDisplay"); } catch (Throwable t) { Slog.i(TAG, "ExtendedRemoteDisplay Not available."); } if(sExtRemoteDisplayClass != null) { // If ExtendedRemoteDisplay is available find the methods Slog.i(TAG, "ExtendedRemoteDisplay Is available. Find Methods"); try { Class args[] = { String.class, RemoteDisplay.Listener.class, Handler.class, Context.class }; sExtRemoteDisplayListen = sExtRemoteDisplayClass.getDeclaredMethod("listen", args); } catch (Throwable t) { Slog.i(TAG, "ExtendedRemoteDisplay.listen Not available."); } try { Class args[] = {}; sExtRemoteDisplayDispose = sExtRemoteDisplayClass.getDeclaredMethod("dispose", args); } catch (Throwable t) { Slog.i(TAG, "ExtendedRemoteDisplay.dispose Not available."); } } } /** * Starts listening for displays to be connected on the specified interface. * * @param iface The interface address and port in the form "x.x.x.x:y". * @param listener The listener to invoke * when displays are connected or disconnected. * @param handler The handler on which to invoke the listener. * @param context The current service context * */ public static Object listen(String iface, RemoteDisplay.Listener listener, Handler handler, Context context) { Object extRemoteDisplay = null; Slog.i(TAG, "ExtendedRemoteDisplay.listen"); if(sExtRemoteDisplayListen != null && sExtRemoteDisplayDispose != null){ try { extRemoteDisplay = sExtRemoteDisplayListen.invoke(null, iface, listener, handler, context); } catch (InvocationTargetException e) { Slog.i(TAG, "ExtendedRemoteDisplay.listen - InvocationTargetException"); Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { throw new RuntimeException(e); } } catch (IllegalAccessException e) { Slog.i(TAG, "ExtendedRemoteDisplay.listen -IllegalAccessException"); e.printStackTrace(); } } return extRemoteDisplay; } /** * Disconnects the remote display and stops listening for new connections. */ public static void dispose(Object extRemoteDisplay) { Slog.i(TAG, "ExtendedRemoteDisplay.dispose"); try{ sExtRemoteDisplayDispose.invoke(extRemoteDisplay); } catch (InvocationTargetException e) { Slog.i(TAG, "ExtendedRemoteDisplay.dispose - InvocationTargetException"); Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { throw new RuntimeException(e); } } catch (IllegalAccessException e) { Slog.i(TAG, "ExtendedRemoteDisplay.dispose-IllegalAccessException"); e.printStackTrace(); } } /** * Checks if ExtendedRemoteDisplay is available */ public static boolean isAvailable() { if(sExtRemoteDisplayClass != null && sExtRemoteDisplayDispose != null && sExtRemoteDisplayListen != null) { Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Available."); return true; } Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Not Available."); return false; } }