通過ConsumerIrService看完整的系統(tǒng)服務(wù)調(diào)用流程(二)

本篇是銜接上一篇:通過ConsumerIrService看完整的系統(tǒng)服務(wù)調(diào)用流程(一)。如不關(guān)心應(yīng)用層的調(diào)用流程可繼續(xù)閱讀,不然建議先移步第一篇。

Frameworks層銜接Hal:

接下來我們看下具體定義和具體實(shí)現(xiàn)。
frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl

// 定義AIDL接口
interface IConsumerIrService
{
    boolean hasIrEmitter();
    void transmit(String packageName, int carrierFrequency, in int[] pattern);
    int[] getCarrierFrequencies();
}

以及對其進(jìn)行的實(shí)現(xiàn):
frameworks/base/services/core/java/com/android/server/ConsumerIrService.java

// 實(shí)現(xiàn)系統(tǒng)服務(wù)
public class ConsumerIrService extends IConsumerIrService.Stub {
    // 系統(tǒng)服務(wù)集成JNI
    private static native boolean halOpen();
    private static native int halTransmit(int carrierFrequency, int[] pattern);
    private static native int[] halGetCarrierFrequencies();
    ...
    ConsumerIrService(Context context) {
    ...
        mHasNativeHal = halOpen(); // this
    ...
    }  
    
    @Override
    public boolean hasIrEmitter() {
        return mHasNativeHal;
    }
    ...
        @Override
    public void transmit(String packageName, int carrierFrequency, int[] pattern) {
         // 這里有權(quán)限的校驗(yàn)
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires TRANSMIT_IR permission");
        }
        ...
        synchronized (mHalLock) {
            int err = halTransmit(carrierFrequency, pattern); // this
        ...
        }
    }
    
        @Override
    public int[] getCarrierFrequencies() {
        // 這里有權(quán)限的校驗(yàn)
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires TRANSMIT_IR permission");
        }
        throwIfNoIrEmitter();
        synchronized(mHalLock) {
            return halGetCarrierFrequencies(); // this
        }
    }
}

權(quán)限的添加在frameworks/base/core/res/AndroidManifest.xml中。

 <permission android:name="android.permission.TRANSMIT_IR"
        android:label="@string/permlab_transmitIr"
        android:description="@string/permdesc_transmitIr"
        android:protectionLevel="normal" />

如果對JNI了解的,就能看出。這部分具體就是橋接了JNI的方法。在看jni的部分之前,還有重要的注冊部分。
frameworks/base/services/java/com/android/server/SystemServer.java

// 在SystemServer中注冊服務(wù)
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    ...
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
    ...
}

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
           if (!isWatch && !tinySystem) {
                t.traceBegin("StartConsumerIrService");
                consumerIr = new ConsumerIrService(context);
                ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
                t.traceEnd();
            }
    ...
}

SystemServer.java具體實(shí)現(xiàn)感興趣的可以繼續(xù)去追,其實(shí)也是通過AIDL來代理的。貼出部分路徑供參考。
frameworks/base/core/java/android/os/ServiceManager.java
frameworks/base/core/java/android/os/ServiceManagerNative.java
frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl

JNI橋接部分:

讓我們回來接著看JNI的實(shí)現(xiàn)。
frameworks/base/services/core/jni/com_android_server_ConsumerIrService.cpp

using ::android::hardware::ir::V1_0::IConsumerIr;
using ::android::hardware::ir::V1_0::ConsumerIrFreqRange;
using ::android::hardware::hidl_vec;

namespace android {
static sp<IConsumerIr> mHal;

static jboolean halOpen(JNIEnv* /* env */, jobject /* obj */) {
    mHal = IConsumerIr::getService();
    return mHal != nullptr;
}

static jint halTransmit(JNIEnv *env, jobject /* obj */, jint carrierFrequency,
    ...
    bool success = mHal->transmit(carrierFrequency, patternVec);
    ...
}

static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject /* obj */) {
    ...
    mHal->getCarrierFreqs(cb);
    ...
}

static const JNINativeMethod method_table[] = {
    { "halOpen", "()Z", (void *)halOpen },
    { "halTransmit", "(I[I)I", (void *)halTransmit },
    { "halGetCarrierFrequencies", "()[I", (void *)halGetCarrierFrequencies},
};

int register_android_server_ConsumerIrService(JNIEnv *env) {
    return jniRegisterNativeMethods(env, "com/android/server/ConsumerIrService",
            method_table, NELEM(method_table));
}
};
HIDL部分:

具體的實(shí)現(xiàn)是通過HIDL來代理承接的,原理和AIDL類似。
hardware/interfaces/ir/1.0/IConsumerIr.hal

// 定義HIDL接口
package android.hardware.ir@1.0;
interface IConsumerIr {
    transmit(int32_t carrierFreq, vec<int32_t> pattern) generates (bool success);
    getCarrierFreqs() generates (bool success, vec<ConsumerIrFreqRange> ranges);
};

