Framework基礎:jni層的傳感器服務器框架講解

天真.png

jni層的傳感器主要是用于作為客戶端來訪問native的SensorService,更多的是連接的作用

入口是/frameworks/base/core/java/android/hardware/SystemSensorManager.java

看看構造函數(shù),nativeCreate主要用于創(chuàng)建jni層的SensorManager足删,nativeClassInit用于獲取jni層對java層sensor結構的映射,便于在jni層修改java層的變量,nativeGetSensorAtIndex用于填充java層的sensor結構。

    public SystemSensorManager(Context context, Looper mainLooper) {
        mMainLooper = mainLooper;
        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
        mContext = context;
        mNativeInstance = nativeCreate(context.getOpPackageName());

        synchronized(mLock) {
            if (!sSensorModuleInitialized) {
                sSensorModuleInitialized = true;
                nativeClassInit();
            }
        }

        // initialize the sensor list
        for (int index = 0;;++index) {
            Sensor sensor = new Sensor();
            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
            mFullSensorsList.add(sensor);
            mHandleToSensor.append(sensor.getHandle(), sensor);
        }
    }

jni層的函數(shù)位于/frameworks/base/core/jni/android_hardware_SensorManager.cpp
注冊了java層與c層的對應關系,主要注冊了兩個java類SystemSensorManager,BaseEventQueue伏伐。最后會在c層調用到java層BaseEventQueue的dispatchSensorEvent完成傳感器數(shù)據(jù)傳遞帕翻。

int register_android_hardware_SensorManager(JNIEnv *env)
{
    RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
            gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));

    RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
            gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));

    gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
            "android/hardware/SystemSensorManager$BaseEventQueue");

    gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
            gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");

    gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
            gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");

    return 0;
}

使用CallVoidMethod回調java層的dispatchSensorEvent方法
                    if (receiverObj.get()) {
                        env->CallVoidMethod(receiverObj.get(),
                                            gBaseEventQueueClassInfo.dispatchSensorEvent,
                                            buffer[i].sensor,
                                            mScratch,
                                            status,
                                            buffer[i].timestamp);
                    }

使用registerListenerImpl來注冊傳感器監(jiān)聽,主要是構建一個SensorEventQueue鸠补,當sensor事件來到是時候,SensorEventQueue會被通知到嘀掸。

    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
        synchronized (mSensorListeners) {
            SensorEventQueue queue = mSensorListeners.get(listener);
            if (queue == null) {
                Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
                final String fullClassName = listener.getClass().getEnclosingClass() != null ?
                    listener.getClass().getEnclosingClass().getName() :
                    listener.getClass().getName();
                queue = new SensorEventQueue(listener, looper, this, fullClassName);
                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
                    queue.dispose();
                    return false;
                }
                mSensorListeners.put(listener, queue);
                return true;
            } else {
                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
            }
        }
    }

SensorEventQueue繼承與BaseEventQueue紫岩,初始化是會新建一個binder connection與sensor service通信,nativeInitBaseEventQueue就是用于建立binder通信的睬塌。native層對應函數(shù)nativeInitSensorEventQueue

        BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
            if (packageName == null) packageName = "";
            nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
                    new WeakReference<>(this), looper.getQueue(), mScratch,
                    packageName, mode, manager.mContext.getOpPackageName());
            mCloseGuard.open("dispose");
            mManager = manager;
        }

//native層對應函數(shù)
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
        jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {
    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    ScopedUtfChars packageUtf(env, packageName);
    String8 clientName(packageUtf.c_str());
    sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));//創(chuàng)建binder通信

    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak, scratch);//用于接收sensor事件
    receiver->incStrong((void*)nativeInitSensorEventQueue);
    return jlong(receiver.get());
}

SensorEventQueue被通知后泉蝌,會執(zhí)行dispatchSensorEvent來處理傳感器事件,最后會進入onSensorChanged進入處理歇万,這就回到了應用中的onSensorChanged處理了。注意的是勋陪,一個listener只能對應一個SensorEventQueue贪磺。

        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                long timestamp) {
            final Sensor sensor = mManager.mHandleToSensor.get(handle);
            SensorEvent t = null;
            synchronized (mSensorsEvents) {
                t = mSensorsEvents.get(handle);
            }

            if (t == null) {
                // This may happen if the client has unregistered and there are pending events in
                // the queue waiting to be delivered. Ignore.
                return;
            }
            // Copy from the values array.
            System.arraycopy(values, 0, t.values, 0, t.values.length);
            t.timestamp = timestamp;
            t.accuracy = inAccuracy;
            t.sensor = sensor;

            // call onAccuracyChanged() only if the value changes
            final int accuracy = mSensorAccuracies.get(handle);
            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
                mSensorAccuracies.put(handle, t.accuracy);
                mListener.onAccuracyChanged(t.sensor, t.accuracy);
            }
            mListener.onSensorChanged(t);
        }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诅愚,隨后出現(xiàn)的幾起案子寒锚,更是在濱河造成了極大的恐慌,老刑警劉巖违孝,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刹前,死亡現(xiàn)場離奇詭異,居然都是意外死亡等浊,警方通過查閱死者的電腦和手機腮郊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筹燕,“玉大人轧飞,你說我怎么就攤上這事∪鲎伲” “怎么了过咬?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長制妄。 經(jīng)常有香客問我掸绞,道長,這世上最難降的妖魔是什么耕捞? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任衔掸,我火速辦了婚禮,結果婚禮上俺抽,老公的妹妹穿的比我還像新娘敞映。我一直安慰自己,他們只是感情好磷斧,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布振愿。 她就那樣靜靜地躺著,像睡著了一般弛饭。 火紅的嫁衣襯著肌膚如雪冕末。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天侣颂,我揣著相機與錄音档桃,去河邊找鬼。 笑死憔晒,一個胖子當著我的面吹牛藻肄,可吹牛的內容都是我干的销凑。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼仅炊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了澎蛛?” 一聲冷哼從身側響起抚垄,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谋逻,沒想到半個月后呆馁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡毁兆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年浙滤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片气堕。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡纺腊,死狀恐怖,靈堂內的尸體忽然破棺而出茎芭,到底是詐尸還是另有隱情揖膜,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布梅桩,位于F島的核電站壹粟,受9級特大地震影響,放射性物質發(fā)生泄漏宿百。R本人自食惡果不足惜趁仙,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垦页。 院中可真熱鬧雀费,春花似錦、人聲如沸外臂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宋光。三九已至貌矿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罪佳,已是汗流浹背逛漫。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赘艳,地道東北人酌毡。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓克握,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枷踏。 傳聞我的和親對象是個殘疾皇子菩暗,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內容