author | Tellen Yu <tellen.yu@amlogic.com> | 2018-01-19 08:04:33 (GMT) |
---|---|---|
committer | Tellen Yu <tellen.yu@amlogic.com> | 2018-01-29 05:23:49 (GMT) |
commit | 334498d01acf41a5093348cffdc8dff3dfcea53f (patch) | |
tree | 3d9dc93fee3f789b5f2c2698adadbaed8b9ccdf1 | |
parent | d946a3cc75b4d9bd5a71da14b1c8d90398756f87 (diff) | |
download | tv-334498d01acf41a5093348cffdc8dff3dfcea53f.zip tv-334498d01acf41a5093348cffdc8dff3dfcea53f.tar.gz tv-334498d01acf41a5093348cffdc8dff3dfcea53f.tar.bz2 |
tvinput: add porting tvinput to HIDL architecture [1/12]
PD# 157786
need use hwbinder instead of binder for RPC since from O
Change-Id: I7f8084d3152546e2d90ad77c9408bb47cbc5befc
-rw-r--r-- | core/java/Android.mk | 23 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvControlManager.java | 411 | ||||
-rw-r--r-- | core/java/droidlogic.tv.software.core.xml | 20 | ||||
-rw-r--r-- | core/jni/Android.mk | 22 | ||||
-rw-r--r-- | core/jni/com_droidlogic_app_tv_TvControlManager.cpp | 75 | ||||
-rw-r--r-- | libtvbinder/Android.mk | 34 | ||||
-rw-r--r-- | libtvbinder/TvServerHidlClient.cpp | 270 | ||||
-rw-r--r-- | libtvbinder/include/TvServerHidlClient.h | 122 |
8 files changed, 780 insertions, 197 deletions
diff --git a/core/java/Android.mk b/core/java/Android.mk index 3281309..3303724 100644 --- a/core/java/Android.mk +++ b/core/java/Android.mk @@ -17,4 +17,27 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK) LOCAL_PROPRIETARY_MODULE := true endif +LOCAL_JAVA_LIBRARIES += \ + android.hidl.base-V1.0-java \ + android.hidl.manager-V1.0-java + +LOCAL_STATIC_JAVA_LIBRARIES := \ + vendor.amlogic.hardware.tvserver-V1.0-java + include $(BUILD_JAVA_LIBRARY) + +#copy xml to permissions directory +include $(CLEAR_VARS) +LOCAL_MODULE := droidlogic.tv.software.core.xml +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK) +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/permissions +else +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions +endif + +include $(BUILD_PREBUILT)
\ No newline at end of file diff --git a/core/java/com/droidlogic/app/tv/TvControlManager.java b/core/java/com/droidlogic/app/tv/TvControlManager.java index 0749ae0..c334d8d 100644 --- a/core/java/com/droidlogic/app/tv/TvControlManager.java +++ b/core/java/com/droidlogic/app/tv/TvControlManager.java @@ -1,15 +1,5 @@ package com.droidlogic.app.tv; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.StringTokenizer; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.io.IOException; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -20,31 +10,51 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import android.os.SystemProperties; - -import android.util.Log; -import android.view.View; -import android.view.Surface; -import android.view.SurfaceHolder; +import android.content.Context; import android.graphics.ImageFormat; import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.media.tv.TvContract; import android.os.Build; import android.os.Handler; +import android.os.HwBinder; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; -import android.graphics.Matrix; - -import android.media.tv.TvContract; +import android.os.RemoteException; +import android.os.SystemProperties; import android.text.TextUtils; -//import android.media.audiofx.Srs; -//import android.media.audiofx.Hpeq; +import android.util.Log; +import android.view.View; +import android.view.Surface; +import android.view.SurfaceHolder; import static com.droidlogic.app.tv.TvControlCommand.*; import com.droidlogic.app.tv.EasEvent; +import android.hidl.manager.V1_0.IServiceManager; +import android.hidl.manager.V1_0.IServiceNotification; +import vendor.amlogic.hardware.tvserver.V1_0.ITvServer; +import vendor.amlogic.hardware.tvserver.V1_0.ITvServerCallback; +import vendor.amlogic.hardware.tvserver.V1_0.SignalInfo; +import vendor.amlogic.hardware.tvserver.V1_0.TvHidlParcel; +import vendor.amlogic.hardware.tvserver.V1_0.ConnectType; +import vendor.amlogic.hardware.tvserver.V1_0.Result; + public class TvControlManager { private static final String TAG = "TvControlManager"; private static final String OPEN_TV_LOG_FLG = "open.libtv.log.flg"; @@ -130,7 +140,7 @@ public class TvControlManager { private native final void native_setup(Object tv_this); private native final void native_release(); - public native void addCallbackBuffer(byte cb[]); + //public native void addCallbackBuffer(byte cb[]); public native final void unlock(); public native final void lock(); public native final void reconnect() throws IOException; @@ -153,12 +163,16 @@ public class TvControlManager { private int sendCmdToTv(Parcel p, Parcel r) { p.setDataPosition(0); + + Log.i(TAG, "sendCmdToTv cmd:" + p.readInt()); + int ret = processCmd(p, r); r.setDataPosition(0); return ret; } public int sendCmd(int cmd) { + Log.i(TAG, "sendCmd cmd:" + cmd); libtv_log_open(); Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -174,6 +188,7 @@ public class TvControlManager { } public int sendCmdIntArray(int cmd, int[] values) { + Log.i(TAG, "sendCmdIntArray cmd:" + cmd); libtv_log_open(); Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -192,6 +207,7 @@ public class TvControlManager { } public int sendCmdFloatArray(int cmd, float[] values) { + Log.i(TAG, "sendCmdFloatArray cmd:" + cmd); libtv_log_open(); Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -211,6 +227,7 @@ public class TvControlManager { } public int sendCmdStringArray(int cmd, String[] values) { + Log.i(TAG, "sendCmdStringArray cmd:" + cmd); libtv_log_open(); Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -230,6 +247,7 @@ public class TvControlManager { } public int sendCmdStringArray(int cmd, int id, String[] values) { + Log.i(TAG, "sendCmdStringArray cmd:" + cmd + " id:" + id); libtv_log_open(); Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -362,7 +380,58 @@ public class TvControlManager { int i = 0, loop_count = 0, tmp_val = 0; Parcel p; + TvHidlParcel parcel = ((TvHidlParcel) (msg.obj)); switch (msg.what) { + case DTV_AV_PLAYBACK_CALLBACK: + if (mAVPlaybackListener != null) { + int msgType= parcel.bodyInt.get(0); + int programID= parcel.bodyInt.get(1); + mAVPlaybackListener.onEvent(msgType, programID); + } + break; + case SOURCE_CONNECT_CALLBACK: + if (mSourceConnectChangeListener != null) { + mSourceConnectChangeListener.onSourceConnectChange(SourceInput.values()[parcel.bodyInt.get(0)], parcel.bodyInt.get(1)); + } + break; + + case SCAN_EVENT_CALLBACK: + p = ((Parcel) (msg.obj)); + ScannerEvent scan_ev = new ScannerEvent(); + readScanEvent(scan_ev, p); + if (mScannerListener != null) + mScannerListener.onEvent(scan_ev); + if (mStorDBListener != null) + mStorDBListener.StorDBonEvent(scan_ev); + break; + + case RRT_EVENT_CALLBACK: + p = ((Parcel) (msg.obj)); + if (mRrtListener != null) { + int result = p.readInt(); + Log.e(TAG, "RRT_EVENT_CALLBACK:" + result); + rrt5XmlLoadStatus = result; + mRrtListener.onRRT5InfoUpdated(result); + } + break; + + case EAS_EVENT_CALLBACK: + Log.i(TAG,"get EAS_event_callBack"); + p = ((Parcel) (msg.obj)); + if (mEasListener != null) { + Log.i(TAG,"mEaslister is not null"); + int sectionCount = p.readInt(); + Log.i(TAG,"eas section count = "+sectionCount); + for (int count = 0; count<sectionCount; count++) { + EasEvent curEasEvent = new EasEvent(); + curEasEvent.readEasEvent(p); + if (easManager.isEasEventNeedProcess(curEasEvent)) { + mEasListener.processDetailsChannelAlert(curEasEvent); + } + } + } + break; + case SUBTITLE_UPDATE_CALLBACK: if (mSubtitleListener != null) { mSubtitleListener.onUpdate(); @@ -379,23 +448,7 @@ public class TvControlManager { ev.FrameHeight= p.readInt(); } break; - case SCAN_EVENT_CALLBACK: - p = ((Parcel) (msg.obj)); - if (mScannerListener != null) { - ScannerEvent scan_ev = new ScannerEvent(); - readScanEvent(scan_ev, p); - mScannerListener.onEvent(scan_ev); - if (mStorDBListener != null) { - mStorDBListener.StorDBonEvent(scan_ev); - } - }else if (mStorDBListener != null) { - ScannerEvent scan_ev = new ScannerEvent(); - readScanEvent(scan_ev, p); - mStorDBListener.StorDBonEvent(scan_ev); - } - if (mStorDBListener == null) - Log.d(TAG,"mStorDBListener is null !!!"); - break; + case SCANNING_FRAME_STABLE_CALLBACK: p = ((Parcel) (msg.obj)); if (mScanningFrameStableListener != null) { @@ -418,14 +471,6 @@ public class TvControlManager { mEpgListener.onEvent(ev); } break; - case DTV_AV_PLAYBACK_CALLBACK: - p = ((Parcel) (msg.obj)); - if (mAVPlaybackListener != null) { - int msgType= p.readInt(); - int programID= p.readInt(); - mAVPlaybackListener.onEvent(msgType, programID); - } - break ; case SEARCH_CALLBACK: if (mSigChanSearchListener != null) { if (msgPdu != null) { @@ -454,11 +499,6 @@ public class TvControlManager { mStatus3DChangeListener.onStatus3DChange(((Parcel) (msg.obj)).readInt()); } break; - case SOURCE_CONNECT_CALLBACK: - if (mSourceConnectChangeListener != null) { - mSourceConnectChangeListener.onSourceConnectChange( SourceInput.values()[((Parcel) (msg.obj)).readInt()], ((Parcel) (msg.obj)).readInt()); - } - break; case HDMIRX_CEC_CALLBACK: if (mHDMIRxCECListener != null) { if (msgPdu != null) { @@ -542,34 +582,6 @@ public class TvControlManager { mRecorderEventListener.onRecoderEvent(ev); } break; - - case RRT_EVENT_CALLBACK: - p = ((Parcel) (msg.obj)); - if (mRrtListener != null) { - int result = p.readInt(); - Log.e(TAG, "RRT_EVENT_CALLBACK:" + result); - rrt5XmlLoadStatus = result; - mRrtListener.onRRT5InfoUpdated(result); - } - break; - - case EAS_EVENT_CALLBACK: - Log.i(TAG,"get EAS_event_callBack"); - p = ((Parcel) (msg.obj)); - if (mEasListener != null) { - Log.i(TAG,"mEaslister is not null"); - int sectionCount = p.readInt(); - Log.i(TAG,"eas section count = "+sectionCount); - for (int count = 0; count<sectionCount; count++) { - EasEvent curEasEvent = new EasEvent(); - curEasEvent.readEasEvent(p); - if (easManager.isEasEventNeedProcess(curEasEvent)) { - mEasListener.processDetailsChannelAlert(curEasEvent); - } - } - } - - break; default: Log.e(TAG, "Unknown message type " + msg.what); break; @@ -583,20 +595,193 @@ public class TvControlManager { } public TvControlManager() { - Looper looper; - if ((looper = Looper.myLooper()) != null) { + Looper looper = Looper.myLooper(); + if (looper != null) { mEventHandler = new EventHandler(looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(looper); } else { mEventHandler = null; + Log.e(TAG, "looper is null, so can not do anything"); } - native_setup(new WeakReference<TvControlManager>(this)); - String LogFlg = TvMiscConfigGet(OPEN_TV_LOG_FLG,null); - if ("log_open".equals(TvMiscConfigGet(OPEN_TV_LOG_FLG,null))) + mHALCallback = new HALCallback(this); + //native_setup(new WeakReference<TvControlManager>(this)); + + try { + boolean ret = IServiceManager.getService() + .registerForNotifications("vendor.amlogic.hardware.tvserver@1.0::ITvServer", "", mServiceNotification); + if (!ret) { + Log.e(TAG, "Failed to register service start notification"); + } + } catch (RemoteException e) { + Log.e(TAG, "Failed to register service start notification", e); + } + connectToProxy(); + + String LogFlg = TvMiscConfigGet(OPEN_TV_LOG_FLG, ""); + if ("log_open".equals(LogFlg)) tvLogFlg =true; } + private static final int TVSERVER_DEATH_COOKIE = 1000; + + // Callback when the UsbPort status is changed by the kernel. + // Mostly due a command sent by the remote Usb device. + private HALCallback mHALCallback; + + // Notification object used to listen to the start of the tvserver daemon. + private final ServiceNotification mServiceNotification = new ServiceNotification(); + + private ITvServer mProxy = null; + // Mutex for all mutable shared state. + private final Object mLock = new Object(); + + private void connectToProxy() { + synchronized (mLock) { + if (mProxy != null) { + return; + } + + try { + mProxy = ITvServer.getService(); + mProxy.linkToDeath(new DeathRecipient(), TVSERVER_DEATH_COOKIE); + mProxy.setCallback(mHALCallback, ConnectType.TYPE_EXTEND); + } catch (NoSuchElementException e) { + Log.e(TAG, "connectToProxy: tvserver HIDL service not found." + + " Did the service fail to start?", e); + } catch (RemoteException e) { + Log.e(TAG, "connectToProxy: tvserver HIDL service not responding", e); + } + } + + Log.i(TAG, "connect to tvserve HIDL service success"); + } + + public String getSupportInputDevices() { + synchronized (mLock) { + Mutable<String> resultVal = new Mutable<>(); + try { + mProxy.getSupportInputDevices((int ret, String v) -> { + resultVal.value = v; + }); + return resultVal.value; + } catch (RemoteException e) { + Log.e(TAG, "getSupportInputDevices:" + e); + } + } + return ""; + } + + /** + * @Function: GetCurrentSignalInfo + * @Description: Get current signal infomation + * @Param: + * @Return: refer to class tvin_info_t + */ + public TVInSignalInfo GetCurrentSignalInfo() { + synchronized (mLock) { + TVInSignalInfo info = new TVInSignalInfo(); + try { + SignalInfo hidlInfo = mProxy.getCurSignalInfo(); + info.transFmt = TVInSignalInfo.TransFmt.values()[hidlInfo.transFmt]; + info.sigFmt = TVInSignalInfo.SignalFmt.valueOf(hidlInfo.fmt); + info.sigStatus = TVInSignalInfo.SignalStatus.values()[hidlInfo.status]; + info.reserved = hidlInfo.frameRate; + return info; + } catch (RemoteException e) { + Log.e(TAG, "GetCurrentSignalInfo:" + e); + } + } + return null; + } + + /** + * @Function: TvMiscConfigSet + * @Description: Set tv config + * @Param: key_str tv config name string, value_str tv config set value string + * @Return: 0 success, -1 fail + */ + public int TvMiscConfigSet(String key_str, String value_str) { + synchronized (mLock) { + try { + return mProxy.setMiscCfg(key_str, value_str); + } catch (RemoteException e) { + Log.e(TAG, "TvMiscConfigSet:" + e); + } + } + + return -1; + } + + /** + * @Function: TvMiscConfigGet + * @Description: Get tv config + * @Param: key_str tv config name string, value_str tv config get value string + * @Return: 0 success, -1 fail + */ + public String TvMiscConfigGet(String key_str, String def_str) { + synchronized (mLock) { + try { + return mProxy.getMiscCfg(key_str, def_str); + } catch (RemoteException e) { + Log.e(TAG, "TvMiscConfigGet:" + e); + } + } + return ""; + } + + private static class Mutable<E> { + public E value; + + Mutable() { + value = null; + } + + Mutable(E value) { + this.value = value; + } + } + + private static class HALCallback extends ITvServerCallback.Stub { + TvControlManager tvCtrlMgr; + HALCallback(TvControlManager tcm) { + tvCtrlMgr = tcm; + } + + public void notifyCallback(TvHidlParcel parcel) { + Log.i(TAG, "notifyCallback msg type:" + parcel.msgType); + + if (tvCtrlMgr.mEventHandler != null) { + Message msg = tvCtrlMgr.mEventHandler.obtainMessage(parcel.msgType, 0, 0, parcel); + tvCtrlMgr.mEventHandler.sendMessage(msg); + } + } + } + + final class DeathRecipient implements HwBinder.DeathRecipient { + DeathRecipient() { + } + + @Override + public void serviceDied(long cookie) { + if (TVSERVER_DEATH_COOKIE == cookie) { + Log.e(TAG, "tvserver HIDL service died cookie: " + cookie); + synchronized (mLock) { + mProxy = null; + } + } + } + } + + final class ServiceNotification extends IServiceNotification.Stub { + @Override + public void onRegistration(String fqName, String name, boolean preexisting) { + Log.i(TAG, "tvserver HIDL service started " + fqName + " " + name); + connectToProxy(); + } + } + + protected void finalize() { //native_release(); } @@ -766,28 +951,6 @@ public class TvControlManager { } /** - * @Function: GetCurrentSignalInfo - * @Description: Get current signal infomation - * @Param: - * @Return: refer to class tvin_info_t - */ - public TVInSignalInfo GetCurrentSignalInfo() { - libtv_log_open(); - Parcel cmd = Parcel.obtain(); - Parcel r = Parcel.obtain(); - cmd.writeInt(GET_CURRENT_SIGNAL_INFO); - sendCmdToTv(cmd, r); - TVInSignalInfo info = new TVInSignalInfo(); - info.transFmt = TVInSignalInfo.TransFmt.values()[r.readInt()]; - info.sigFmt = TVInSignalInfo.SignalFmt.valueOf(r.readInt()); - info.sigStatus = TVInSignalInfo.SignalStatus.values()[r.readInt()]; - info.reserved = r.readInt(); - cmd.recycle(); - r.recycle(); - return info; - } - - /** * @Function: SetSourceInput * @Description: Set source input to switch source, * @Param: source_input, refer to enum SourceInput; win_pos, refer to class window_pos_t @@ -3575,36 +3738,6 @@ public class TvControlManager { // SSM END //MISC - /** - * @Function: TvMiscConfigSet - * @Description: Set tv config - * @Param: key_str tv config name string, value_str tv config set value string - * @Return: 0 success, -1 fail - */ - public int TvMiscConfigSet(String key_str, String value_str) { - String val[] = new String[]{key_str, value_str}; - return sendCmdStringArray(MISC_CFG_SET, val); - } - - /** - * @Function: TvMiscConfigGet - * @Description: Get tv config - * @Param: key_str tv config name string, value_str tv config get value string - * @Return: 0 success, -1 fail - */ - public String TvMiscConfigGet(String key_str, String def_str) { - libtv_log_open(); - Parcel cmd = Parcel.obtain(); - Parcel r = Parcel.obtain(); - cmd.writeInt(MISC_CFG_GET); - cmd.writeString(key_str); - cmd.writeString(def_str); - sendCmdToTv(cmd, r); - String str = r.readString(); - cmd.recycle(); - r.recycle(); - return str; - } /** * @Function: TvMiscSetGPIOCtrl @@ -5582,10 +5715,10 @@ public class TvControlManager { } private void libtv_log_open(){ - if (tvLogFlg) { + //if (tvLogFlg) { StackTraceElement traceElement = ((new Exception()).getStackTrace())[1]; Log.i(TAG, traceElement.getMethodName()); - } + //} } public enum LEFT_RIGHT_SOUND_CHANNEL { diff --git a/core/java/droidlogic.tv.software.core.xml b/core/java/droidlogic.tv.software.core.xml new file mode 100644 index 0000000..4c4d8b1 --- a/dev/null +++ b/core/java/droidlogic.tv.software.core.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<permissions> + <library name="droidlogic.tv.software.core" + file="/vendor/framework/droidlogic-tv.jar" /> +</permissions> diff --git a/core/jni/Android.mk b/core/jni/Android.mk index e5c68a1..4f61c68 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -6,17 +6,19 @@ LOCAL_MODULE_TAGS := optional LIB_TV_BINDER_PATH := $(wildcard $(BOARD_AML_VENDOR_PATH)/tv/frameworks/libtvbinder) LOCAL_SRC_FILES:= \ - com_droidlogic_app_tv_TvControlManager.cpp + com_droidlogic_app_tv_TvControlManager.cpp + LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libbinder \ - libtvbinder \ - libnativehelper \ - libandroid_runtime \ - liblog \ - libskia \ - libhardware + vendor.amlogic.hardware.tvserver@1.0_vendor \ + libcutils \ + libutils \ + libbinder \ + libtvbinder \ + libnativehelper \ + libandroid_runtime \ + liblog \ + libskia \ + libhardware LOCAL_C_INCLUDES += \ frameworks/base/core/jni \ diff --git a/core/jni/com_droidlogic_app_tv_TvControlManager.cpp b/core/jni/com_droidlogic_app_tv_TvControlManager.cpp index 5e5ba4b..b0b2da0 100644 --- a/core/jni/com_droidlogic_app_tv_TvControlManager.cpp +++ b/core/jni/com_droidlogic_app_tv_TvControlManager.cpp @@ -6,7 +6,6 @@ #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include <utils/Vector.h> -#include "TvClient.h" #include <binder/IMemory.h> #include <binder/Parcel.h> #include <binder/MemoryHeapBase.h> @@ -20,6 +19,8 @@ #include <sys/types.h> #include <sys/stat.h> +#include "TvServerHidlClient.h" + using namespace android; struct fields_t { @@ -31,14 +32,14 @@ static fields_t fields; static Mutex sLock; class JNITvContext: public TvListener { public: - JNITvContext(JNIEnv *env, jobject weak_this, jclass clazz, const sp<TvClient> &tv); + JNITvContext(JNIEnv *env, jobject weak_this, jclass clazz, const sp<TvServerHidlClient> &tv); ~JNITvContext() { release(); } - virtual void notify(int32_t msgType, const Parcel &p); + virtual void notify(const tv_parcel_t &parcel); void addCallbackBuffer(JNIEnv *env, jbyteArray cbb); - sp<TvClient> getTv() + sp<TvServerHidlClient> getTv() { Mutex::Autolock _l(mLock); return mTv; @@ -50,7 +51,7 @@ public: private: jobject mTvJObjectWeak; // weak reference to java object jclass mTvJClass; // strong reference to java class - sp<TvClient> mTv; // strong reference to native object + sp<TvServerHidlClient> mTv; // strong reference to native object Mutex mLock; Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[] @@ -64,9 +65,9 @@ private: #define CAPTURE_MAX_BITMAP_W 1920 #define CAPTURE_MAX_BITMAP_H 1080 -sp<TvClient> get_native_tv(JNIEnv *env, jobject thiz, JNITvContext **pContext) +sp<TvServerHidlClient> get_native_tv(JNIEnv *env, jobject thiz, JNITvContext **pContext) { - sp<TvClient> tv; + sp<TvServerHidlClient> tv = nullptr; Mutex::Autolock _l(sLock); JNITvContext *context = reinterpret_cast<JNITvContext *>(env->GetLongField(thiz, fields.context)); if (context != NULL) { @@ -80,7 +81,7 @@ sp<TvClient> get_native_tv(JNIEnv *env, jobject thiz, JNITvContext **pContext) return tv; } -JNITvContext::JNITvContext(JNIEnv *env, jobject weak_this, jclass clazz, const sp<TvClient> &tv) +JNITvContext::JNITvContext(JNIEnv *env, jobject weak_this, jclass clazz, const sp<TvServerHidlClient> &tv) { mTvJObjectWeak = env->NewGlobalRef(weak_this); mTvJClass = (jclass)env->NewGlobalRef(clazz); @@ -116,20 +117,19 @@ void JNITvContext::release() // connect to tv service static void com_droidlogic_app_tv_TvControlManager_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) { - sp<TvClient> tv = TvClient::connect(); - ALOGD("com_droidlogic_app_tv_TvControlManager_native_setup."); - if (tv == NULL) { + sp<TvServerHidlClient> tv = TvServerHidlClient::connect(CONNECT_TYPE_EXTEND); + if (tv == nullptr) { jniThrowException(env, "java/lang/RuntimeException", "Fail to connect to tv service"); return; } // make sure tv amlogic is alive - if (tv->getStatus() != NO_ERROR) { - jniThrowException(env, "java/lang/RuntimeException", "Tv initialization failed!"); - return; - } + //if (tv->getStatus() != NO_ERROR) { + // jniThrowException(env, "java/lang/RuntimeException", "Tv initialization failed!"); + // return; + //} jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { @@ -144,12 +144,10 @@ static void com_droidlogic_app_tv_TvControlManager_native_setup(JNIEnv *env, job env->SetLongField(thiz, fields.context, (long)context.get()); } - static void com_droidlogic_app_tv_TvControlManager_release(JNIEnv *env, jobject thiz) { // TODO: Change to LOGE JNITvContext *context = NULL; - sp<TvClient> tv; { Mutex::Autolock _l(sLock); context = reinterpret_cast<JNITvContext *>(env->GetLongField(thiz, fields.context)); @@ -162,7 +160,7 @@ static void com_droidlogic_app_tv_TvControlManager_release(JNIEnv *env, jobject // clean up if release has not been called before if (context != NULL) { - tv = context->getTv(); + sp<TvServerHidlClient> tv = context->getTv(); context->release(); ALOGD("native_release: context=%p tv=%p", context, tv.get()); @@ -177,8 +175,9 @@ static void com_droidlogic_app_tv_TvControlManager_release(JNIEnv *env, jobject } } -void JNITvContext::notify(int32_t msgType, const Parcel &p) +void JNITvContext::notify(const tv_parcel_t &parcel) { + /* // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); if (mTvJObjectWeak == NULL) { @@ -206,6 +205,7 @@ void JNITvContext::notify(int32_t msgType, const Parcel &p) env->CallStaticVoidMethod(mTvJClass, fields.post_event, mTvJObjectWeak, msgType, jParcel); env->DeleteLocalRef(jParcel); } + */ } @@ -223,7 +223,7 @@ void JNITvContext::addCallbackBuffer(JNIEnv *env, jbyteArray cbb) static jint com_droidlogic_app_tv_TvControlManager_processCmd(JNIEnv *env, jobject thiz, jobject pObj, jobject rObj) { - sp<TvClient> tv = get_native_tv(env, thiz, NULL); + sp<TvServerHidlClient> tv = get_native_tv(env, thiz, NULL); if (tv == 0) return -1; Parcel *p = parcelForJavaObject(env, pObj); @@ -255,44 +255,41 @@ static void com_droidlogic_app_tv_TvControlManager_addCallbackBuffer(JNIEnv *env static void com_droidlogic_app_tv_TvControlManager_reconnect(JNIEnv *env, jobject thiz) { - sp<TvClient> tv = get_native_tv(env, thiz, NULL); - if (tv == 0) return; + sp<TvServerHidlClient> tv = get_native_tv(env, thiz, NULL); + if (tv == nullptr) return; - if (tv->reconnect() != NO_ERROR) { - jniThrowException(env, "java/io/IOException", "reconnect failed"); - return; - } + tv->reconnect(); } static void com_droidlogic_app_tv_TvControlManager_lock(JNIEnv *env, jobject thiz) { - sp<TvClient> tv = get_native_tv(env, thiz, NULL); + sp<TvServerHidlClient> tv = get_native_tv(env, thiz, NULL); if (tv == 0) return; ALOGD("lock"); - if (tv->lock() != NO_ERROR) { - jniThrowException(env, "java/lang/RuntimeException", "lock failed"); - } + //if (tv->lock() != NO_ERROR) { + // jniThrowException(env, "java/lang/RuntimeException", "lock failed"); + //} } static void com_droidlogic_app_tv_TvControlManager_unlock(JNIEnv *env, jobject thiz) { - sp<TvClient> tv = get_native_tv(env, thiz, NULL); + sp<TvServerHidlClient> tv = get_native_tv(env, thiz, NULL); if (tv == 0) return; ALOGD("unlock"); - if (tv->unlock() != NO_ERROR) { - jniThrowException(env, "java/lang/RuntimeException", "unlock failed"); - } + //if (tv->unlock() != NO_ERROR) { + // jniThrowException(env, "java/lang/RuntimeException", "unlock failed"); + //} } static void com_droidlogic_app_tv_TvControlManager_create_subtitle_bitmap(JNIEnv *env, jobject thiz, jobject bmpobj) { ALOGD("create subtitle bmp"); JNITvContext *context = reinterpret_cast<JNITvContext *>(env->GetLongField(thiz, fields.context)); - sp<TvClient> tv = get_native_tv(env, thiz, NULL); + sp<TvServerHidlClient> tv = get_native_tv(env, thiz, NULL); if (tv == 0) return; //get skbitmap @@ -300,7 +297,7 @@ static void com_droidlogic_app_tv_TvControlManager_create_subtitle_bitmap(JNIEnv jfieldID skbmp_fid; jlong hbmp; bmp_clazz = env->FindClass("android/graphics/Bitmap"); - skbmp_fid = env->GetFieldID(bmp_clazz, "mNativePtr", "J"); + skbmp_fid = env->GetFieldID(bmp_clazz, "mNativePtr", "J"); hbmp = env->GetLongField(bmpobj, skbmp_fid); context->pSubBmp = reinterpret_cast<SkBitmap *>(hbmp); @@ -317,7 +314,7 @@ static void com_droidlogic_app_tv_TvControlManager_create_subtitle_bitmap(JNIEnv //send share mem to server - tv->createSubtitle(context->mSubMemBase); + //tv->createSubtitle(context->mSubMemBase); return; } @@ -339,11 +336,13 @@ static JNINativeMethod camMethods[] = { "(Landroid/os/Parcel;Landroid/os/Parcel;)I", (void *)com_droidlogic_app_tv_TvControlManager_processCmd }, + /* { "addCallbackBuffer", "([B)V", (void *)com_droidlogic_app_tv_TvControlManager_addCallbackBuffer }, + */ { "reconnect", "()V", @@ -399,7 +398,7 @@ static int find_fields(JNIEnv *env, field *fields, int count) int register_com_droidlogic_app_tv_TvControlManager(JNIEnv *env) { field fields_to_find[] = { - { "com/droidlogic/app/tv/TvControlManager", "mNativeContext", "J", &fields.context } + { "com/droidlogic/app/tv/TvControlManager", "mNativeContext", "J", &fields.context } }; ALOGD("register_com_droidlogic_app_tv_TvControlManager."); diff --git a/libtvbinder/Android.mk b/libtvbinder/Android.mk index 9abeef4..22b65bf 100644 --- a/libtvbinder/Android.mk +++ b/libtvbinder/Android.mk @@ -4,17 +4,32 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES:= \ - TvClient.cpp \ - ITv.cpp \ - ITvClient.cpp \ - ITvService.cpp + TvServerHidlClient.cpp \ + TvClient.cpp \ + ITv.cpp \ + ITvClient.cpp \ + ITvService.cpp LOCAL_SHARED_LIBRARIES := \ - libcutils \ - liblog \ - libutils \ - libbinder \ - libui + vendor.amlogic.hardware.tvserver@1.0_vendor \ + libbase \ + libhidlbase \ + libhidltransport \ + libhidlmemory \ + android.hidl.allocator@1.0 \ + liblog \ + libcutils \ + libutils \ + libbinder + +LOCAL_C_INCLUDES += \ + system/libhidl/transport/include/hidl \ + system/libhidl/libhidlmemory/include + +LOCAL_C_INCLUDES += \ + external/libcxx/include + +LOCAL_CPPFLAGS += -std=c++14 LOCAL_MODULE:= libtvbinder @@ -22,5 +37,4 @@ ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK) LOCAL_PROPRIETARY_MODULE := true endif -#LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY) diff --git a/libtvbinder/TvServerHidlClient.cpp b/libtvbinder/TvServerHidlClient.cpp new file mode 100644 index 0000000..2e7ad6a --- a/dev/null +++ b/libtvbinder/TvServerHidlClient.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * @author Tellen Yu + * @version 1.0 + * @date 2018/1/12 + * @par function description: + * - 1 droidlogic tv hwbinder client + */ + +#define LOG_TAG "TvServerHidlClient" +#include <utils/Log.h> + +#include <android/hidl/allocator/1.0/IAllocator.h> +#include <android/hidl/memory/1.0/IMemory.h> +#include <hidlmemory/mapping.h> +#include "include/TvServerHidlClient.h" + +namespace android { + +using ::android::hidl::allocator::V1_0::IAllocator; +using ::android::hidl::memory::V1_0::IMemory; + +Mutex TvServerHidlClient::mLock; + +// establish binder interface to tv service +sp<ITvServer> TvServerHidlClient::getTvService() +{ + Mutex::Autolock _l(mLock); + +#if 1//PLATFORM_SDK_VERSION >= 26 + sp<ITvServer> tvservice = ITvServer::tryGetService(); + while (tvservice == nullptr) { + usleep(200*1000);//sleep 200ms + tvservice = ITvServer::tryGetService(); + ALOGE("tryGet tvserver daemon Service"); + }; + mDeathRecipient = new TvServerDaemonDeathRecipient(this); + Return<bool> linked = tvservice->linkToDeath(mDeathRecipient, /*cookie*/ 0); + if (!linked.isOk()) { + ALOGE("Transaction error in linking to tvserver daemon service death: %s", linked.description().c_str()); + } else if (!linked) { + ALOGE("Unable to link to tvserver daemon service death notifications"); + } else { + ALOGI("Link to tvserver daemon service death notification successful"); + } + +#else + Mutex::Autolock _l(mLock); + if (mTvService.get() == 0) { + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> binder; + do { + binder = sm->getService(String16("tvservice")); + if (binder != 0) + break; + ALOGW("TvService not published, waiting..."); + usleep(500000); // 0.5 s + } while (true); + if (mDeathNotifier == NULL) { + mDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(mDeathNotifier); + mTvService = interface_cast<ITvService>(binder); + } + ALOGE_IF(mTvService == 0, "no TvService!?"); + return mTvService; +#endif + + return tvservice; +} + +TvServerHidlClient::TvServerHidlClient(tv_connect_type_t type): mType(type) +{ + mTvServer = getTvService(); + mTvServerHidlCallback = new TvServerHidlCallback(this); + mTvServer->setCallback(mTvServerHidlCallback, static_cast<ConnectType>(type)); +} + +TvServerHidlClient::~TvServerHidlClient() +{ + disconnect(); +} + +sp<TvServerHidlClient> TvServerHidlClient::connect(tv_connect_type_t type) +{ + return new TvServerHidlClient(type); +} + +void TvServerHidlClient::reconnect() +{ + ALOGI("tvserver client type:%d reconnect", mType); + mTvServer.clear(); + //reconnect to server + mTvServer = getTvService(); + mTvServer->setCallback(mTvServerHidlCallback, static_cast<ConnectType>(mType)); +} + +void TvServerHidlClient::disconnect() +{ + ALOGD("disconnect"); +} + +status_t TvServerHidlClient::processCmd(const Parcel &p, Parcel *r __unused) +{ + int cmd = p.readInt32(); + + ALOGD("processCmd cmd=%d", cmd); + return 0; +#if 0 + sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); + if (ashmemAllocator == nullptr) { + ALOGE("can not get ashmem service"); + return -1; + } + + size_t size = p.dataSize(); + hidl_memory hidlMemory; + auto res = ashmemAllocator->allocate(size, [&](bool success, const hidl_memory& memory) { + if (!success) { + ALOGE("ashmem allocate size:%d fail", size); + } + hidlMemory = memory; + }); + + if (!res.isOk()) { + ALOGE("ashmem allocate result fail"); + return -1; + } + + sp<IMemory> memory = hardware::mapMemory(hidlMemory); + void* data = memory->getPointer(); + memory->update(); + // update memory however you wish after calling update and before calling commit + memcpy(data, p.data(), size); + memory->commit(); + Return<int32_t> ret = mTvServer->processCmd(hidlMemory, (int)size); + if (!ret.isOk()) { + ALOGE("Failed to processCmd"); + } + return ret; +#endif +} + +void TvServerHidlClient::setListener(const sp<TvListener> &listener) +{ + mListener = listener; +} + +int TvServerHidlClient::startTv() { + return mTvServer->startTv(); +} + +int TvServerHidlClient::stopTv() { + return mTvServer->stopTv(); +} + +int TvServerHidlClient::switchInputSrc(int32_t inputSrc) { + return mTvServer->switchInputSrc(inputSrc); +} + +int TvServerHidlClient::getInputSrcConnectStatus(int32_t inputSrc) { + return mTvServer->getInputSrcConnectStatus(inputSrc); +} + +int TvServerHidlClient::getCurrentInputSrc() { + return mTvServer->getCurrentInputSrc(); +} + +int TvServerHidlClient::getHdmiAvHotplugStatus() { + return mTvServer->getHdmiAvHotplugStatus(); +} + +std::string TvServerHidlClient::getSupportInputDevices() { + int ret; + std::string tvDevices; + mTvServer->getSupportInputDevices([&](int32_t result, const ::android::hardware::hidl_string& devices) { + ret = result; + tvDevices = devices; + }); + return tvDevices; +} + +int TvServerHidlClient::getHdmiPorts() { + return mTvServer->getHdmiPorts(); +} + +void TvServerHidlClient::getCurSignalInfo(int &fmt, int &transFmt, int &status, int &frameRate) { + mTvServer->getCurSignalInfo([&](const SignalInfo& info) { + fmt = info.fmt; + transFmt = info.transFmt; + status = info.status; + frameRate = info.frameRate; + }); +} + +int TvServerHidlClient::setMiscCfg(const std::string& key, const std::string& val) { + return mTvServer->setMiscCfg(key, val); +} + +std::string TvServerHidlClient::getMiscCfg(const std::string& key, const std::string& def) { + std::string miscCfg; + mTvServer->getMiscCfg(key, def, [&](const std::string& cfg) { + miscCfg = cfg; + }); + + return miscCfg; +} + + +// callback from tv service +Return<void> TvServerHidlClient::TvServerHidlCallback::notifyCallback(const TvHidlParcel& hidlParcel) +{ + ALOGI("notifyCallback event type:%d", hidlParcel.msgType); + +#if 0 + Parcel p; + + sp<IMemory> memory = android::hardware::mapMemory(parcelMem); + void* data = memory->getPointer(); + memory->update(); + // update memory however you wish after calling update and before calling commit + p.setDataPosition(0); + p.write(data, size); + memory->commit(); + +#endif + sp<TvListener> listener; + { + Mutex::Autolock _l(mLock); + listener = tvserverClient->mListener; + } + + tv_parcel_t parcel; + parcel.msgType = hidlParcel.msgType; + for (int i = 0; i < hidlParcel.bodyInt.size(); i++) { + parcel.bodyInt.push_back(hidlParcel.bodyInt[i]); + } + + for (int j = 0; j < hidlParcel.bodyString.size(); j++) { + parcel.bodyString.push_back(hidlParcel.bodyString[j]); + } + + if (listener != NULL) { + listener->notify(parcel); + } + return Void(); +} + +void TvServerHidlClient::TvServerDaemonDeathRecipient::serviceDied(uint64_t cookie __unused, + const ::android::wp<::android::hidl::base::V1_0::IBase>& who __unused) +{ + ALOGE("tvserver daemon died."); + Mutex::Autolock _l(mLock); + + usleep(200*1000);//sleep 200ms + tvserverClient->reconnect(); +} +} diff --git a/libtvbinder/include/TvServerHidlClient.h b/libtvbinder/include/TvServerHidlClient.h new file mode 100644 index 0000000..f2df5f2 --- a/dev/null +++ b/libtvbinder/include/TvServerHidlClient.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * @author Tellen Yu + * @version 1.0 + * @date 2018/1/12 + * @par function description: + * - 1 droidlogic tv hwbinder client + */ + +#ifndef _ANDROID_TV_SERVER_HIDL_CLIENT_H_ +#define _ANDROID_TV_SERVER_HIDL_CLIENT_H_ + +#include <utils/Timers.h> +#include <utils/threads.h> +#include <utils/RefBase.h> +#include <utils/Mutex.h> +#include <binder/Parcel.h> + +#include <vendor/amlogic/hardware/tvserver/1.0/ITvServer.h> + +namespace android { + +using ::vendor::amlogic::hardware::tvserver::V1_0::ITvServer; +using ::vendor::amlogic::hardware::tvserver::V1_0::ITvServerCallback; +using ::vendor::amlogic::hardware::tvserver::V1_0::ConnectType; +using ::vendor::amlogic::hardware::tvserver::V1_0::SignalInfo; +using ::vendor::amlogic::hardware::tvserver::V1_0::TvHidlParcel; + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +typedef enum { + CONNECT_TYPE_HAL = 0, + CONNECT_TYPE_EXTEND = 1 +} tv_connect_type_t; + +typedef struct tv_parcel_s { + int msgType; + std::vector<int> bodyInt; + std::vector<std::string> bodyString; +} tv_parcel_t; + +class TvListener : virtual public RefBase { +public: + virtual void notify(const tv_parcel_t &parcel) = 0; +}; + +class TvServerHidlClient : virtual public RefBase { +public: + static sp<TvServerHidlClient> connect(tv_connect_type_t type); + TvServerHidlClient(tv_connect_type_t type); + ~TvServerHidlClient(); + + void reconnect(); + void disconnect(); + status_t processCmd(const Parcel &p, Parcel *r); + void setListener(const sp<TvListener> &listener); + + int startTv(); + int stopTv(); + int switchInputSrc(int32_t inputSrc); + int getInputSrcConnectStatus(int32_t inputSrc); + int getCurrentInputSrc(); + int getHdmiAvHotplugStatus(); + std::string getSupportInputDevices(); + int getHdmiPorts(); + + void getCurSignalInfo(int &fmt, int &transFmt, int &status, int &frameRate); + int setMiscCfg(const std::string& key, const std::string& val); + std::string getMiscCfg(const std::string& key, const std::string& def); + +private: + class TvServerHidlCallback : public ITvServerCallback { + public: + TvServerHidlCallback(TvServerHidlClient *client): tvserverClient(client) {}; + Return<void> notifyCallback(const TvHidlParcel& parcel) override; + + private: + TvServerHidlClient *tvserverClient; + }; + + struct TvServerDaemonDeathRecipient : public android::hardware::hidl_death_recipient { + TvServerDaemonDeathRecipient(TvServerHidlClient *client): tvserverClient(client) {}; + + // hidl_death_recipient interface + virtual void serviceDied(uint64_t cookie, + const ::android::wp<::android::hidl::base::V1_0::IBase>& who) override; + private: + TvServerHidlClient *tvserverClient; + }; + sp<TvServerDaemonDeathRecipient> mDeathRecipient = nullptr; + + static Mutex mLock; + tv_connect_type_t mType; + // helper function to obtain tv service handle + sp<ITvServer> getTvService(); + + sp<TvListener> mListener; + sp<ITvServer> mTvServer; + sp<TvServerHidlCallback> mTvServerHidlCallback = nullptr; +}; + +}//namespace android + +#endif/*_ANDROID_TV_SERVER_HIDL_CLIENT_H_*/ |