安卓如何实现双击触摸唤醒点亮屏幕功能-源码分析linage os高通平台

背景:

前面文章已经有讲解过双击亮屏在一些方案调研情况,刚好linage os手机本身也有这个功能,刚好也有整体开源源码,所以今天带大家来对双击亮屏的源码部分进行剖析,本篇文章会一直分析到hal操作驱动节点。

设置作为切入点分析

根据字符tap to wake尝试grep相关字符在Settings这个代码中

bash 复制代码
nx563j_aosp14/packages/apps/Settings$ grep "tap_to_wake" ./ -rn
./src/com/android/settings/display/TapToWakePreferenceController.java:28:    private static final String KEY_TAP_TO_WAKE = "tap_to_wake";

看看相关代码

cpp 复制代码
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        boolean value = (Boolean) newValue;
        Settings.Secure.putInt(
                mContext.getContentResolver(), Settings.Secure.DOUBLE_TAP_TO_WAKE, value ? 1 : 0);
        return true;
    }

这里PowerManagerService会监听settings值的变化然后进行设置

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

cpp 复制代码
  private final class SettingsObserver extends ContentObserver {
        public SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            synchronized (mLock) {
                handleSettingsChangedLocked();
            }
        }
    }

具体对DOUBLE_TAP_TO_WAKE的处理

cpp 复制代码
if (mSupportsDoubleTapWakeConfig) {
    boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
            Settings.Secure.DOUBLE_TAP_TO_WAKE, DEFAULT_DOUBLE_TAP_TO_WAKE,
                    UserHandle.USER_CURRENT) != 0;
    if (doubleTapWakeEnabled != mDoubleTapWakeEnabled) {
        mDoubleTapWakeEnabled = doubleTapWakeEnabled;
        mNativeWrapper.nativeSetPowerMode(Mode.DOUBLE_TAP_TO_WAKE, mDoubleTapWakeEnabled);
    }
}

    /** Wrapper for PowerManager.nativeSetPowerMode */
        public boolean nativeSetPowerMode(int mode, boolean enabled) {
            return PowerManagerService.nativeSetPowerMode(mode, enabled);
        }

java代码就最后调用到了nativeSetPowerMode

native层面分析

frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

cpp 复制代码
static jboolean nativeSetPowerMode(JNIEnv* /* env */, jclass /* clazz */, jint mode,
                                   jboolean enabled) {
    return setPowerMode(static_cast<Mode>(mode), enabled);
}

static bool setPowerMode(Mode mode, bool enabled) {
    android::base::Timer t;
    auto result = gPowerHalController.setMode(mode, enabled);
    if (mode == Mode::INTERACTIVE && t.duration() > 20ms) {
        ALOGD("Excessive delay in setting interactive mode to %s while turning screen %s",
              enabled ? "true" : "false", enabled ? "on" : "off");
    }
    return result.isOk();
}

这里在native代码最后调用到了setPowerMode再接下来调用到PowerHalController的setMode

frameworks/native/services/powermanager/PowerHalController.cpp

cpp 复制代码
HalResult<void> PowerHalController::setMode(Mode mode, bool enabled) {
    std::shared_ptr<HalWrapper> handle = initHal();
    auto result = handle->setMode(mode, enabled);
    return processHalResult(result, "setMode");
}

这里的initHal明显可以看出其实是返回一个hal的接口来进行后面的setMode调用

cpp 复制代码
std::shared_ptr<HalWrapper> PowerHalController::initHal() {
    std::lock_guard<std::mutex> lock(mConnectedHalMutex);
    if (mConnectedHal == nullptr) {
        mConnectedHal = mHalConnector->connect();
    }
    return mConnectedHal;
}

这里进行了connect调用返回hal接口

cpp 复制代码
std::unique_ptr<HalWrapper> HalConnector::connect() {
    sp<IPower> halAidl = PowerHalLoader::loadAidl();
    if (halAidl) {
        return std::make_unique<AidlHalWrapper>(halAidl);
    }
    sp<V1_0::IPower> halHidlV1_0 = PowerHalLoader::loadHidlV1_0();
    sp<V1_1::IPower> halHidlV1_1 = PowerHalLoader::loadHidlV1_1();
    if (halHidlV1_1) {
        return std::make_unique<HidlHalWrapperV1_1>(halHidlV1_0, halHidlV1_1);
    }
    if (halHidlV1_0) {
        return std::make_unique<HidlHalWrapperV1_0>(halHidlV1_0);
    }
    return nullptr;
}

