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

相关推荐
blackorbird23 分钟前
黑客靠谷歌定位找时机,窃密后远程摧毁手机核心数据!
智能手机
泥嚎泥嚎1 小时前
【Android】给App添加启动画面——SplashScreen
android·java
全栈派森1 小时前
初见 Dart:这门新语言如何让你的 App「动」起来?
android·flutter·ios
q***98521 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
恋猫de小郭1 小时前
Dart 3.10 发布,快来看有什么更新吧
android·前端·flutter
wanhengidc3 小时前
在云手机中云计算的作用都有哪些?
服务器·网络·游戏·智能手机·云计算
恋猫de小郭3 小时前
Flutter 3.38 发布,快来看看有什么更新吧
android·前端·flutter
百锦再8 小时前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
会跑的兔子9 小时前
Android 16 Kotlin协程 第二部分
android·windows·kotlin
键来大师9 小时前
Android15 RK3588 修改默认不锁屏不休眠
android·java·framework·rk3588