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 Brown#define LOG_TAG "RemoteDisplay" 18cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 19cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include "jni.h" 20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include "JNIHelp.h" 21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 22cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include "android_os_Parcel.h" 23cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include "android_util_Binder.h" 24cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 25ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 26cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <android_runtime/android_view_Surface.h> 2787eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include <android_runtime/Log.h> 28cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 29cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <binder/IServiceManager.h> 30cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 31d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden#include <gui/IGraphicBufferProducer.h> 32cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <media/IMediaPlayerService.h> 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <media/IRemoteDisplay.h> 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <media/IRemoteDisplayClient.h> 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <utils/Log.h> 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown#include <ScopedUtfChars.h> 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownnamespace android { 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownstatic struct { 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown jmethodID notifyDisplayConnected; 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown jmethodID notifyDisplayDisconnected; 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown jmethodID notifyDisplayError; 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} gRemoteDisplayClassInfo; 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown// ---------------------------------------------------------------------------- 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownclass NativeRemoteDisplayClient : public BnRemoteDisplayClient { 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpublic: 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NativeRemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj) : 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRemoteDisplayObjGlobal(env->NewGlobalRef(remoteDisplayObj)) { 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownprotected: 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ~NativeRemoteDisplayClient() { 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->DeleteGlobalRef(mRemoteDisplayObjGlobal); 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpublic: 64d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden virtual void onDisplayConnected(const sp<IGraphicBufferProducer>& bufferProducer, 651f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang uint32_t width, uint32_t height, uint32_t flags, uint32_t session) { 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 6829479ebe1007361222bf6ab4d5e2a27927d4b8e8Mathias Agopian jobject surfaceObj = android_view_Surface_createFromIGraphicBufferProducer(env, bufferProducer); 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (surfaceObj == NULL) { 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ALOGE("Could not create Surface from surface texture %p provided by media server.", 71d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden bufferProducer.get()); 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->CallVoidMethod(mRemoteDisplayObjGlobal, 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown gRemoteDisplayClassInfo.notifyDisplayConnected, 771f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang surfaceObj, width, height, flags, session); 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->DeleteLocalRef(surfaceObj); 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown checkAndClearExceptionFromCallback(env, "notifyDisplayConnected"); 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 81cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 82cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown virtual void onDisplayDisconnected() { 83cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 84cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 85cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->CallVoidMethod(mRemoteDisplayObjGlobal, 86cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown gRemoteDisplayClassInfo.notifyDisplayDisconnected); 87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown checkAndClearExceptionFromCallback(env, "notifyDisplayDisconnected"); 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown virtual void onDisplayError(int32_t error) { 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->CallVoidMethod(mRemoteDisplayObjGlobal, 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown gRemoteDisplayClassInfo.notifyDisplayError, error); 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown checkAndClearExceptionFromCallback(env, "notifyDisplayError"); 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownprivate: 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown jobject mRemoteDisplayObjGlobal; 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (env->ExceptionCheck()) { 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ALOGE("An exception was thrown by callback '%s'.", methodName); 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown LOGE_EX(env); 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown env->ExceptionClear(); 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}; 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownclass NativeRemoteDisplay { 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpublic: 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NativeRemoteDisplay(const sp<IRemoteDisplay>& display, 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown const sp<NativeRemoteDisplayClient>& client) : 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplay(display), mClient(client) { 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ~NativeRemoteDisplay() { 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplay->dispose(); 119cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 120cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1211f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang void pause() { 1221f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDisplay->pause(); 1231f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 1241f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 1251f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang void resume() { 1261f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDisplay->resume(); 1271f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 1281f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 129cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownprivate: 130cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sp<IRemoteDisplay> mDisplay; 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sp<NativeRemoteDisplayClient> mClient; 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}; 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown// ---------------------------------------------------------------------------- 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 137fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganovstatic jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr, 138fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov jstring opPackageNameStr) { 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ScopedUtfChars iface(env, ifaceStr); 140fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov ScopedUtfChars opPackageName(env, opPackageNameStr); 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sp<IServiceManager> sm = defaultServiceManager(); 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>( 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sm->getService(String16("media.player"))); 145cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (service == NULL) { 146cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ALOGE("Could not obtain IMediaPlayerService from service manager"); 147cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return 0; 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj)); 151fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov sp<IRemoteDisplay> display = service->listenForRemoteDisplay(String16(opPackageName.c_str()), 152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown client, String8(iface.c_str())); 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (display == NULL) { 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ALOGE("Media player service rejected request to listen for remote display '%s'.", 155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown iface.c_str()); 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return 0; 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NativeRemoteDisplay* wrapper = new NativeRemoteDisplay(display, client); 160075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return reinterpret_cast<jlong>(wrapper); 161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 163075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic void nativePause(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) { 1641f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr); 1651f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang wrapper->pause(); 1661f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang} 1671f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 168075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic void nativeResume(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) { 1691f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr); 1701f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang wrapper->resume(); 1711f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang} 1721f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 173075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) { 174cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr); 175cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown delete wrapper; 176cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 177cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 178cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown// ---------------------------------------------------------------------------- 179cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 18076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 181fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov {"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J", 182cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown (void*)nativeListen }, 183075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat {"nativeDispose", "(J)V", 184cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown (void*)nativeDispose }, 185075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat {"nativePause", "(J)V", 1861f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang (void*)nativePause }, 187075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat {"nativeResume", "(J)V", 1881f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang (void*)nativeResume }, 189cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}; 190cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 191cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownint register_android_media_RemoteDisplay(JNIEnv* env) 192cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown{ 193ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe int err = RegisterMethodsOrDie(env, "android/media/RemoteDisplay", gMethods, NELEM(gMethods)); 194ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 195ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe jclass clazz = FindClassOrDie(env, "android/media/RemoteDisplay"); 196ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gRemoteDisplayClassInfo.notifyDisplayConnected = GetMethodIDOrDie(env, 197ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe clazz, "notifyDisplayConnected", "(Landroid/view/Surface;IIII)V"); 198ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gRemoteDisplayClassInfo.notifyDisplayDisconnected = GetMethodIDOrDie(env, 199ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe clazz, "notifyDisplayDisconnected", "()V"); 200ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gRemoteDisplayClassInfo.notifyDisplayError = GetMethodIDOrDie(env, 201ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe clazz, "notifyDisplayError", "(I)V"); 202cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return err; 203cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 204cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 205cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}; 206