可以看出这里会依次加载aidl,hidl等接口,正常有aidl就会直接返回,没有就再加载hidl接口,这里的就需要结合具体设备上power hal的提供情况

power的aidl hal分析

我的机器设备是aidl的hal类型,hal代码是lineage os开源的,属于高通的通用一套8998代码

具体路径:

vendor/qcom/opensource/power

大家注意哈,这个hal代码路径大家自己根据情况确定,这种方式适合lineage os自带了高通开源代码

那么知道了路径后,继续分析上面提到的handle->setMode方法最后调用到了如下方法

hal实现代码路径:vendor/qcom/opensource/power/Power.cpp

cpp 复制代码
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
    LOG(ERROR) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
#ifdef MODE_EXT
    if (setDeviceSpecificMode(type, enabled)) {
        return ndk::ScopedAStatus::ok();
    }
#endif
    switch (type) {
#ifdef TAP_TO_WAKE_NODE//可以看到这里有一个宏,而且是根据mk中变量确定编译宏
        case Mode::DOUBLE_TAP_TO_WAKE:
        			//直接把enabled的值写入到TAP_TO_WAKE_NODE这个路径
            ::android::base::WriteStringToFile(enabled ? "1" : "0", TAP_TO_WAKE_NODE, true);
            break;
#else
        case Mode::DOUBLE_TAP_TO_WAKE:
#endif
        case Mode::LOW_POWER:
        case Mode::DEVICE_IDLE:
        case Mode::DISPLAY_INACTIVE:
        case Mode::AUDIO_STREAMING_LOW_LATENCY:
        case Mode::CAMERA_STREAMING_SECURE:
        case Mode::CAMERA_STREAMING_LOW:
        case Mode::CAMERA_STREAMING_MID:
        case Mode::CAMERA_STREAMING_HIGH:
        case Mode::VR:
  //省略
    }
    return ndk::ScopedAStatus::ok();
}

上面的#ifdef TAP_TO_WAKE_NODE这个宏已经在前面文章给大家剖析过,所以很容易知道这里的TAP_TO_WAKE_NODE值

bash 复制代码
TARGET_TAP_TO_WAKE_NODE := "/sys/class/touch/tpnode/synaptics/wake_gesture"

实际上到这里就很清楚hal中干的事情,就是对/sys/class/touch/tpnode/synaptics/wake_gesture写入对应的值0或1,具体也可以通过设置中开关,然后验证/sys/class/touch/tpnode/synaptics/wake_gesture的值

bash 复制代码
adb shell cat /sys/class/touch/tpnode/synaptics/wake_gesture
1
bash 复制代码
 adb shell cat /sys/class/touch/tpnode/synaptics/wake_gesture
0

那么剩下的事就是驱动层面实现的事情,本篇文章就不对驱动部分进行深入剖析了。

更多framework详细代码和资料参考如下链接

投屏专题部分:

https://mp.weixin.qq.com/s/IGm6VHMiAOPejC_H3N_SNg

hal+perfetto+surfaceflinger

https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg

其他课程七件套专题:

点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频试看:
https://www.bilibili.com/video/BV1wc41117L4/

参考相关链接:

https://blog.csdn.net/zhimokf/article/details/137958615

更多framework假威风耗:androidframework007

相关推荐
暮志未晚Webgl2 小时前
98. UE5 GAS RPG 实现闪电链技能负面效果
android·网络·ue5
命运之手2 小时前
【Android】Build Non-Fullscreen Transparent Activity
android·activity·dialog-style·non-fullscreen·transparent
kidding7233 小时前
uniapp打包安卓apk步骤
android·uni-app
趣浪出海3 小时前
Android 无Bug版 多语言设计方案!
android·bug·多语言·google play
程序猿陌名!3 小时前
Android 编译使用哪个key签名?
android
二流小码农3 小时前
鸿蒙开发:两个重磅更新,鸿蒙版微信要来了!
android·ios·harmonyos
通信侠3 小时前
android广播实现PIN码设置
android·java·经验分享
王能3 小时前
Kotlin真·全平台——Kotlin Compose Multiplatform Mobile(kotlin跨平台方案、KMP、KMM)
android·ios·kotlin·web·android jetpack·kmp·kmm
命运之手4 小时前
【Android】限制TextView大小并允许滑动
android