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

相关推荐
PC端游爱好者1 小时前
研究生如何远控实验室电脑?远程办公功能使用教程
macos·智能手机·电脑
B.-2 小时前
Flutter 应用在真机上调试的流程
android·flutter·ios·xcode·android-studio
有趣的杰克2 小时前
Flutter【04】高性能表单架构设计
android·flutter·dart
大耳猫7 小时前
主动测量View的宽高
android·ui
帅次10 小时前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
枯骨成佛10 小时前
Android中Crash Debug技巧
android
kim565916 小时前
android studio 更改gradle版本方法(备忘)
android·ide·gradle·android studio
咸芝麻鱼16 小时前
Android Studio | 最新版本配置要求高,JDK运行环境不适配,导致无法启动App
android·ide·android studio
无所谓จุ๊บ16 小时前
Android Studio使用c++编写
android·c++
csucoderlee16 小时前
Android Studio的新界面New UI,怎么切换回老界面
android·ui·android studio