我接著看在Hardware層的實(shí)現(xiàn)。
hardware/interfaces/ir/1.0/default/ConsumerIr.h

#include <android/hardware/ir/1.0/IConsumerIr.h>
#include <hardware/consumerir.h>
...

using ::android::hardware::ir::V1_0::ConsumerIrFreqRange;
using ::android::hardware::ir::V1_0::IConsumerIr;
...

struct ConsumerIr : public IConsumerIr {
    ConsumerIr(consumerir_device_t *device);
    // Methods from ::android::hardware::ir::V1_0::IConsumerIr follow.
    Return<bool> transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) override;
    Return<void> getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) override;
private:
    consumerir_device_t *mDevice;
};
...

hardware/interfaces/ir/1.0/default/ConsumerIr.cpp

#include <hardware/hardware.h>
#include <hardware/consumerir.h>
...
ConsumerIr::ConsumerIr(consumerir_device_t *device) {
    mDevice = device;
}

// Methods from ::android::hardware::consumerir::V1_0::IConsumerIr follow.
Return<bool> ConsumerIr::transmit(int32_t carrierFreq, const hidl_vec<int32_t>& pattern) {
    // 調(diào)用設(shè)備驅(qū)動函數(shù)
    return mDevice->transmit(mDevice, carrierFreq, pattern.data(), pattern.size()) == 0; 
}

Return<void> ConsumerIr::getCarrierFreqs(getCarrierFreqs_cb _hidl_cb) {
    int32_t len = mDevice->get_num_carrier_freqs(mDevice); // 調(diào)用設(shè)備驅(qū)動函數(shù)
    ...
    consumerir_freq_range_t *rangeAr = new consumerir_freq_range_t[len];
    bool success = (mDevice->get_carrier_freqs(mDevice, len, rangeAr) >= 0);
    ...
    return Void();
}
...

還有基礎(chǔ)關(guān)鍵的地方。
hardware/interfaces/ir/1.0/default/service.cpp
直通模式:

#define LOG_TAG "android.hardware.ir@1.0-service"

#include <android/hardware/ir/1.0/IConsumerIr.h>
#include <hidl/LegacySupport.h>

using android::hardware::ir::V1_0::IConsumerIr;
using android::hardware::defaultPassthroughServiceImplementation;

int main() {
    // 核心注冊函數(shù):自動加載HAL實(shí)現(xiàn)庫
    return defaultPassthroughServiceImplementation<IConsumerIr>();
}

通過直通模式及“ 服務(wù)與調(diào)用者處于同一進(jìn)程 ” ,還有一種模式是 綁定式服務(wù)運(yùn)行在獨(dú)立進(jìn)程
綁定模式:舉例

// hardware/interfaces/hello/1.0/default/HelloService.cpp
#include <hidl/HidlTransportSupport.h>

using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;

int main() {
    configureRpcThreadpool(4, true); // 配置Binder線程池
    
    // 創(chuàng)建Binderized服務(wù)
    android::sp<IHello> service = new HelloImpl();
    service->registerAsService(); // 注冊到hwservicemanager
    
    joinRpcThreadpool(); // 進(jìn)入Binder循環(huán)
    return 0;
}

針對這一層還有.rc.bp 的配置,感興趣的自己去找源碼看。

驅(qū)動部分:

最后的最后我們簡單看看實(shí)際調(diào)用的驅(qū)動部分,由于不同模組驅(qū)動有所不同這里僅做參考。
hardware/libhardware/include/hardware/consumerir.h
hardware/libhardware/modules/consumerir/consumerir.c

#include <hardware/consumerir.h>
#include <hardware/hardware.h>
...
static int consumerir_open(const hw_module_t* module, const char* name,
        hw_device_t** device){
  ...
    dev->transmit = consumerir_transmit; // 指向?qū)嶋H驅(qū)動函數(shù)
    dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs;
    dev->get_carrier_freqs = consumerir_get_carrier_freqs; // 指向?qū)嶋H驅(qū)動函數(shù)
 ...
}
...
// 向系統(tǒng)注冊HAL    
static struct hw_module_methods_t consumerir_module_methods = {.open = consumerir_open,};
consumerir_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        ...
        .methods            = &consumerir_module_methods,
    },
};

如果反這來看,其實(shí)就是完整的通過自定義系統(tǒng)服務(wù)來大同應(yīng)用端和硬件設(shè)備端的調(diào)用。
這里特別提醒,為了保證API 的可見性。我們還需要更新current.txt
frameworks/base/api/current.txt

 public final class ConsumerIrManager.CarrierFrequencyRange {
    ctor public ConsumerIrManager.CarrierFrequencyRange(int, int);
    method public int getMaxFrequency();
    method public int getMinFrequency();
 }

部分還需要在frameworks/base/core/res/res/values/public.xml中注冊新資源。
在系統(tǒng)源碼中關(guān)于HIDL都會使用vts進(jìn)行HIDL自動化測試。例子在源碼中有很多自行參考。

有部分細(xì)節(jié)沒有照顧到,還望補(bǔ)充和指正,謝謝~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容