Android4.4電源管理——回調函數


1、基本概念:

(1)什么是回調函數?    簡而言之,回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用為調用它所指向的函數時,我們就說這是回調函數。
(2)為什么要使用回調函數?    因為可以把調用者與被調用者分開。調用者不關心誰是被調用者,所有它需知道的,只是存在一個具有某種特定原型、某些限制條件(如返回值為int)的被調用函數。    如果想知道回調函數在實際中有什么作用,先假設有這樣一種情況,我們要編寫一個庫,它提供了某些排序算法的實現,如冒泡排序、快速排序、shell排序、shake排序等等,但為使庫更加通用,不想在函數中嵌入排序邏輯,而讓使用者來實現相應的邏輯;或者,想讓庫可用於多種數據類型(int、float、string),此時,該怎么辦呢?可以使用函數指針,並進行回調。

2、Android中的回調函數/對象

2.1、JNI層到JAVA層

com_android_server_power_PowerManagerService.cpp

//回調函數聲明

static struct {
    jmethodID wakeUpFromNative;
    jmethodID goToSleepFromNative;
    jmethodID userActivityFromNative;
} gPowerManagerServiceClassInfo;

int register_android_server_PowerManagerService(JNIEnv* env) {

    //注冊JNI函數,供JAVA層調用。JAVA——》JNI

    int res = jniRegisterNativeMethods(env, "com/android/server/power/PowerManagerService",
            gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods));
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");

    // 注冊回調函數,使JNI層可以調用JAVA層函數。JNI——》JAVA

    jclass clazz;
    FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");

    GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
            "wakeUpFromNative", "(J)V");

    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz,
            "goToSleepFromNative", "(JI)V");

    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
            "userActivityFromNative", "(JII)V");


    // 初始化本地全局變量
    for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
        gLastEventTime[i] = LLONG_MIN;
    }
    gScreenOn = true;

    gScreenBright = true;

    //初始化驅動接口函數

    gPowerManagerServiceObj = NULL;
    gPowerModule = NULL;
    return 0;

}


//具體實注冊的現函數

android_media_MediaDrm.cpp

#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
    var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
    LOG_FATAL_IF(! var, "Unable to find method " fieldName);


//回調函數的實現

PowerManagerService.java

    // Called from native code.
    private void wakeUpFromNative(long eventTime) {
        wakeUpInternal(eventTime);
    }


總結:通過在JNI層注冊JAVA層的函數,來實現JNI層到JAVA層的函數調用。

2.2、JAVA層到JAVA層

DisplayPowerController.java

//回調函數接口聲明

    /**
     * Asynchronous callbacks from the power controller to the power manager service.
     */
    public interface Callbacks {
        void onStateChanged();
        void onProximityPositive();
        void onProximityNegative();
    }

//觸發回調函數,調用實現對象的方法

    private void sendOnStateChangedWithWakelock() {
        mDisplaySuspendBlocker.acquire();
        mCallbackHandler.post(mOnStateChangedRunnable);
    }

    private final Runnable mOnStateChangedRunnable = new Runnable() {
        @Override
        public void run() {
            mCallbacks.onStateChanged();
            mDisplaySuspendBlocker.release();
        }
    };


//回調函數接口實現

PowerManagerService.java

    private final DisplayPowerController.Callbacks mDisplayPowerControllerCallbacks =
            new DisplayPowerController.Callbacks() {
        @Override
        public void onStateChanged() {
            synchronized (mLock) {
                mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
                updatePowerStateLocked();
            }
        }

        @Override
        public void onProximityPositive() {
            synchronized (mLock) {
                mProximityPositive = true;
                mDirty |= DIRTY_PROXIMITY_POSITIVE;
                updatePowerStateLocked();
            }
        }

        @Override
        public void onProximityNegative() {
            synchronized (mLock) {
                mProximityPositive = false;
                mDirty |= DIRTY_PROXIMITY_POSITIVE;
                userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
                        PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                updatePowerStateLocked();
            }
        }
    };

//將回調對象作為參數傳遞給被調用對象

    // The display power controller runs on the power manager service's
    // own handler thread to ensure timely operation.
    mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
                    mContext, mNotifier, mLightsService, twilight, sensorManager,
                    mDisplayManagerService, mDisplaySuspendBlocker, mDisplayBlanker,

                    mDisplayPowerControllerCallbacks, mHandler);

總結:通過在被調用類中聲明回調函數/對象,並在調用類中實現回調函數/對象,來實現通知調用類的目的。




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com