安卓如何实现双击触摸唤醒点亮屏幕功能-源码分析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

相关推荐
雨白8 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹9 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空11 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭12 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日12 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安13 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑13 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟17 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡18 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0018 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体