背景:
前面文章已经有讲解过双击亮屏在一些方案调研情况,刚好linage os手机本身也有这个功能,刚好也有整体开源源码,所以今天带大家来对双击亮屏的源码部分进行剖析,本篇文章会一直分析到hal操作驱动节点。
设置作为切入点分析
根据字符tap to wake尝试grep相关字符在Settings这个代码中
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";
看看相关代码
@Overridepublic 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
private final class SettingsObserver extends ContentObserver {public SettingsObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange, Uri uri) {synchronized (mLock) {handleSettingsChangedLocked();}}}
具体对DOUBLE_TAP_TO_WAKE的处理
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
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
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调用
std::shared_ptr<HalWrapper> PowerHalController::initHal() {std::lock_guard<std::mutex> lock(mConnectedHalMutex);if (mConnectedHal == nullptr) {mConnectedHal = mHalConnector->connect();}return mConnectedHal;
}
这里进行了connect调用返回hal接口
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
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {LOG(ERROR) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
#ifdef MODE_EXTif (setDeviceSpecificMode(type, enabled)) {return ndk::ScopedAStatus::ok();}
#endifswitch (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;
#elsecase Mode::DOUBLE_TAP_TO_WAKE:
#endifcase 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值
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的值
adb shell cat /sys/class/touch/tpnode/synaptics/wake_gesture
1
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