mirror of
https://github.com/chararomandroid/android_device_samsung_a20
synced 2026-08-23 04:25:33 -04:00
[DNM] universal7885: import hardware/samsung deps
Signed-off-by: roynatech2544 <whiteshell2544@naver.com>
This commit is contained in:
parent
c25cedb10c
commit
76a69f9276
40 changed files with 3779 additions and 0 deletions
17
universal7885-common/aidl/Android.mk
Normal file
17
universal7885-common/aidl/Android.mk
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 The LineageOS Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(call all-subdir-makefiles)
|
||||||
23
universal7885-common/aidl/light/Android.bp
Normal file
23
universal7885-common/aidl/light/Android.bp
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 The LineageOS Project
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "android.hardware.light-service.samsung",
|
||||||
|
relative_install_path: "hw",
|
||||||
|
init_rc: ["android.hardware.light-service.samsung.rc"],
|
||||||
|
vintf_fragments: ["android.hardware.light-service.samsung.xml"],
|
||||||
|
local_include_dirs: ["include"],
|
||||||
|
srcs: [
|
||||||
|
"Lights.cpp",
|
||||||
|
"service.cpp",
|
||||||
|
],
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbinder_ndk",
|
||||||
|
"android.hardware.light-V1-ndk_platform",
|
||||||
|
],
|
||||||
|
vendor: true,
|
||||||
|
}
|
||||||
189
universal7885-common/aidl/light/Lights.cpp
Normal file
189
universal7885-common/aidl/light/Lights.cpp
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.lights-service.samsung"
|
||||||
|
|
||||||
|
#include <android-base/stringprintf.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "Lights.h"
|
||||||
|
|
||||||
|
#define COLOR_MASK 0x00ffffff
|
||||||
|
#define MAX_INPUT_BRIGHTNESS 255
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace light {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write value to path and close file.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static void set(const std::string& path, const T& value) {
|
||||||
|
std::ofstream file(path);
|
||||||
|
file << value << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T get(const std::string& path, const T& def) {
|
||||||
|
std::ifstream file(path);
|
||||||
|
T result;
|
||||||
|
|
||||||
|
file >> result;
|
||||||
|
return file.fail() ? def : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lights::Lights() {
|
||||||
|
mLights.emplace(LightType::BACKLIGHT,
|
||||||
|
std::bind(&Lights::handleBacklight, this, std::placeholders::_1));
|
||||||
|
#ifdef BUTTON_BRIGHTNESS_NODE
|
||||||
|
mLights.emplace(LightType::BUTTONS, std::bind(&Lights::handleButtons, this, std::placeholders::_1));
|
||||||
|
#endif /* BUTTON_BRIGHTNESS_NODE */
|
||||||
|
#ifdef LED_BLINK_NODE
|
||||||
|
mLights.emplace(LightType::BATTERY, std::bind(&Lights::handleBattery, this, std::placeholders::_1));
|
||||||
|
mLights.emplace(LightType::NOTIFICATIONS,
|
||||||
|
std::bind(&Lights::handleNotifications, this, std::placeholders::_1));
|
||||||
|
mLights.emplace(LightType::ATTENTION,
|
||||||
|
std::bind(&Lights::handleAttention, this, std::placeholders::_1));
|
||||||
|
#endif /* LED_BLINK_NODE */
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Lights::setLightState(int32_t id, const HwLightState& state) {
|
||||||
|
LightType type = static_cast<LightType>(id);
|
||||||
|
auto it = mLights.find(type);
|
||||||
|
|
||||||
|
if (it == mLights.end()) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lock global mutex until light state is updated.
|
||||||
|
*/
|
||||||
|
std::lock_guard<std::mutex> lock(mLock);
|
||||||
|
|
||||||
|
it->second(state);
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lights::handleBacklight(const HwLightState& state) {
|
||||||
|
uint32_t max_brightness = get(PANEL_MAX_BRIGHTNESS_NODE, MAX_INPUT_BRIGHTNESS);
|
||||||
|
uint32_t brightness = rgbToBrightness(state);
|
||||||
|
|
||||||
|
if (max_brightness != MAX_INPUT_BRIGHTNESS) {
|
||||||
|
brightness = brightness * max_brightness / MAX_INPUT_BRIGHTNESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(PANEL_BRIGHTNESS_NODE, brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BUTTON_BRIGHTNESS_NODE
|
||||||
|
void Lights::handleButtons(const HwLightState& state) {
|
||||||
|
#ifdef VAR_BUTTON_BRIGHTNESS
|
||||||
|
uint32_t brightness = rgbToBrightness(state);
|
||||||
|
#else
|
||||||
|
uint32_t brightness = (state.color & COLOR_MASK) ? 1 : 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
set(BUTTON_BRIGHTNESS_NODE, brightness);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LED_BLINK_NODE
|
||||||
|
void Lights::handleBattery(const HwLightState& state) {
|
||||||
|
mBatteryState = state;
|
||||||
|
setNotificationLED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lights::handleNotifications(const HwLightState& state) {
|
||||||
|
mNotificationState = state;
|
||||||
|
setNotificationLED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lights::handleAttention(const HwLightState& state) {
|
||||||
|
mAttentionState = state;
|
||||||
|
setNotificationLED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lights::setNotificationLED() {
|
||||||
|
int32_t adjusted_brightness = MAX_INPUT_BRIGHTNESS;
|
||||||
|
HwLightState state;
|
||||||
|
#ifdef LED_BLN_NODE
|
||||||
|
bool bln = false;
|
||||||
|
#endif /* LED_BLN_NODE */
|
||||||
|
|
||||||
|
if (mNotificationState.color & COLOR_MASK) {
|
||||||
|
adjusted_brightness = LED_BRIGHTNESS_NOTIFICATION;
|
||||||
|
state = mNotificationState;
|
||||||
|
#ifdef LED_BLN_NODE
|
||||||
|
bln = true;
|
||||||
|
#endif /* LED_BLN_NODE */
|
||||||
|
} else if (mAttentionState.color & COLOR_MASK) {
|
||||||
|
adjusted_brightness = LED_BRIGHTNESS_ATTENTION;
|
||||||
|
state = mAttentionState;
|
||||||
|
if (state.flashMode == FlashMode::HARDWARE) {
|
||||||
|
if (state.flashOnMs > 0 && state.flashOffMs == 0) state.flashMode = FlashMode::NONE;
|
||||||
|
state.color = 0x000000ff;
|
||||||
|
}
|
||||||
|
if (state.flashMode == FlashMode::NONE) {
|
||||||
|
state.color = 0;
|
||||||
|
}
|
||||||
|
} else if (mBatteryState.color & COLOR_MASK) {
|
||||||
|
adjusted_brightness = LED_BRIGHTNESS_BATTERY;
|
||||||
|
state = mBatteryState;
|
||||||
|
} else {
|
||||||
|
set(LED_BLINK_NODE, "0x00000000 0 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.flashMode == FlashMode::NONE) {
|
||||||
|
state.flashOnMs = 0;
|
||||||
|
state.flashOffMs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.color = calibrateColor(state.color & COLOR_MASK, adjusted_brightness);
|
||||||
|
set(LED_BLINK_NODE, ::android::base::StringPrintf("0x%08x %d %d", state.color, state.flashOnMs,
|
||||||
|
state.flashOffMs));
|
||||||
|
|
||||||
|
#ifdef LED_BLN_NODE
|
||||||
|
if (bln) {
|
||||||
|
set(LED_BLN_NODE, (state.color & COLOR_MASK) ? 1 : 0);
|
||||||
|
}
|
||||||
|
#endif /* LED_BLN_NODE */
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Lights::calibrateColor(uint32_t color, int32_t brightness) {
|
||||||
|
uint32_t red = ((color >> 16) & 0xFF) * LED_ADJUSTMENT_R;
|
||||||
|
uint32_t green = ((color >> 8) & 0xFF) * LED_ADJUSTMENT_G;
|
||||||
|
uint32_t blue = (color & 0xFF) * LED_ADJUSTMENT_B;
|
||||||
|
|
||||||
|
return (((red * brightness) / 255) << 16) + (((green * brightness) / 255) << 8) +
|
||||||
|
((blue * brightness) / 255);
|
||||||
|
}
|
||||||
|
#endif /* LED_BLINK_NODE */
|
||||||
|
|
||||||
|
#define AutoHwLight(light) {.id = (int32_t)light, .type = light, .ordinal = 0}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Lights::getLights(std::vector<HwLight> *_aidl_return) {
|
||||||
|
for (auto const& light : mLights) {
|
||||||
|
_aidl_return->push_back(AutoHwLight(light.first));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Lights::rgbToBrightness(const HwLightState& state) {
|
||||||
|
uint32_t color = state.color & COLOR_MASK;
|
||||||
|
|
||||||
|
return ((77 * ((color >> 16) & 0xff)) + (150 * ((color >> 8) & 0xff)) + (29 * (color & 0xff))) >>
|
||||||
|
8;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace light
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
} // namespace aidl
|
||||||
54
universal7885-common/aidl/light/Lights.h
Normal file
54
universal7885-common/aidl/light/Lights.h
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <aidl/android/hardware/light/BnLights.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "samsung_lights.h"
|
||||||
|
|
||||||
|
using ::aidl::android::hardware::light::HwLightState;
|
||||||
|
using ::aidl::android::hardware::light::HwLight;
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace light {
|
||||||
|
|
||||||
|
class Lights : public BnLights {
|
||||||
|
public:
|
||||||
|
Lights();
|
||||||
|
|
||||||
|
ndk::ScopedAStatus setLightState(int32_t id, const HwLightState& state) override;
|
||||||
|
ndk::ScopedAStatus getLights(std::vector<HwLight> *_aidl_return) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleBacklight(const HwLightState& state);
|
||||||
|
#ifdef BUTTON_BRIGHTNESS_NODE
|
||||||
|
void handleButtons(const HwLightState& state);
|
||||||
|
#endif /* BUTTON_BRIGHTNESS_NODE */
|
||||||
|
#ifdef LED_BLINK_NODE
|
||||||
|
void handleBattery(const HwLightState& state);
|
||||||
|
void handleNotifications(const HwLightState& state);
|
||||||
|
void handleAttention(const HwLightState& state);
|
||||||
|
void setNotificationLED();
|
||||||
|
uint32_t calibrateColor(uint32_t color, int32_t brightness);
|
||||||
|
|
||||||
|
HwLightState mAttentionState;
|
||||||
|
HwLightState mBatteryState;
|
||||||
|
HwLightState mNotificationState;
|
||||||
|
#endif /* LED_BLINK_NODE */
|
||||||
|
|
||||||
|
uint32_t rgbToBrightness(const HwLightState& state);
|
||||||
|
|
||||||
|
std::mutex mLock;
|
||||||
|
std::unordered_map<LightType, std::function<void(const HwLightState&)>> mLights;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace light
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
} // namespace aidl
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
service vendor.light-default /vendor/bin/hw/android.hardware.light-service.samsung
|
||||||
|
class hal
|
||||||
|
user system
|
||||||
|
group system
|
||||||
|
shutdown critical
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<manifest version="1.0" type="device">
|
||||||
|
<hal format="aidl">
|
||||||
|
<name>android.hardware.light</name>
|
||||||
|
<fqname>ILights/default</fqname>
|
||||||
|
</hal>
|
||||||
|
</manifest>
|
||||||
58
universal7885-common/aidl/light/include/samsung_lights.h
Normal file
58
universal7885-common/aidl/light/include/samsung_lights.h
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The CyanogenMod Project
|
||||||
|
* Copyright (C) 2017 The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SAMSUNG_LIGHTS_H
|
||||||
|
#define SAMSUNG_LIGHTS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board specific nodes
|
||||||
|
*
|
||||||
|
* If your kernel exposes these controls in another place, you can either
|
||||||
|
* symlink to the locations given here, or override this header in your
|
||||||
|
* device tree.
|
||||||
|
*/
|
||||||
|
#define PANEL_BRIGHTNESS_NODE "/sys/class/backlight/panel/brightness"
|
||||||
|
#define PANEL_MAX_BRIGHTNESS_NODE "/sys/class/backlight/panel/max_brightness"
|
||||||
|
#define BUTTON_BRIGHTNESS_NODE "/sys/class/sec/sec_touchkey/brightness"
|
||||||
|
#define LED_BLINK_NODE "/sys/class/sec/led/led_blink"
|
||||||
|
#define LED_BLN_NODE "/sys/class/misc/backlightnotification/notification_led"
|
||||||
|
|
||||||
|
// Uncomment to enable variable button brightness
|
||||||
|
//#define VAR_BUTTON_BRIGHTNESS 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Brightness adjustment factors
|
||||||
|
*
|
||||||
|
* If one of your device's LEDs is more powerful than the others, use these
|
||||||
|
* values to equalise them. This value is in the range 0.0-1.0.
|
||||||
|
*/
|
||||||
|
#define LED_ADJUSTMENT_R 1.0
|
||||||
|
#define LED_ADJUSTMENT_G 1.0
|
||||||
|
#define LED_ADJUSTMENT_B 1.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Light brightness factors
|
||||||
|
*
|
||||||
|
* It might make sense for all colours to be scaled down (for example, if your
|
||||||
|
* LED is too bright). Use these values to adjust the brightness of each
|
||||||
|
* light. This value is within the range 0-255.
|
||||||
|
*/
|
||||||
|
#define LED_BRIGHTNESS_BATTERY 255
|
||||||
|
#define LED_BRIGHTNESS_NOTIFICATION 255
|
||||||
|
#define LED_BRIGHTNESS_ATTENTION 255
|
||||||
|
|
||||||
|
#endif // SAMSUNG_LIGHTS_H
|
||||||
27
universal7885-common/aidl/light/service.cpp
Normal file
27
universal7885-common/aidl/light/service.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.light-service.samsung"
|
||||||
|
|
||||||
|
#include "Lights.h"
|
||||||
|
|
||||||
|
#include <android/binder_manager.h>
|
||||||
|
#include <android/binder_process.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
|
||||||
|
using ::aidl::android::hardware::light::Lights;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||||
|
std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
|
||||||
|
|
||||||
|
const std::string instance = std::string() + Lights::descriptor + "/default";
|
||||||
|
binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
|
||||||
|
CHECK(status == STATUS_OK);
|
||||||
|
|
||||||
|
ABinderProcess_joinThreadPool();
|
||||||
|
return EXIT_FAILURE; // should not reach
|
||||||
|
}
|
||||||
45
universal7885-common/aidl/power-libperfmgr/Android.bp
Normal file
45
universal7885-common/aidl/power-libperfmgr/Android.bp
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
soong_namespace {
|
||||||
|
imports: [
|
||||||
|
"hardware/google/pixel",
|
||||||
|
"hardware/google/interfaces",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "android.hardware.power-service.samsung-libperfmgr",
|
||||||
|
relative_install_path: "hw",
|
||||||
|
init_rc: ["android.hardware.power-service.samsung-libperfmgr.rc"],
|
||||||
|
vintf_fragments: ["android.hardware.power-service.samsung.xml"],
|
||||||
|
vendor: true,
|
||||||
|
shared_libs: [
|
||||||
|
"android.hardware.power-V1-ndk_platform",
|
||||||
|
"libbase",
|
||||||
|
"libcutils",
|
||||||
|
"liblog",
|
||||||
|
"libutils",
|
||||||
|
"libbinder_ndk",
|
||||||
|
"libperfmgr",
|
||||||
|
"pixel-power-ext-V1-ndk_platform",
|
||||||
|
],
|
||||||
|
srcs: [
|
||||||
|
"service.cpp",
|
||||||
|
"Power.cpp",
|
||||||
|
"PowerExt.cpp",
|
||||||
|
"InteractionHandler.cpp"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,264 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.power@-service.samsung-libperfmgr"
|
||||||
|
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <utils/Log.h>
|
||||||
|
#include <utils/Trace.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "InteractionHandler.h"
|
||||||
|
|
||||||
|
#define MAX_LENGTH 64
|
||||||
|
|
||||||
|
#define MSINSEC 1000L
|
||||||
|
#define USINMS 1000000L
|
||||||
|
|
||||||
|
static const std::vector<std::string> fb_idle_patch = {"/sys/class/drm/card0/device/idle_state",
|
||||||
|
"/sys/class/graphics/fb0/idle_state"};
|
||||||
|
|
||||||
|
InteractionHandler::InteractionHandler(std::shared_ptr<HintManager> const &hint_manager)
|
||||||
|
: mState(INTERACTION_STATE_UNINITIALIZED),
|
||||||
|
mWaitMs(100),
|
||||||
|
mMinDurationMs(1400),
|
||||||
|
mMaxDurationMs(5650),
|
||||||
|
mDurationMs(0),
|
||||||
|
mHintManager(hint_manager) {}
|
||||||
|
|
||||||
|
InteractionHandler::~InteractionHandler() {
|
||||||
|
Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fb_idle_open(void) {
|
||||||
|
int fd;
|
||||||
|
for (auto &path : fb_idle_patch) {
|
||||||
|
fd = open(path.c_str(), O_RDONLY);
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
ALOGE("Unable to open fb idle state path (%d)", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InteractionHandler::Init() {
|
||||||
|
std::lock_guard<std::mutex> lk(mLock);
|
||||||
|
|
||||||
|
if (mState != INTERACTION_STATE_UNINITIALIZED)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
mIdleFd = fb_idle_open();
|
||||||
|
|
||||||
|
mEventFd = eventfd(0, EFD_NONBLOCK);
|
||||||
|
if (mEventFd < 0) {
|
||||||
|
ALOGE("Unable to create event fd (%d)", errno);
|
||||||
|
if (mIdleFd >= 0) {
|
||||||
|
close(mIdleFd);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mState = INTERACTION_STATE_IDLE;
|
||||||
|
mThread = std::unique_ptr<std::thread>(new std::thread(&InteractionHandler::Routine, this));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::Exit() {
|
||||||
|
std::unique_lock<std::mutex> lk(mLock);
|
||||||
|
if (mState == INTERACTION_STATE_UNINITIALIZED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AbortWaitLocked();
|
||||||
|
mState = INTERACTION_STATE_UNINITIALIZED;
|
||||||
|
lk.unlock();
|
||||||
|
|
||||||
|
mCond.notify_all();
|
||||||
|
mThread->join();
|
||||||
|
|
||||||
|
close(mEventFd);
|
||||||
|
if (mIdleFd >= 0) {
|
||||||
|
close(mIdleFd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::PerfLock() {
|
||||||
|
ALOGV("%s: acquiring perf lock", __func__);
|
||||||
|
if (!mHintManager->DoHint("INTERACTION")) {
|
||||||
|
ALOGE("%s: do hint INTERACTION failed", __func__);
|
||||||
|
}
|
||||||
|
ATRACE_INT("interaction_lock", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::PerfRel() {
|
||||||
|
ALOGV("%s: releasing perf lock", __func__);
|
||||||
|
if (!mHintManager->EndHint("INTERACTION")) {
|
||||||
|
ALOGE("%s: end hint INTERACTION failed", __func__);
|
||||||
|
}
|
||||||
|
ATRACE_INT("interaction_lock", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t InteractionHandler::CalcTimespecDiffMs(struct timespec start, struct timespec end) {
|
||||||
|
size_t diff_in_us = 0;
|
||||||
|
diff_in_us += (end.tv_sec - start.tv_sec) * MSINSEC;
|
||||||
|
diff_in_us += (end.tv_nsec - start.tv_nsec) / USINMS;
|
||||||
|
return diff_in_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::Acquire(int32_t duration) {
|
||||||
|
ATRACE_CALL();
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lk(mLock);
|
||||||
|
if (mState == INTERACTION_STATE_UNINITIALIZED) {
|
||||||
|
ALOGW("%s: called while uninitialized", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inputDuration = duration + 650;
|
||||||
|
int finalDuration;
|
||||||
|
if (inputDuration > mMaxDurationMs)
|
||||||
|
finalDuration = mMaxDurationMs;
|
||||||
|
else if (inputDuration > mMinDurationMs)
|
||||||
|
finalDuration = inputDuration;
|
||||||
|
else
|
||||||
|
finalDuration = mMinDurationMs;
|
||||||
|
|
||||||
|
struct timespec cur_timespec;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &cur_timespec);
|
||||||
|
if (mState != INTERACTION_STATE_IDLE && finalDuration <= mDurationMs) {
|
||||||
|
size_t elapsed_time = CalcTimespecDiffMs(mLastTimespec, cur_timespec);
|
||||||
|
// don't hint if previous hint's duration covers this hint's duration
|
||||||
|
if (elapsed_time <= (mDurationMs - finalDuration)) {
|
||||||
|
ALOGV("%s: Previous duration (%d) cover this (%d) elapsed: %lld", __func__,
|
||||||
|
static_cast<int>(mDurationMs), static_cast<int>(finalDuration),
|
||||||
|
static_cast<long long>(elapsed_time));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mLastTimespec = cur_timespec;
|
||||||
|
mDurationMs = finalDuration;
|
||||||
|
|
||||||
|
ALOGV("%s: input: %d final duration: %d", __func__, duration, finalDuration);
|
||||||
|
|
||||||
|
if (mState == INTERACTION_STATE_WAITING)
|
||||||
|
AbortWaitLocked();
|
||||||
|
else if (mState == INTERACTION_STATE_IDLE)
|
||||||
|
PerfLock();
|
||||||
|
|
||||||
|
mState = INTERACTION_STATE_INTERACTION;
|
||||||
|
mCond.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::Release() {
|
||||||
|
std::lock_guard<std::mutex> lk(mLock);
|
||||||
|
if (mState == INTERACTION_STATE_WAITING) {
|
||||||
|
ATRACE_CALL();
|
||||||
|
PerfRel();
|
||||||
|
mState = INTERACTION_STATE_IDLE;
|
||||||
|
} else {
|
||||||
|
// clear any wait aborts pending in event fd
|
||||||
|
uint64_t val;
|
||||||
|
ssize_t ret = read(mEventFd, &val, sizeof(val));
|
||||||
|
|
||||||
|
ALOGW_IF(ret < 0, "%s: failed to clear eventfd (%zd, %d)", __func__, ret, errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be called while locked
|
||||||
|
void InteractionHandler::AbortWaitLocked() {
|
||||||
|
uint64_t val = 1;
|
||||||
|
ssize_t ret = write(mEventFd, &val, sizeof(val));
|
||||||
|
if (ret != sizeof(val))
|
||||||
|
ALOGW("Unable to write to event fd (%zd)", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
|
||||||
|
char data[MAX_LENGTH];
|
||||||
|
ssize_t ret;
|
||||||
|
struct pollfd pfd[2];
|
||||||
|
|
||||||
|
ATRACE_CALL();
|
||||||
|
|
||||||
|
ALOGV("%s: wait:%d timeout:%d", __func__, wait_ms, timeout_ms);
|
||||||
|
|
||||||
|
pfd[0].fd = mEventFd;
|
||||||
|
pfd[0].events = POLLIN;
|
||||||
|
pfd[1].fd = mIdleFd;
|
||||||
|
pfd[1].events = POLLPRI | POLLERR;
|
||||||
|
|
||||||
|
ret = poll(pfd, 1, wait_ms);
|
||||||
|
if (ret > 0) {
|
||||||
|
ALOGV("%s: wait aborted", __func__);
|
||||||
|
return;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
ALOGE("%s: error in poll while waiting", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIdleFd < 0) {
|
||||||
|
ret = poll(pfd, 1, timeout_ms);
|
||||||
|
if (ret > 0) {
|
||||||
|
ALOGV("%s: wait for duration aborted", __func__);
|
||||||
|
return;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
ALOGE("%s: Error on waiting for duration (%zd)", __func__, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pread(mIdleFd, data, sizeof(data), 0);
|
||||||
|
if (!ret) {
|
||||||
|
ALOGE("%s: Unexpected EOF!", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(data, "idle", 4)) {
|
||||||
|
ALOGV("%s: already idle", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = poll(pfd, 2, timeout_ms);
|
||||||
|
if (ret < 0)
|
||||||
|
ALOGE("%s: Error on waiting for idle (%zd)", __func__, ret);
|
||||||
|
else if (ret == 0)
|
||||||
|
ALOGV("%s: timed out waiting for idle", __func__);
|
||||||
|
else if (pfd[0].revents)
|
||||||
|
ALOGV("%s: wait for idle aborted", __func__);
|
||||||
|
else if (pfd[1].revents)
|
||||||
|
ALOGV("%s: idle detected", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionHandler::Routine() {
|
||||||
|
std::unique_lock<std::mutex> lk(mLock, std::defer_lock);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
lk.lock();
|
||||||
|
mCond.wait(lk, [&] { return mState != INTERACTION_STATE_IDLE; });
|
||||||
|
if (mState == INTERACTION_STATE_UNINITIALIZED)
|
||||||
|
return;
|
||||||
|
mState = INTERACTION_STATE_WAITING;
|
||||||
|
lk.unlock();
|
||||||
|
|
||||||
|
WaitForIdle(mWaitMs, mDurationMs);
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POWER_LIBPERFMGR_INTERACTIONHANDLER_H_
|
||||||
|
#define POWER_LIBPERFMGR_INTERACTIONHANDLER_H_
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <perfmgr/HintManager.h>
|
||||||
|
|
||||||
|
using ::android::perfmgr::HintManager;
|
||||||
|
|
||||||
|
enum interaction_state {
|
||||||
|
INTERACTION_STATE_UNINITIALIZED,
|
||||||
|
INTERACTION_STATE_IDLE,
|
||||||
|
INTERACTION_STATE_INTERACTION,
|
||||||
|
INTERACTION_STATE_WAITING,
|
||||||
|
};
|
||||||
|
|
||||||
|
class InteractionHandler {
|
||||||
|
public:
|
||||||
|
InteractionHandler(std::shared_ptr<HintManager> const &hint_manager);
|
||||||
|
~InteractionHandler();
|
||||||
|
bool Init();
|
||||||
|
void Exit();
|
||||||
|
void Acquire(int32_t duration);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Release();
|
||||||
|
void WaitForIdle(int32_t wait_ms, int32_t timeout_ms);
|
||||||
|
void AbortWaitLocked();
|
||||||
|
void Routine();
|
||||||
|
|
||||||
|
void PerfLock();
|
||||||
|
void PerfRel();
|
||||||
|
|
||||||
|
size_t CalcTimespecDiffMs(struct timespec start, struct timespec end);
|
||||||
|
|
||||||
|
enum interaction_state mState;
|
||||||
|
|
||||||
|
int mIdleFd;
|
||||||
|
int mEventFd;
|
||||||
|
|
||||||
|
int32_t mWaitMs;
|
||||||
|
int32_t mMinDurationMs;
|
||||||
|
int32_t mMaxDurationMs;
|
||||||
|
int32_t mDurationMs;
|
||||||
|
|
||||||
|
struct timespec mLastTimespec;
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> mThread;
|
||||||
|
std::mutex mLock;
|
||||||
|
std::condition_variable mCond;
|
||||||
|
std::shared_ptr<HintManager> mHintManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // POWER_LIBPERFMGR_INTERACTIONHANDLER_H_
|
||||||
262
universal7885-common/aidl/power-libperfmgr/Power.cpp
Normal file
262
universal7885-common/aidl/power-libperfmgr/Power.cpp
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
|
||||||
|
#define LOG_TAG "android.hardware.power-service.samsung-libperfmgr"
|
||||||
|
|
||||||
|
#include "Power.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <android-base/stringprintf.h>
|
||||||
|
#include <android-base/strings.h>
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
|
#include <utils/Trace.h>
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace google {
|
||||||
|
namespace hardware {
|
||||||
|
namespace power {
|
||||||
|
namespace impl {
|
||||||
|
namespace pixel {
|
||||||
|
|
||||||
|
constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
|
||||||
|
constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
|
||||||
|
constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
|
||||||
|
|
||||||
|
Power::Power(std::shared_ptr<HintManager> hm)
|
||||||
|
: mHintManager(hm),
|
||||||
|
mInteractionHandler(nullptr),
|
||||||
|
mVRModeOn(false),
|
||||||
|
mSustainedPerfModeOn(false) {
|
||||||
|
mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager);
|
||||||
|
mInteractionHandler->Init();
|
||||||
|
|
||||||
|
std::string state = ::android::base::GetProperty(kPowerHalStateProp, "");
|
||||||
|
if (state == "SUSTAINED_PERFORMANCE") {
|
||||||
|
ALOGI("Initialize with SUSTAINED_PERFORMANCE on");
|
||||||
|
mHintManager->DoHint("SUSTAINED_PERFORMANCE");
|
||||||
|
mSustainedPerfModeOn = true;
|
||||||
|
} else if (state == "VR") {
|
||||||
|
ALOGI("Initialize with VR on");
|
||||||
|
mHintManager->DoHint(state);
|
||||||
|
mVRModeOn = true;
|
||||||
|
} else if (state == "VR_SUSTAINED_PERFORMANCE") {
|
||||||
|
ALOGI("Initialize with SUSTAINED_PERFORMANCE and VR on");
|
||||||
|
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
|
||||||
|
mSustainedPerfModeOn = true;
|
||||||
|
mVRModeOn = true;
|
||||||
|
} else {
|
||||||
|
ALOGI("Initialize PowerHAL");
|
||||||
|
}
|
||||||
|
|
||||||
|
state = ::android::base::GetProperty(kPowerHalAudioProp, "");
|
||||||
|
if (state == "AUDIO_STREAMING_LOW_LATENCY") {
|
||||||
|
ALOGI("Initialize with AUDIO_LOW_LATENCY on");
|
||||||
|
mHintManager->DoHint(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = ::android::base::GetProperty(kPowerHalRenderingProp, "");
|
||||||
|
if (state == "EXPENSIVE_RENDERING") {
|
||||||
|
ALOGI("Initialize with EXPENSIVE_RENDERING on");
|
||||||
|
mHintManager->DoHint("EXPENSIVE_RENDERING");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now start to take powerhint
|
||||||
|
ALOGI("PowerHAL ready to process hints");
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
|
||||||
|
LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled;
|
||||||
|
ATRACE_INT(toString(type).c_str(), enabled);
|
||||||
|
switch (type) {
|
||||||
|
case Mode::LOW_POWER:
|
||||||
|
if (enabled) {
|
||||||
|
mHintManager->DoHint(toString(type));
|
||||||
|
} else {
|
||||||
|
mHintManager->EndHint(toString(type));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Mode::SUSTAINED_PERFORMANCE:
|
||||||
|
if (enabled && !mSustainedPerfModeOn) {
|
||||||
|
if (!mVRModeOn) { // Sustained mode only.
|
||||||
|
mHintManager->DoHint("SUSTAINED_PERFORMANCE");
|
||||||
|
} else { // Sustained + VR mode.
|
||||||
|
mHintManager->EndHint("VR");
|
||||||
|
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
|
||||||
|
}
|
||||||
|
mSustainedPerfModeOn = true;
|
||||||
|
} else if (!enabled && mSustainedPerfModeOn) {
|
||||||
|
mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
|
||||||
|
mHintManager->EndHint("SUSTAINED_PERFORMANCE");
|
||||||
|
if (mVRModeOn) { // Switch back to VR Mode.
|
||||||
|
mHintManager->DoHint("VR");
|
||||||
|
}
|
||||||
|
mSustainedPerfModeOn = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Mode::VR:
|
||||||
|
if (enabled && !mVRModeOn) {
|
||||||
|
if (!mSustainedPerfModeOn) { // VR mode only.
|
||||||
|
mHintManager->DoHint("VR");
|
||||||
|
} else { // Sustained + VR mode.
|
||||||
|
mHintManager->EndHint("SUSTAINED_PERFORMANCE");
|
||||||
|
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
|
||||||
|
}
|
||||||
|
mVRModeOn = true;
|
||||||
|
} else if (!enabled && mVRModeOn) {
|
||||||
|
mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
|
||||||
|
mHintManager->EndHint("VR");
|
||||||
|
if (mSustainedPerfModeOn) { // Switch back to sustained Mode.
|
||||||
|
mHintManager->DoHint("SUSTAINED_PERFORMANCE");
|
||||||
|
}
|
||||||
|
mVRModeOn = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Mode::LAUNCH:
|
||||||
|
if (mVRModeOn || mSustainedPerfModeOn) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::DOUBLE_TAP_TO_WAKE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::FIXED_PERFORMANCE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::EXPENSIVE_RENDERING:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::INTERACTIVE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::DEVICE_IDLE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::DISPLAY_INACTIVE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::AUDIO_STREAMING_LOW_LATENCY:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::CAMERA_STREAMING_SECURE:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::CAMERA_STREAMING_LOW:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::CAMERA_STREAMING_MID:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Mode::CAMERA_STREAMING_HIGH:
|
||||||
|
[[fallthrough]];
|
||||||
|
default:
|
||||||
|
if (enabled) {
|
||||||
|
mHintManager->DoHint(toString(type));
|
||||||
|
} else {
|
||||||
|
mHintManager->EndHint(toString(type));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) {
|
||||||
|
bool supported = mHintManager->IsHintSupported(toString(type));
|
||||||
|
switch (type) {
|
||||||
|
case Mode::LOW_POWER: // LOW_POWER handled insides PowerHAL specifically
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
case Mode::DOUBLE_TAP_TO_WAKE:
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
case Mode::INTERACTIVE:
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Power mode " << toString(type) << " isModeSupported: " << supported;
|
||||||
|
*_aidl_return = supported;
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
|
||||||
|
LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs;
|
||||||
|
ATRACE_INT(toString(type).c_str(), durationMs);
|
||||||
|
switch (type) {
|
||||||
|
case Boost::INTERACTION:
|
||||||
|
if (mVRModeOn || mSustainedPerfModeOn) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mInteractionHandler->Acquire(durationMs);
|
||||||
|
break;
|
||||||
|
case Boost::DISPLAY_UPDATE_IMMINENT:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Boost::ML_ACC:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Boost::AUDIO_LAUNCH:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Boost::CAMERA_LAUNCH:
|
||||||
|
[[fallthrough]];
|
||||||
|
case Boost::CAMERA_SHOT:
|
||||||
|
[[fallthrough]];
|
||||||
|
default:
|
||||||
|
if (mVRModeOn || mSustainedPerfModeOn) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (durationMs > 0) {
|
||||||
|
mHintManager->DoHint(toString(type), std::chrono::milliseconds(durationMs));
|
||||||
|
} else if (durationMs == 0) {
|
||||||
|
mHintManager->DoHint(toString(type));
|
||||||
|
} else {
|
||||||
|
mHintManager->EndHint(toString(type));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) {
|
||||||
|
bool supported = mHintManager->IsHintSupported(toString(type));
|
||||||
|
LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported;
|
||||||
|
*_aidl_return = supported;
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char *boolToString(bool b) {
|
||||||
|
return b ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
binder_status_t Power::dump(int fd, const char **, uint32_t) {
|
||||||
|
std::string buf(::android::base::StringPrintf(
|
||||||
|
"HintManager Running: %s\n"
|
||||||
|
"VRMode: %s\n"
|
||||||
|
"SustainedPerformanceMode: %s\n",
|
||||||
|
boolToString(mHintManager->IsRunning()), boolToString(mVRModeOn),
|
||||||
|
boolToString(mSustainedPerfModeOn)));
|
||||||
|
// Dump nodes through libperfmgr
|
||||||
|
mHintManager->DumpToFd(fd);
|
||||||
|
if (!::android::base::WriteStringToFd(buf, fd)) {
|
||||||
|
PLOG(ERROR) << "Failed to dump state to fd";
|
||||||
|
}
|
||||||
|
fsync(fd);
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pixel
|
||||||
|
} // namespace impl
|
||||||
|
} // namespace power
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace google
|
||||||
|
} // namespace aidl
|
||||||
61
universal7885-common/aidl/power-libperfmgr/Power.h
Normal file
61
universal7885-common/aidl/power-libperfmgr/Power.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <aidl/android/hardware/power/BnPower.h>
|
||||||
|
#include <perfmgr/HintManager.h>
|
||||||
|
|
||||||
|
#include "InteractionHandler.h"
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace google {
|
||||||
|
namespace hardware {
|
||||||
|
namespace power {
|
||||||
|
namespace impl {
|
||||||
|
namespace pixel {
|
||||||
|
|
||||||
|
using ::InteractionHandler;
|
||||||
|
using ::aidl::android::hardware::power::Boost;
|
||||||
|
using ::aidl::android::hardware::power::Mode;
|
||||||
|
using ::android::perfmgr::HintManager;
|
||||||
|
|
||||||
|
class Power : public ::aidl::android::hardware::power::BnPower {
|
||||||
|
public:
|
||||||
|
Power(std::shared_ptr<HintManager> hm);
|
||||||
|
ndk::ScopedAStatus setMode(Mode type, bool enabled) override;
|
||||||
|
ndk::ScopedAStatus isModeSupported(Mode type, bool *_aidl_return) override;
|
||||||
|
ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override;
|
||||||
|
ndk::ScopedAStatus isBoostSupported(Boost type, bool *_aidl_return) override;
|
||||||
|
binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<HintManager> mHintManager;
|
||||||
|
std::unique_ptr<InteractionHandler> mInteractionHandler;
|
||||||
|
std::atomic<bool> mVRModeOn;
|
||||||
|
std::atomic<bool> mSustainedPerfModeOn;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pixel
|
||||||
|
} // namespace impl
|
||||||
|
} // namespace power
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace google
|
||||||
|
} // namespace aidl
|
||||||
87
universal7885-common/aidl/power-libperfmgr/PowerExt.cpp
Normal file
87
universal7885-common/aidl/power-libperfmgr/PowerExt.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
|
||||||
|
#define LOG_TAG "android.hardware.power-service.samsung.ext-libperfmgr"
|
||||||
|
|
||||||
|
#include "PowerExt.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <android-base/stringprintf.h>
|
||||||
|
#include <android-base/strings.h>
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
|
#include <utils/Trace.h>
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace google {
|
||||||
|
namespace hardware {
|
||||||
|
namespace power {
|
||||||
|
namespace impl {
|
||||||
|
namespace pixel {
|
||||||
|
|
||||||
|
ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) {
|
||||||
|
LOG(DEBUG) << "PowerExt setMode: " << mode << " to: " << enabled;
|
||||||
|
ATRACE_INT(mode.c_str(), enabled);
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
mHintManager->DoHint(mode);
|
||||||
|
} else {
|
||||||
|
mHintManager->EndHint(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus PowerExt::isModeSupported(const std::string &mode, bool *_aidl_return) {
|
||||||
|
bool supported = mHintManager->IsHintSupported(mode);
|
||||||
|
LOG(INFO) << "PowerExt mode " << mode << " isModeSupported: " << supported;
|
||||||
|
*_aidl_return = supported;
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t durationMs) {
|
||||||
|
LOG(DEBUG) << "PowerExt setBoost: " << boost << " duration: " << durationMs;
|
||||||
|
ATRACE_INT(boost.c_str(), durationMs);
|
||||||
|
|
||||||
|
if (durationMs > 0) {
|
||||||
|
mHintManager->DoHint(boost, std::chrono::milliseconds(durationMs));
|
||||||
|
} else if (durationMs == 0) {
|
||||||
|
mHintManager->DoHint(boost);
|
||||||
|
} else {
|
||||||
|
mHintManager->EndHint(boost);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus PowerExt::isBoostSupported(const std::string &boost, bool *_aidl_return) {
|
||||||
|
bool supported = mHintManager->IsHintSupported(boost);
|
||||||
|
LOG(INFO) << "PowerExt boost " << boost << " isBoostSupported: " << supported;
|
||||||
|
*_aidl_return = supported;
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pixel
|
||||||
|
} // namespace impl
|
||||||
|
} // namespace power
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace google
|
||||||
|
} // namespace aidl
|
||||||
53
universal7885-common/aidl/power-libperfmgr/PowerExt.h
Normal file
53
universal7885-common/aidl/power-libperfmgr/PowerExt.h
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <aidl/google/hardware/power/extension/pixel/BnPowerExt.h>
|
||||||
|
#include <perfmgr/HintManager.h>
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace google {
|
||||||
|
namespace hardware {
|
||||||
|
namespace power {
|
||||||
|
namespace impl {
|
||||||
|
namespace pixel {
|
||||||
|
|
||||||
|
using ::android::perfmgr::HintManager;
|
||||||
|
|
||||||
|
class PowerExt : public ::aidl::google::hardware::power::extension::pixel::BnPowerExt {
|
||||||
|
public:
|
||||||
|
PowerExt(std::shared_ptr<HintManager> hm)
|
||||||
|
: mHintManager(hm) {}
|
||||||
|
ndk::ScopedAStatus setMode(const std::string &mode, bool enabled) override;
|
||||||
|
ndk::ScopedAStatus isModeSupported(const std::string &mode, bool *_aidl_return) override;
|
||||||
|
ndk::ScopedAStatus setBoost(const std::string &boost, int32_t durationMs) override;
|
||||||
|
ndk::ScopedAStatus isBoostSupported(const std::string &boost, bool *_aidl_return) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<HintManager> mHintManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pixel
|
||||||
|
} // namespace impl
|
||||||
|
} // namespace power
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace google
|
||||||
|
} // namespace aidl
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
service vendor.power-hal-aidl /vendor/bin/hw/android.hardware.power-service.samsung-libperfmgr
|
||||||
|
class hal
|
||||||
|
user root
|
||||||
|
group system radio
|
||||||
|
priority -20
|
||||||
|
|
||||||
|
on late-fs
|
||||||
|
start vendor.power-hal-aidl
|
||||||
|
|
||||||
|
# restart powerHAL when framework died
|
||||||
|
on property:init.svc.zygote=restarting && property:vendor.powerhal.state=*
|
||||||
|
setprop vendor.powerhal.state ""
|
||||||
|
setprop vendor.powerhal.audio ""
|
||||||
|
setprop vendor.powerhal.rendering ""
|
||||||
|
restart vendor.power-hal-aidl
|
||||||
|
|
||||||
|
# Clean up after b/163539793 resolved
|
||||||
|
on property:vendor.powerhal.dalvik.vm.dex2oat-threads=*
|
||||||
|
setprop dalvik.vm.dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads}
|
||||||
|
setprop dalvik.vm.restore-dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads}
|
||||||
|
|
||||||
|
on property:vendor.powerhal.dalvik.vm.dex2oat-cpu-set=*
|
||||||
|
setprop dalvik.vm.dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set}
|
||||||
|
setprop dalvik.vm.restore-dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set}
|
||||||
|
|
||||||
|
# initialize powerHAL when boot is completed
|
||||||
|
on property:sys.boot_completed=1
|
||||||
|
setprop vendor.powerhal.init 1
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<manifest version="1.0" type="device">
|
||||||
|
<hal format="aidl" override="true">
|
||||||
|
<name>android.hardware.power</name>
|
||||||
|
<fqname>IPower/default</fqname>
|
||||||
|
</hal>
|
||||||
|
</manifest>
|
||||||
|
|
@ -0,0 +1,441 @@
|
||||||
|
{
|
||||||
|
"Nodes": [
|
||||||
|
{
|
||||||
|
"Name": "CPULittleClusterMaxFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"1113600"
|
||||||
|
],
|
||||||
|
"DefaultIndex": 0,
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CPULittleClusterMinFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"1113600",
|
||||||
|
"576000"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CPUBigClusterMaxFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"2016000",
|
||||||
|
"1497600",
|
||||||
|
"1401600"
|
||||||
|
],
|
||||||
|
"DefaultIndex": 0,
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CPUBigClusterMinFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"1497600",
|
||||||
|
"1401600",
|
||||||
|
"1286400",
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_max_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"2016000",
|
||||||
|
"1497600",
|
||||||
|
"1401600"
|
||||||
|
],
|
||||||
|
"DefaultIndex": 0,
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CPUBigPlusClusterMinFreq",
|
||||||
|
"Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_min_freq",
|
||||||
|
"Values": [
|
||||||
|
"9999999",
|
||||||
|
"1497600",
|
||||||
|
"1401600",
|
||||||
|
"1286400",
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "GPUMaxFreq",
|
||||||
|
"Path": "/sys/class/kgsl/kgsl-3d0/devfreq/max_freq",
|
||||||
|
"Values": [
|
||||||
|
"585000000",
|
||||||
|
"427000000"
|
||||||
|
],
|
||||||
|
"DefaultIndex": 0,
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "GPUMinFreq",
|
||||||
|
"Path": "/sys/class/kgsl/kgsl-3d0/devfreq/min_freq",
|
||||||
|
"Values": [
|
||||||
|
"585000000",
|
||||||
|
"427000000",
|
||||||
|
"345000000",
|
||||||
|
"257000000"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "TASchedtuneBoost",
|
||||||
|
"Path": "/dev/stune/top-app/schedtune.boost",
|
||||||
|
"Values": [
|
||||||
|
"30",
|
||||||
|
"10"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PMQoSCpuDmaLatency",
|
||||||
|
"Path": "/dev/cpu_dma_latency",
|
||||||
|
"Values": [
|
||||||
|
"44",
|
||||||
|
"100"
|
||||||
|
],
|
||||||
|
"HoldFd": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "TouchscreenEnable",
|
||||||
|
"Path": "/sys/class/input/input3/enabled",
|
||||||
|
"Values": [
|
||||||
|
"1",
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"ResetOnInit": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DoubleTapToWakeEnable",
|
||||||
|
"Path": "/sys/class/sec/tsp/cmd",
|
||||||
|
"Values": [
|
||||||
|
"aot_enable,0",
|
||||||
|
"aot_enable,1"
|
||||||
|
],
|
||||||
|
"DefaultIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PowerHALMainState",
|
||||||
|
"Path": "vendor.powerhal.state",
|
||||||
|
"Values": [
|
||||||
|
"SUSTAINED_PERFORMANCE",
|
||||||
|
"VR_MODE",
|
||||||
|
"VR_SUSTAINED_PERFORMANCE",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"Type": "Property"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PowerHALAudioState",
|
||||||
|
"Path": "vendor.powerhal.audio",
|
||||||
|
"Values": [
|
||||||
|
"AUDIO_STREAMING_LOW_LATENCY",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"Type": "Property"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PowerHALRenderingState",
|
||||||
|
"Path": "vendor.powerhal.rendering",
|
||||||
|
"Values": [
|
||||||
|
"EXPENSIVE_RENDERING",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"Type": "Property"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PowerHALPerfProfileState",
|
||||||
|
"Path": "vendor.powerhal.perf_profile",
|
||||||
|
"Values": [
|
||||||
|
"POWER_SAVE",
|
||||||
|
"BIAS_POWER_SAVE",
|
||||||
|
"BIAS_PERFORMANCE",
|
||||||
|
"HIGH_PERFORMANCE"
|
||||||
|
],
|
||||||
|
"Type": "Property"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Actions": [
|
||||||
|
{
|
||||||
|
"PowerHint": "INTERACTION",
|
||||||
|
"Node": "CPUBigClusterMinFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1286400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "INTERACTION",
|
||||||
|
"Node": "CPUBigPlusClusterMinFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1286400"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "INTERACTION",
|
||||||
|
"Node": "CPULittleClusterMinFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1113600"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "INTERACTION",
|
||||||
|
"Node": "TASchedtuneBoost",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "CPUBigClusterMaxFreq",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "CPUBigClusterMinFreq",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "CPUBigPlusClusterMinFreq",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "CPULittleClusterMinFreq",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "LAUNCH",
|
||||||
|
"Node": "PMQoSCpuDmaLatency",
|
||||||
|
"Duration": 5000,
|
||||||
|
"Value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPUBigClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPUBigClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPUBigPlusClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPULittleClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "CPULittleClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_LAUNCH",
|
||||||
|
"Node": "PMQoSCpuDmaLatency",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_STREAMING_MID",
|
||||||
|
"Node": "CPUBigClusterMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "2016000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_STREAMING_MID",
|
||||||
|
"Node": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "2016000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPUBigClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPUBigClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPUBigPlusClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPULittleClusterMaxFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "CPULittleClusterMinFreq",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "9999999"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "CAMERA_SHOT",
|
||||||
|
"Node": "PMQoSCpuDmaLatency",
|
||||||
|
"Duration": 1000,
|
||||||
|
"Value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "AUDIO_LAUNCH",
|
||||||
|
"Node": "PMQoSCpuDmaLatency",
|
||||||
|
"Duration": 2000,
|
||||||
|
"Value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "AUDIO_STREAMING_LOW_LATENCY",
|
||||||
|
"Node": "PowerHALAudioState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "AUDIO_STREAMING_LOW_LATENCY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "AUDIO_STREAMING_LOW_LATENCY",
|
||||||
|
"Node": "PMQoSCpuDmaLatency",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "PowerHALMainState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "SUSTAINED_PERFORMANCE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "CPUBigClusterMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1401600"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "CPUBigPlusClusterMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1401600"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "CPULittleClusterMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1113600"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "GPUMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "427000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "VR_MODE",
|
||||||
|
"Node": "PowerHALMainState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "VR_MODE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "VR_SUSTAINED_PERFORMANCE",
|
||||||
|
"Node": "PowerHALMainState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "VR_SUSTAINED_PERFORMANCE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "EXPENSIVE_RENDERING",
|
||||||
|
"Node": "PowerHALRenderingState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "EXPENSIVE_RENDERING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "EXPENSIVE_RENDERING",
|
||||||
|
"Node": "GPUMinFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "427000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "EXPENSIVE_RENDERING",
|
||||||
|
"Node": "GPUMaxFreq",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "585000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "INTERACTIVE",
|
||||||
|
"Node": "TouchscreenEnable",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "DOUBLE_TAP_TO_WAKE",
|
||||||
|
"Node": "DoubleTapToWakeEnable",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "aot_enable,1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "PROFILE_POWER_SAVE",
|
||||||
|
"Node": "PowerHALPerfProfileState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "POWER_SAVE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "PROFILE_BIAS_POWER_SAVE",
|
||||||
|
"Node": "PowerHALPerfProfileState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "BIAS_POWER_SAVE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "PROFILE_BIAS_PERFORMANCE",
|
||||||
|
"Node": "PowerHALPerfProfileState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "BIAS_PERFORMANCE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PowerHint": "PROFILE_HIGH_PERFORMANCE",
|
||||||
|
"Node": "PowerHALPerfProfileState",
|
||||||
|
"Duration": 0,
|
||||||
|
"Value": "HIGH_PERFORMANCE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
74
universal7885-common/aidl/power-libperfmgr/service.cpp
Normal file
74
universal7885-common/aidl/power-libperfmgr/service.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.power-service.samsung-libperfmgr"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <android/binder_manager.h>
|
||||||
|
#include <android/binder_process.h>
|
||||||
|
|
||||||
|
#include "Power.h"
|
||||||
|
#include "PowerExt.h"
|
||||||
|
|
||||||
|
using aidl::google::hardware::power::impl::pixel::Power;
|
||||||
|
using aidl::google::hardware::power::impl::pixel::PowerExt;
|
||||||
|
using ::android::perfmgr::HintManager;
|
||||||
|
|
||||||
|
constexpr char kPowerHalConfigPath[] = "/vendor/etc/powerhint.json";
|
||||||
|
constexpr char kPowerHalInitProp[] = "vendor.powerhal.init";
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
LOG(INFO) << "Pixel Power HAL AIDL Service with Extension is starting.";
|
||||||
|
|
||||||
|
// Parse config but do not start the looper
|
||||||
|
std::shared_ptr<HintManager> hm = HintManager::GetFromJSON(kPowerHalConfigPath, false);
|
||||||
|
if (!hm) {
|
||||||
|
LOG(FATAL) << "Invalid config: " << kPowerHalConfigPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// single thread
|
||||||
|
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||||
|
|
||||||
|
// core service
|
||||||
|
std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>(hm);
|
||||||
|
ndk::SpAIBinder pwBinder = pw->asBinder();
|
||||||
|
|
||||||
|
// extension service
|
||||||
|
std::shared_ptr<PowerExt> pwExt = ndk::SharedRefBase::make<PowerExt>(hm);
|
||||||
|
|
||||||
|
// attach the extension to the same binder we will be registering
|
||||||
|
CHECK(STATUS_OK == AIBinder_setExtension(pwBinder.get(), pwExt->asBinder().get()));
|
||||||
|
|
||||||
|
const std::string instance = std::string() + Power::descriptor + "/default";
|
||||||
|
binder_status_t status = AServiceManager_addService(pw->asBinder().get(), instance.c_str());
|
||||||
|
CHECK(status == STATUS_OK);
|
||||||
|
LOG(INFO) << "Pixel Power HAL AIDL Service with Extension is started.";
|
||||||
|
|
||||||
|
std::thread initThread([&]() {
|
||||||
|
::android::base::WaitForProperty(kPowerHalInitProp, "1");
|
||||||
|
hm->Start();
|
||||||
|
});
|
||||||
|
initThread.detach();
|
||||||
|
|
||||||
|
ABinderProcess_joinThreadPool();
|
||||||
|
|
||||||
|
// should not reach
|
||||||
|
LOG(ERROR) << "Pixel Power HAL AIDL Service with Extension just died.";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
22
universal7885-common/aidl/vibrator/Android.bp
Normal file
22
universal7885-common/aidl/vibrator/Android.bp
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 The LineageOS Project
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "android.hardware.vibrator-service.samsung",
|
||||||
|
relative_install_path: "hw",
|
||||||
|
init_rc: ["android.hardware.vibrator-service.samsung.rc"],
|
||||||
|
vintf_fragments: ["android.hardware.vibrator-service.samsung.xml"],
|
||||||
|
srcs: [
|
||||||
|
"Vibrator.cpp",
|
||||||
|
"service.cpp",
|
||||||
|
],
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbinder_ndk",
|
||||||
|
"android.hardware.vibrator-V2-ndk_platform",
|
||||||
|
],
|
||||||
|
vendor: true,
|
||||||
|
}
|
||||||
296
universal7885-common/aidl/vibrator/Vibrator.cpp
Normal file
296
universal7885-common/aidl/vibrator/Vibrator.cpp
Normal file
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Vibrator.h"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace vibrator {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write value to path and close file.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static ndk::ScopedAStatus writeNode(const std::string& path, const T& value) {
|
||||||
|
std::ofstream node(path);
|
||||||
|
if (!node) {
|
||||||
|
LOG(ERROR) << "Failed to open: " << path;
|
||||||
|
return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "writeNode node: " << path << " value: " << value;
|
||||||
|
|
||||||
|
node << value << std::endl;
|
||||||
|
if (!node) {
|
||||||
|
LOG(ERROR) << "Failed to write: " << value;
|
||||||
|
return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool nodeExists(const std::string& path) {
|
||||||
|
std::ofstream f(path.c_str());
|
||||||
|
return f.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vibrator::Vibrator() {
|
||||||
|
mIsTimedOutVibrator = nodeExists(VIBRATOR_TIMEOUT_PATH);
|
||||||
|
mHasTimedOutIntensity = nodeExists(VIBRATOR_INTENSITY_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
|
||||||
|
*_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
|
||||||
|
IVibrator::CAP_EXTERNAL_CONTROL /*| IVibrator::CAP_COMPOSE_EFFECTS |
|
||||||
|
IVibrator::CAP_ALWAYS_ON_CONTROL*/;
|
||||||
|
|
||||||
|
if (mHasTimedOutIntensity) {
|
||||||
|
*_aidl_return = *_aidl_return | IVibrator::CAP_AMPLITUDE_CONTROL |
|
||||||
|
IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::off() {
|
||||||
|
return activate(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs, const std::shared_ptr<IVibratorCallback>& callback) {
|
||||||
|
ndk::ScopedAStatus status = activate(timeoutMs);
|
||||||
|
|
||||||
|
if (callback != nullptr) {
|
||||||
|
std::thread([=] {
|
||||||
|
LOG(INFO) << "Starting on on another thread";
|
||||||
|
usleep(timeoutMs * 1000);
|
||||||
|
LOG(INFO) << "Notifying on complete";
|
||||||
|
if (!callback->onComplete().isOk()) {
|
||||||
|
LOG(ERROR) << "Failed to call onComplete";
|
||||||
|
}
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength, const std::shared_ptr<IVibratorCallback>& callback, int32_t* _aidl_return) {
|
||||||
|
ndk::ScopedAStatus status;
|
||||||
|
uint8_t amplitude;
|
||||||
|
uint32_t ms;
|
||||||
|
|
||||||
|
amplitude = strengthToAmplitude(strength, &status);
|
||||||
|
if (!status.isOk()) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
setAmplitude(amplitude);
|
||||||
|
|
||||||
|
ms = effectToMs(effect, &status);
|
||||||
|
if (!status.isOk()) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = activate(ms);
|
||||||
|
|
||||||
|
if (callback != nullptr) {
|
||||||
|
std::thread([=] {
|
||||||
|
LOG(INFO) << "Starting perform on another thread";
|
||||||
|
usleep(ms * 1000);
|
||||||
|
LOG(INFO) << "Notifying perform complete";
|
||||||
|
callback->onComplete();
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
*_aidl_return = ms;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
|
||||||
|
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::HEAVY_CLICK,
|
||||||
|
Effect::TICK, Effect::TEXTURE_TICK, Effect::THUD, Effect::POP,
|
||||||
|
Effect::RINGTONE_1, Effect::RINGTONE_2, Effect::RINGTONE_3,
|
||||||
|
Effect::RINGTONE_4, Effect::RINGTONE_5, Effect::RINGTONE_6,
|
||||||
|
Effect::RINGTONE_7, Effect::RINGTONE_7, Effect::RINGTONE_8,
|
||||||
|
Effect::RINGTONE_9, Effect::RINGTONE_10, Effect::RINGTONE_11,
|
||||||
|
Effect::RINGTONE_12, Effect::RINGTONE_13, Effect::RINGTONE_14,
|
||||||
|
Effect::RINGTONE_15};
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
|
||||||
|
uint32_t intensity;
|
||||||
|
|
||||||
|
if (amplitude == 0) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "Setting amplitude: " << (uint32_t)amplitude;
|
||||||
|
|
||||||
|
intensity = std::lround((amplitude - 1) * INTENSITY_MAX / 254.0);
|
||||||
|
if (intensity > INTENSITY_MAX) {
|
||||||
|
intensity = INTENSITY_MAX;
|
||||||
|
}
|
||||||
|
LOG(DEBUG) << "Setting intensity: " << intensity;
|
||||||
|
|
||||||
|
if (mHasTimedOutIntensity) {
|
||||||
|
return writeNode(VIBRATOR_INTENSITY_PATH, intensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
|
||||||
|
if (mEnabled) {
|
||||||
|
LOG(WARNING) << "Setting external control while the vibrator is enabled is "
|
||||||
|
"unsupported!";
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "ExternalControl: " << mExternalControl << " -> " << enabled;
|
||||||
|
mExternalControl = enabled;
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive>* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive /*primitive*/, int32_t* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& /*composite*/, const std::shared_ptr<IVibratorCallback>& /*callback*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect>* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/, EffectStrength /*strength*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getResonantFrequency(float* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getQFactor(float* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getFrequencyResolution(float* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float>* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking>* /*_aidl_return*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle>& /*composite*/, const std::shared_ptr<IVibratorCallback>& /*callback*/) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus Vibrator::activate(uint32_t timeoutMs) {
|
||||||
|
std::lock_guard<std::mutex> lock{mMutex};
|
||||||
|
if (!mIsTimedOutVibrator) {
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeNode(VIBRATOR_TIMEOUT_PATH, timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Vibrator::strengthToAmplitude(EffectStrength strength, ndk::ScopedAStatus* status) {
|
||||||
|
*status = ndk::ScopedAStatus::ok();
|
||||||
|
|
||||||
|
switch (strength) {
|
||||||
|
case EffectStrength::LIGHT:
|
||||||
|
return 64;
|
||||||
|
case EffectStrength::MEDIUM:
|
||||||
|
return 128;
|
||||||
|
case EffectStrength::STRONG:
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Vibrator::effectToMs(Effect effect, ndk::ScopedAStatus* status) {
|
||||||
|
*status = ndk::ScopedAStatus::ok();
|
||||||
|
|
||||||
|
switch (effect) {
|
||||||
|
case Effect::CLICK:
|
||||||
|
return 20;
|
||||||
|
case Effect::DOUBLE_CLICK:
|
||||||
|
return 25;
|
||||||
|
case Effect::HEAVY_CLICK:
|
||||||
|
return 30;
|
||||||
|
case Effect::TICK:
|
||||||
|
case Effect::TEXTURE_TICK:
|
||||||
|
case Effect::THUD:
|
||||||
|
case Effect::POP:
|
||||||
|
return 15;
|
||||||
|
case Effect::RINGTONE_1:
|
||||||
|
case Effect::RINGTONE_2:
|
||||||
|
case Effect::RINGTONE_3:
|
||||||
|
case Effect::RINGTONE_4:
|
||||||
|
case Effect::RINGTONE_5:
|
||||||
|
case Effect::RINGTONE_6:
|
||||||
|
case Effect::RINGTONE_7:
|
||||||
|
case Effect::RINGTONE_8:
|
||||||
|
case Effect::RINGTONE_9:
|
||||||
|
case Effect::RINGTONE_10:
|
||||||
|
case Effect::RINGTONE_11:
|
||||||
|
case Effect::RINGTONE_12:
|
||||||
|
case Effect::RINGTONE_13:
|
||||||
|
case Effect::RINGTONE_14:
|
||||||
|
case Effect::RINGTONE_15:
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vibrator
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
} // namespace aidl
|
||||||
75
universal7885-common/aidl/vibrator/Vibrator.h
Normal file
75
universal7885-common/aidl/vibrator/Vibrator.h
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <aidl/android/hardware/vibrator/BnVibrator.h>
|
||||||
|
|
||||||
|
#define INTENSITY_MIN 1000
|
||||||
|
#define INTENSITY_MAX 10000
|
||||||
|
#define INTENSITY_DEFAULT INTENSITY_MAX
|
||||||
|
|
||||||
|
#define VIBRATOR_TIMEOUT_PATH "/sys/class/timed_output/vibrator/enable"
|
||||||
|
#define VIBRATOR_INTENSITY_PATH "/sys/class/timed_output/vibrator/intensity"
|
||||||
|
|
||||||
|
using ::aidl::android::hardware::vibrator::IVibratorCallback;
|
||||||
|
using ::aidl::android::hardware::vibrator::Braking;
|
||||||
|
using ::aidl::android::hardware::vibrator::Effect;
|
||||||
|
using ::aidl::android::hardware::vibrator::EffectStrength;
|
||||||
|
using ::aidl::android::hardware::vibrator::CompositeEffect;
|
||||||
|
using ::aidl::android::hardware::vibrator::CompositePrimitive;
|
||||||
|
using ::aidl::android::hardware::vibrator::PrimitivePwle;
|
||||||
|
|
||||||
|
namespace aidl {
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace vibrator {
|
||||||
|
|
||||||
|
class Vibrator : public BnVibrator {
|
||||||
|
public:
|
||||||
|
Vibrator();
|
||||||
|
ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus off() override;
|
||||||
|
ndk::ScopedAStatus on(int32_t timeoutMs, const std::shared_ptr<IVibratorCallback>& callback) override;
|
||||||
|
ndk::ScopedAStatus perform(Effect effect, EffectStrength strength, const std::shared_ptr<IVibratorCallback>& callback, int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus setAmplitude(float amplitude) override;
|
||||||
|
ndk::ScopedAStatus setExternalControl(bool enabled) override;
|
||||||
|
ndk::ScopedAStatus getCompositionDelayMax(int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getCompositionSizeMax(int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getSupportedPrimitives(std::vector<CompositePrimitive>* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getPrimitiveDuration(CompositePrimitive primitive, int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite, const std::shared_ptr<IVibratorCallback>& callback) override;
|
||||||
|
ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector<Effect>* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override;
|
||||||
|
ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
|
||||||
|
ndk::ScopedAStatus getResonantFrequency(float* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getQFactor(float* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getFrequencyResolution(float* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getFrequencyMinimum(float* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector<float>* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* _aidl_return) override;
|
||||||
|
ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle>& composite, const std::shared_ptr<IVibratorCallback>& callback) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ndk::ScopedAStatus activate(uint32_t ms);
|
||||||
|
static uint32_t effectToMs(Effect effect, ndk::ScopedAStatus* status);
|
||||||
|
static uint8_t strengthToAmplitude(EffectStrength strength, ndk::ScopedAStatus* status);
|
||||||
|
|
||||||
|
bool mEnabled{false};
|
||||||
|
bool mExternalControl{false};
|
||||||
|
std::mutex mMutex;
|
||||||
|
|
||||||
|
bool mIsTimedOutVibrator;
|
||||||
|
bool mHasTimedOutIntensity;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vibrator
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
} // namespace aidl
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
service vendor.vibrator-default /vendor/bin/hw/android.hardware.vibrator-service.samsung
|
||||||
|
class hal
|
||||||
|
user system
|
||||||
|
group system
|
||||||
|
shutdown critical
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<manifest version="1.0" type="device">
|
||||||
|
<hal format="aidl">
|
||||||
|
<name>android.hardware.vibrator</name>
|
||||||
|
<fqname>IVibrator/default</fqname>
|
||||||
|
</hal>
|
||||||
|
</manifest>
|
||||||
25
universal7885-common/aidl/vibrator/service.cpp
Normal file
25
universal7885-common/aidl/vibrator/service.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The LineageOS Project
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Vibrator.h"
|
||||||
|
|
||||||
|
#include <android/binder_manager.h>
|
||||||
|
#include <android/binder_process.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
|
||||||
|
using ::aidl::android::hardware::vibrator::Vibrator;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||||
|
std::shared_ptr<Vibrator> vibrator = ndk::SharedRefBase::make<Vibrator>();
|
||||||
|
|
||||||
|
const std::string instance = std::string() + Vibrator::descriptor + "/default";
|
||||||
|
binder_status_t status = AServiceManager_addService(vibrator->asBinder().get(), instance.c_str());
|
||||||
|
CHECK(status == STATUS_OK);
|
||||||
|
|
||||||
|
ABinderProcess_joinThreadPool();
|
||||||
|
return EXIT_FAILURE; // should not reach
|
||||||
|
}
|
||||||
61
universal7885-common/hidl/fingerprint/Android.mk
Normal file
61
universal7885-common/hidl/fingerprint/Android.mk
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 The LineageOS Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
BiometricsFingerprint.cpp \
|
||||||
|
service.cpp
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
|
libbase \
|
||||||
|
libhardware \
|
||||||
|
libhidlbase \
|
||||||
|
liblog \
|
||||||
|
libutils \
|
||||||
|
android.hardware.biometrics.fingerprint@2.1 \
|
||||||
|
android.hardware.biometrics.fingerprint@2.2 \
|
||||||
|
android.hardware.biometrics.fingerprint@2.3
|
||||||
|
|
||||||
|
ifeq ($(TARGET_SEC_FP_CALL_NOTIFY_ON_CANCEL),true)
|
||||||
|
LOCAL_CFLAGS += -DCALL_NOTIFY_ON_CANCEL
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_SEC_FP_USES_PERCENTAGE_SAMPLES),true)
|
||||||
|
LOCAL_CFLAGS += -DUSES_PERCENTAGE_SAMPLES
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_SEC_FP_CALL_CANCEL_ON_ENROLL_COMPLETION),true)
|
||||||
|
LOCAL_CFLAGS += -DCALL_CANCEL_ON_ENROLL_COMPLETION
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_SEC_FP_HAS_FINGERPRINT_GESTURES),true)
|
||||||
|
LOCAL_CFLAGS += -DHAS_FINGERPRINT_GESTURES
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.3-service.samsung
|
||||||
|
LOCAL_INIT_RC := android.hardware.biometrics.fingerprint@2.3-service.samsung.rc
|
||||||
|
LOCAL_VINTF_FRAGMENTS := android.hardware.biometrics.fingerprint@2.3-service.samsung.xml
|
||||||
|
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_OWNER := samsung
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||||
518
universal7885-common/hidl/fingerprint/BiometricsFingerprint.cpp
Normal file
518
universal7885-common/hidl/fingerprint/BiometricsFingerprint.cpp
Normal file
|
|
@ -0,0 +1,518 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#define LOG_TAG "android.hardware.biometrics.fingerprint@2.3-service.samsung"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
|
||||||
|
#include <hardware/hw_auth_token.h>
|
||||||
|
|
||||||
|
#include <hardware/fingerprint.h>
|
||||||
|
#include <hardware/hardware.h>
|
||||||
|
#include "BiometricsFingerprint.h"
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef HAS_FINGERPRINT_GESTURES
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace biometrics {
|
||||||
|
namespace fingerprint {
|
||||||
|
namespace V2_3 {
|
||||||
|
namespace implementation {
|
||||||
|
|
||||||
|
using RequestStatus = android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
|
||||||
|
|
||||||
|
BiometricsFingerprint* BiometricsFingerprint::sInstance = nullptr;
|
||||||
|
|
||||||
|
BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr) {
|
||||||
|
sInstance = this; // keep track of the most recent instance
|
||||||
|
if (!openHal()) {
|
||||||
|
LOG(ERROR) << "Can't open HAL module";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_FINGERPRINT_GESTURES
|
||||||
|
request(FINGERPRINT_REQUEST_NAVIGATION_MODE_START, 1);
|
||||||
|
|
||||||
|
uinputFd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
||||||
|
if (uinputFd < 0) {
|
||||||
|
LOG(ERROR) << "Unable to open uinput node";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = ioctl(uinputFd, UI_SET_EVBIT, EV_KEY) |
|
||||||
|
ioctl(uinputFd, UI_SET_KEYBIT, KEY_UP) |
|
||||||
|
ioctl(uinputFd, UI_SET_KEYBIT, KEY_DOWN);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG(ERROR) << "Unable to enable key events";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(uidev.name, "uinput-sec-fp");
|
||||||
|
uidev.id.bustype = BUS_VIRTUAL;
|
||||||
|
|
||||||
|
err = write(uinputFd, &uidev, sizeof(uidev));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Write user device to uinput node failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioctl(uinputFd, UI_DEV_CREATE);
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Unable to create uinput device";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Successfully registered uinput-sec-fp for fingerprint gestures";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricsFingerprint::~BiometricsFingerprint() {
|
||||||
|
if (ss_fingerprint_close() != 0) {
|
||||||
|
LOG(ERROR) << "Can't close HAL module";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<bool> BiometricsFingerprint::isUdfps(uint32_t) {
|
||||||
|
std::ifstream in("/sys/devices/virtual/fingerprint/fingerprint/position");
|
||||||
|
if (in) {
|
||||||
|
in.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> BiometricsFingerprint::onFingerDown(uint32_t, uint32_t, float, float) {
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> BiometricsFingerprint::onFingerUp() {
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::ErrorFilter(int32_t error) {
|
||||||
|
switch (error) {
|
||||||
|
case 0:
|
||||||
|
return RequestStatus::SYS_OK;
|
||||||
|
case -2:
|
||||||
|
return RequestStatus::SYS_ENOENT;
|
||||||
|
case -4:
|
||||||
|
return RequestStatus::SYS_EINTR;
|
||||||
|
case -5:
|
||||||
|
return RequestStatus::SYS_EIO;
|
||||||
|
case -11:
|
||||||
|
return RequestStatus::SYS_EAGAIN;
|
||||||
|
case -12:
|
||||||
|
return RequestStatus::SYS_ENOMEM;
|
||||||
|
case -13:
|
||||||
|
return RequestStatus::SYS_EACCES;
|
||||||
|
case -14:
|
||||||
|
return RequestStatus::SYS_EFAULT;
|
||||||
|
case -16:
|
||||||
|
return RequestStatus::SYS_EBUSY;
|
||||||
|
case -22:
|
||||||
|
return RequestStatus::SYS_EINVAL;
|
||||||
|
case -28:
|
||||||
|
return RequestStatus::SYS_ENOSPC;
|
||||||
|
case -110:
|
||||||
|
return RequestStatus::SYS_ETIMEDOUT;
|
||||||
|
default:
|
||||||
|
LOG(ERROR) << "An unknown error returned from fingerprint vendor library: " << error;
|
||||||
|
return RequestStatus::SYS_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate from errors returned by traditional HAL (see fingerprint.h) to
|
||||||
|
// HIDL-compliant FingerprintError.
|
||||||
|
FingerprintError BiometricsFingerprint::VendorErrorFilter(int32_t error, int32_t* vendorCode) {
|
||||||
|
*vendorCode = 0;
|
||||||
|
switch (error) {
|
||||||
|
case FINGERPRINT_ERROR_HW_UNAVAILABLE:
|
||||||
|
return FingerprintError::ERROR_HW_UNAVAILABLE;
|
||||||
|
case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
|
||||||
|
return FingerprintError::ERROR_UNABLE_TO_PROCESS;
|
||||||
|
case FINGERPRINT_ERROR_TIMEOUT:
|
||||||
|
return FingerprintError::ERROR_TIMEOUT;
|
||||||
|
case FINGERPRINT_ERROR_NO_SPACE:
|
||||||
|
return FingerprintError::ERROR_NO_SPACE;
|
||||||
|
case FINGERPRINT_ERROR_CANCELED:
|
||||||
|
return FingerprintError::ERROR_CANCELED;
|
||||||
|
case FINGERPRINT_ERROR_UNABLE_TO_REMOVE:
|
||||||
|
return FingerprintError::ERROR_UNABLE_TO_REMOVE;
|
||||||
|
case FINGERPRINT_ERROR_LOCKOUT:
|
||||||
|
return FingerprintError::ERROR_LOCKOUT;
|
||||||
|
default:
|
||||||
|
if (error >= FINGERPRINT_ERROR_VENDOR_BASE) {
|
||||||
|
// vendor specific code.
|
||||||
|
*vendorCode = error - FINGERPRINT_ERROR_VENDOR_BASE;
|
||||||
|
return FingerprintError::ERROR_VENDOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG(ERROR) << "Unknown error from fingerprint vendor library: " << error;
|
||||||
|
return FingerprintError::ERROR_UNABLE_TO_PROCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate acquired messages returned by traditional HAL (see fingerprint.h)
|
||||||
|
// to HIDL-compliant FingerprintAcquiredInfo.
|
||||||
|
FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(int32_t info,
|
||||||
|
int32_t* vendorCode) {
|
||||||
|
*vendorCode = 0;
|
||||||
|
switch (info) {
|
||||||
|
case FINGERPRINT_ACQUIRED_GOOD:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_GOOD;
|
||||||
|
case FINGERPRINT_ACQUIRED_PARTIAL:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_PARTIAL;
|
||||||
|
case FINGERPRINT_ACQUIRED_INSUFFICIENT:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
|
||||||
|
case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_IMAGER_DIRTY;
|
||||||
|
case FINGERPRINT_ACQUIRED_TOO_SLOW:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_TOO_SLOW;
|
||||||
|
case FINGERPRINT_ACQUIRED_TOO_FAST:
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_TOO_FAST;
|
||||||
|
default:
|
||||||
|
if (info >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
|
||||||
|
// vendor specific code.
|
||||||
|
*vendorCode = info - FINGERPRINT_ACQUIRED_VENDOR_BASE;
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_VENDOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG(ERROR) << "Unknown acquiredmsg from fingerprint vendor library: " << info;
|
||||||
|
return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<uint64_t> BiometricsFingerprint::setNotify(
|
||||||
|
const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
|
||||||
|
std::lock_guard<std::mutex> lock(mClientCallbackMutex);
|
||||||
|
mClientCallback = clientCallback;
|
||||||
|
// This is here because HAL 2.3 doesn't have a way to propagate a
|
||||||
|
// unique token for its driver. Subsequent versions should send a unique
|
||||||
|
// token for each call to setNotify(). This is fine as long as there's only
|
||||||
|
// one fingerprint device on the platform.
|
||||||
|
return reinterpret_cast<uint64_t>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<uint64_t> BiometricsFingerprint::preEnroll() {
|
||||||
|
return ss_fingerprint_pre_enroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::enroll(const hidl_array<uint8_t, 69>& hat,
|
||||||
|
uint32_t gid, uint32_t timeoutSec) {
|
||||||
|
const hw_auth_token_t* authToken = reinterpret_cast<const hw_auth_token_t*>(hat.data());
|
||||||
|
|
||||||
|
return ErrorFilter(ss_fingerprint_enroll(authToken, gid, timeoutSec));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::postEnroll() {
|
||||||
|
return ErrorFilter(ss_fingerprint_post_enroll());
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<uint64_t> BiometricsFingerprint::getAuthenticatorId() {
|
||||||
|
return ss_fingerprint_get_auth_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::cancel() {
|
||||||
|
int32_t ret = ss_fingerprint_cancel();
|
||||||
|
|
||||||
|
#ifdef CALL_NOTIFY_ON_CANCEL
|
||||||
|
if (ret == 0) {
|
||||||
|
fingerprint_msg_t msg{};
|
||||||
|
msg.type = FINGERPRINT_ERROR;
|
||||||
|
msg.data.error = FINGERPRINT_ERROR_CANCELED;
|
||||||
|
notify(&msg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ErrorFilter(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::enumerate() {
|
||||||
|
if (ss_fingerprint_enumerate != nullptr) {
|
||||||
|
return ErrorFilter(ss_fingerprint_enumerate());
|
||||||
|
}
|
||||||
|
|
||||||
|
return RequestStatus::SYS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::remove(uint32_t gid, uint32_t fid) {
|
||||||
|
return ErrorFilter(ss_fingerprint_remove(gid, fid));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::setActiveGroup(uint32_t gid,
|
||||||
|
const hidl_string& storePath) {
|
||||||
|
if (storePath.size() >= PATH_MAX || storePath.size() <= 0) {
|
||||||
|
LOG(ERROR) << "Bad path length: " << storePath.size();
|
||||||
|
return RequestStatus::SYS_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(storePath.c_str(), W_OK)) {
|
||||||
|
return RequestStatus::SYS_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorFilter(ss_fingerprint_set_active_group(gid, storePath.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId, uint32_t gid) {
|
||||||
|
return ErrorFilter(ss_fingerprint_authenticate(operationId, gid));
|
||||||
|
}
|
||||||
|
|
||||||
|
IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
|
||||||
|
if (!sInstance) {
|
||||||
|
sInstance = new BiometricsFingerprint();
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BiometricsFingerprint::openHal() {
|
||||||
|
void* handle = dlopen("libbauthserver.so", RTLD_NOW);
|
||||||
|
if (handle) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ss_fingerprint_close =
|
||||||
|
reinterpret_cast<typeof(ss_fingerprint_close)>(dlsym(handle, "ss_fingerprint_close"));
|
||||||
|
ss_fingerprint_open =
|
||||||
|
reinterpret_cast<typeof(ss_fingerprint_open)>(dlsym(handle, "ss_fingerprint_open"));
|
||||||
|
|
||||||
|
ss_set_notify_callback = reinterpret_cast<typeof(ss_set_notify_callback)>(
|
||||||
|
dlsym(handle, "ss_set_notify_callback"));
|
||||||
|
ss_fingerprint_pre_enroll = reinterpret_cast<typeof(ss_fingerprint_pre_enroll)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_pre_enroll"));
|
||||||
|
ss_fingerprint_enroll =
|
||||||
|
reinterpret_cast<typeof(ss_fingerprint_enroll)>(dlsym(handle, "ss_fingerprint_enroll"));
|
||||||
|
ss_fingerprint_post_enroll = reinterpret_cast<typeof(ss_fingerprint_post_enroll)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_post_enroll"));
|
||||||
|
ss_fingerprint_get_auth_id = reinterpret_cast<typeof(ss_fingerprint_get_auth_id)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_get_auth_id"));
|
||||||
|
ss_fingerprint_cancel =
|
||||||
|
reinterpret_cast<typeof(ss_fingerprint_cancel)>(dlsym(handle, "ss_fingerprint_cancel"));
|
||||||
|
ss_fingerprint_enumerate = reinterpret_cast<typeof(ss_fingerprint_enumerate)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_enumerate"));
|
||||||
|
ss_fingerprint_remove =
|
||||||
|
reinterpret_cast<typeof(ss_fingerprint_remove)>(dlsym(handle, "ss_fingerprint_remove"));
|
||||||
|
ss_fingerprint_set_active_group = reinterpret_cast<typeof(ss_fingerprint_set_active_group)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_set_active_group"));
|
||||||
|
ss_fingerprint_authenticate = reinterpret_cast<typeof(ss_fingerprint_authenticate)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_authenticate"));
|
||||||
|
ss_fingerprint_request = reinterpret_cast<typeof(ss_fingerprint_request)>(
|
||||||
|
dlsym(handle, "ss_fingerprint_request"));
|
||||||
|
|
||||||
|
if ((err = ss_fingerprint_open(nullptr)) != 0) {
|
||||||
|
LOG(ERROR) << "Can't open fingerprint, error: " << err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = ss_set_notify_callback(BiometricsFingerprint::notify)) != 0) {
|
||||||
|
LOG(ERROR) << "Can't register fingerprint module callback, error: " << err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BiometricsFingerprint::notify(const fingerprint_msg_t* msg) {
|
||||||
|
BiometricsFingerprint* thisPtr =
|
||||||
|
static_cast<BiometricsFingerprint*>(BiometricsFingerprint::getInstance());
|
||||||
|
std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
|
||||||
|
if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
|
||||||
|
LOG(ERROR) << "Receiving callbacks before the client callback is registered.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uint64_t devId = 1;
|
||||||
|
switch (msg->type) {
|
||||||
|
case FINGERPRINT_ERROR: {
|
||||||
|
int32_t vendorCode = 0;
|
||||||
|
FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
|
||||||
|
LOG(DEBUG) << "onError(" << static_cast<int>(result) << ")";
|
||||||
|
if (!thisPtr->mClientCallback->onError(devId, result, vendorCode).isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onError callback";
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case FINGERPRINT_ACQUIRED: {
|
||||||
|
if (msg->data.acquired.acquired_info > SEM_FINGERPRINT_EVENT_BASE) {
|
||||||
|
thisPtr->handleEvent(msg->data.acquired.acquired_info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int32_t vendorCode = 0;
|
||||||
|
FingerprintAcquiredInfo result =
|
||||||
|
VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
|
||||||
|
LOG(DEBUG) << "onAcquired(" << static_cast<int>(result) << ")";
|
||||||
|
if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onAcquired callback";
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case FINGERPRINT_TEMPLATE_ENROLLING:
|
||||||
|
#ifdef USES_PERCENTAGE_SAMPLES
|
||||||
|
const_cast<fingerprint_msg_t*>(msg)->data.enroll.samples_remaining =
|
||||||
|
100 - msg->data.enroll.samples_remaining;
|
||||||
|
#endif
|
||||||
|
#ifdef CALL_CANCEL_ON_ENROLL_COMPLETION
|
||||||
|
if(msg->data.enroll.samples_remaining == 0) {
|
||||||
|
thisPtr->ss_fingerprint_cancel();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
LOG(DEBUG) << "onEnrollResult(fid=" << msg->data.enroll.finger.fid
|
||||||
|
<< ", gid=" << msg->data.enroll.finger.gid
|
||||||
|
<< ", rem=" << msg->data.enroll.samples_remaining << ")";
|
||||||
|
if (!thisPtr->mClientCallback
|
||||||
|
->onEnrollResult(devId, msg->data.enroll.finger.fid,
|
||||||
|
msg->data.enroll.finger.gid, msg->data.enroll.samples_remaining)
|
||||||
|
.isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onEnrollResult callback";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINGERPRINT_TEMPLATE_REMOVED:
|
||||||
|
LOG(DEBUG) << "onRemove(fid=" << msg->data.removed.finger.fid
|
||||||
|
<< ", gid=" << msg->data.removed.finger.gid
|
||||||
|
<< ", rem=" << msg->data.removed.remaining_templates << ")";
|
||||||
|
if (!thisPtr->mClientCallback
|
||||||
|
->onRemoved(devId, msg->data.removed.finger.fid, msg->data.removed.finger.gid,
|
||||||
|
msg->data.removed.remaining_templates)
|
||||||
|
.isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onRemoved callback";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINGERPRINT_AUTHENTICATED:
|
||||||
|
LOG(DEBUG) << "onAuthenticated(fid=" << msg->data.authenticated.finger.fid
|
||||||
|
<< ", gid=" << msg->data.authenticated.finger.gid << ")";
|
||||||
|
if (msg->data.authenticated.finger.fid != 0) {
|
||||||
|
const uint8_t* hat = reinterpret_cast<const uint8_t*>(&msg->data.authenticated.hat);
|
||||||
|
const hidl_vec<uint8_t> token(
|
||||||
|
std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
|
||||||
|
if (!thisPtr->mClientCallback
|
||||||
|
->onAuthenticated(devId, msg->data.authenticated.finger.fid,
|
||||||
|
msg->data.authenticated.finger.gid, token)
|
||||||
|
.isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onAuthenticated callback";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not a recognized fingerprint
|
||||||
|
if (!thisPtr->mClientCallback
|
||||||
|
->onAuthenticated(devId, msg->data.authenticated.finger.fid,
|
||||||
|
msg->data.authenticated.finger.gid, hidl_vec<uint8_t>())
|
||||||
|
.isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onAuthenticated callback";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINGERPRINT_TEMPLATE_ENUMERATING:
|
||||||
|
LOG(DEBUG) << "onEnumerate(fid=" << msg->data.enumerated.finger.fid
|
||||||
|
<< ", gid=" << msg->data.enumerated.finger.gid
|
||||||
|
<< ", rem=" << msg->data.enumerated.remaining_templates << ")";
|
||||||
|
if (!thisPtr->mClientCallback
|
||||||
|
->onEnumerate(devId, msg->data.enumerated.finger.fid,
|
||||||
|
msg->data.enumerated.finger.gid,
|
||||||
|
msg->data.enumerated.remaining_templates)
|
||||||
|
.isOk()) {
|
||||||
|
LOG(ERROR) << "failed to invoke fingerprint onEnumerate callback";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BiometricsFingerprint::handleEvent(int eventCode) {
|
||||||
|
switch (eventCode) {
|
||||||
|
#ifdef HAS_FINGERPRINT_GESTURES
|
||||||
|
case SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_DOWN:
|
||||||
|
case SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP:
|
||||||
|
struct input_event event {};
|
||||||
|
int keycode = eventCode == SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP ?
|
||||||
|
KEY_UP : KEY_DOWN;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
// Report the key
|
||||||
|
event.type = EV_KEY;
|
||||||
|
event.code = keycode;
|
||||||
|
event.value = 1;
|
||||||
|
err = write(uinputFd, &event, sizeof(event));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Write EV_KEY to uinput node failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force a flush with an EV_SYN
|
||||||
|
event.type = EV_SYN;
|
||||||
|
event.code = SYN_REPORT;
|
||||||
|
event.value = 0;
|
||||||
|
err = write(uinputFd, &event, sizeof(event));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Write EV_SYN to uinput node failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report the key
|
||||||
|
event.type = EV_KEY;
|
||||||
|
event.code = keycode;
|
||||||
|
event.value = 0;
|
||||||
|
err = write(uinputFd, &event, sizeof(event));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Write EV_KEY to uinput node failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force a flush with an EV_SYN
|
||||||
|
event.type = EV_SYN;
|
||||||
|
event.code = SYN_REPORT;
|
||||||
|
event.value = 0;
|
||||||
|
err = write(uinputFd, &event, sizeof(event));
|
||||||
|
if (err < 0) {
|
||||||
|
LOG(ERROR) << "Write EV_SYN to uinput node failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BiometricsFingerprint::request(int cmd, int param) {
|
||||||
|
// TO-DO: input, output handling not implemented
|
||||||
|
int result = ss_fingerprint_request(cmd, nullptr, 0, nullptr, 0, param);
|
||||||
|
LOG(INFO) << "request(cmd=" << cmd << ", param=" << param << ", result=" << result << ")";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BiometricsFingerprint::waitForSensor(std::chrono::milliseconds pollWait,
|
||||||
|
std::chrono::milliseconds timeOut) {
|
||||||
|
int sensorStatus = SEM_SENSOR_STATUS_WORKING;
|
||||||
|
std::chrono::milliseconds timeWaited = 0ms;
|
||||||
|
while (sensorStatus != SEM_SENSOR_STATUS_OK) {
|
||||||
|
if (sensorStatus == SEM_SENSOR_STATUS_CALIBRATION_ERROR
|
||||||
|
|| sensorStatus == SEM_SENSOR_STATUS_ERROR){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (timeWaited >= timeOut) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
sensorStatus = request(FINGERPRINT_REQUEST_GET_SENSOR_STATUS, 0);
|
||||||
|
std::this_thread::sleep_for(pollWait);
|
||||||
|
timeWaited += pollWait;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V2_3
|
||||||
|
} // namespace fingerprint
|
||||||
|
} // namespace biometrics
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
124
universal7885-common/hidl/fingerprint/BiometricsFingerprint.h
Normal file
124
universal7885-common/hidl/fingerprint/BiometricsFingerprint.h
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_3_BIOMETRICSFINGERPRINT_H
|
||||||
|
#define ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_3_BIOMETRICSFINGERPRINT_H
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#ifdef HAS_FINGERPRINT_GESTURES
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <hardware/fingerprint.h>
|
||||||
|
#include <hardware/hardware.h>
|
||||||
|
#include <hidl/MQDescriptor.h>
|
||||||
|
#include <hidl/Status.h>
|
||||||
|
#include <android/hardware/biometrics/fingerprint/2.3/IBiometricsFingerprint.h>
|
||||||
|
#include <android/hardware/biometrics/fingerprint/2.1/types.h>
|
||||||
|
|
||||||
|
#include "VendorConstants.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace biometrics {
|
||||||
|
namespace fingerprint {
|
||||||
|
namespace V2_3 {
|
||||||
|
namespace implementation {
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
using ::android::sp;
|
||||||
|
using ::android::hardware::hidl_string;
|
||||||
|
using ::android::hardware::hidl_vec;
|
||||||
|
using ::android::hardware::Return;
|
||||||
|
using ::android::hardware::Void;
|
||||||
|
using ::android::hardware::biometrics::fingerprint::V2_3::IBiometricsFingerprint;
|
||||||
|
using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
|
||||||
|
using ::android::hardware::biometrics::fingerprint::V2_1::FingerprintAcquiredInfo;
|
||||||
|
using ::android::hardware::biometrics::fingerprint::V2_1::FingerprintError;
|
||||||
|
using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
|
||||||
|
|
||||||
|
struct BiometricsFingerprint : public IBiometricsFingerprint {
|
||||||
|
BiometricsFingerprint();
|
||||||
|
~BiometricsFingerprint();
|
||||||
|
|
||||||
|
// Method to wrap legacy HAL with BiometricsFingerprint class
|
||||||
|
static IBiometricsFingerprint* getInstance();
|
||||||
|
|
||||||
|
// Methods from ::android::hardware::biometrics::fingerprint::V2_3::IBiometricsFingerprint follow.
|
||||||
|
Return<uint64_t> setNotify(
|
||||||
|
const sp<IBiometricsFingerprintClientCallback>& clientCallback) override;
|
||||||
|
Return<uint64_t> preEnroll() override;
|
||||||
|
Return<RequestStatus> enroll(const hidl_array<uint8_t, 69>& hat, uint32_t gid,
|
||||||
|
uint32_t timeoutSec) override;
|
||||||
|
Return<RequestStatus> postEnroll() override;
|
||||||
|
Return<uint64_t> getAuthenticatorId() override;
|
||||||
|
Return<RequestStatus> cancel() override;
|
||||||
|
Return<RequestStatus> enumerate() override;
|
||||||
|
Return<RequestStatus> remove(uint32_t gid, uint32_t fid) override;
|
||||||
|
Return<RequestStatus> setActiveGroup(uint32_t gid, const hidl_string& storePath) override;
|
||||||
|
Return<RequestStatus> authenticate(uint64_t operationId, uint32_t gid) override;
|
||||||
|
Return<bool> isUdfps(uint32_t sensorID) override;
|
||||||
|
Return<void> onFingerDown(uint32_t x, uint32_t y, float minor, float major) override;
|
||||||
|
Return<void> onFingerUp() override;
|
||||||
|
Return<void> onShowUdfpsOverlay(){ return Void();}
|
||||||
|
Return<void> onHideUdfpsOverlay(){ return Void();}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool openHal();
|
||||||
|
int request(int cmd, int param);
|
||||||
|
int waitForSensor(std::chrono::milliseconds pollWait, std::chrono::milliseconds timeOut);
|
||||||
|
static void notify(
|
||||||
|
const fingerprint_msg_t* msg); /* Static callback for legacy HAL implementation */
|
||||||
|
void handleEvent(int eventCode);
|
||||||
|
static Return<RequestStatus> ErrorFilter(int32_t error);
|
||||||
|
static FingerprintError VendorErrorFilter(int32_t error, int32_t* vendorCode);
|
||||||
|
static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
|
||||||
|
static BiometricsFingerprint* sInstance;
|
||||||
|
|
||||||
|
std::mutex mClientCallbackMutex;
|
||||||
|
sp<IBiometricsFingerprintClientCallback> mClientCallback;
|
||||||
|
#ifdef HAS_FINGERPRINT_GESTURES
|
||||||
|
int uinputFd;
|
||||||
|
struct uinput_user_dev uidev {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int (*ss_fingerprint_close)();
|
||||||
|
int (*ss_fingerprint_open)(const char* id);
|
||||||
|
|
||||||
|
int (*ss_set_notify_callback)(fingerprint_notify_t notify);
|
||||||
|
uint64_t (*ss_fingerprint_pre_enroll)();
|
||||||
|
int (*ss_fingerprint_enroll)(const hw_auth_token_t* hat, uint32_t gid, uint32_t timeout_sec);
|
||||||
|
int (*ss_fingerprint_post_enroll)();
|
||||||
|
uint64_t (*ss_fingerprint_get_auth_id)();
|
||||||
|
int (*ss_fingerprint_cancel)();
|
||||||
|
int (*ss_fingerprint_enumerate)();
|
||||||
|
int (*ss_fingerprint_remove)(uint32_t gid, uint32_t fid);
|
||||||
|
int (*ss_fingerprint_set_active_group)(uint32_t gid, const char* store_path);
|
||||||
|
int (*ss_fingerprint_authenticate)(uint64_t operation_id, uint32_t gid);
|
||||||
|
int (*ss_fingerprint_request)(uint32_t cmd, char *inBuf, uint32_t inBuf_length, char *outBuf, uint32_t outBuf_length, uint32_t param);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V2_3
|
||||||
|
} // namespace fingerprint
|
||||||
|
} // namespace biometrics
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
|
||||||
|
#endif // ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_3_BIOMETRICSFINGERPRINT_H
|
||||||
104
universal7885-common/hidl/fingerprint/VendorConstants.h
Normal file
104
universal7885-common/hidl/fingerprint/VendorConstants.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2020 The LineageOS Project
|
||||||
|
|
||||||
|
#ifndef SAMSUNG_FINGERPRINT_CONSTANTS_H
|
||||||
|
#define SAMSUNG_FINGERPRINT_CONSTANTS_H
|
||||||
|
|
||||||
|
// Fingerprint requests
|
||||||
|
#define FINGERPRINT_REQUEST_ENROLL_SESSION 1002
|
||||||
|
#define FINGERPRINT_REQUEST_ENROLL_TYPE 18
|
||||||
|
#define FINGERPRINT_REQUEST_ENUMERATE 11
|
||||||
|
#define FINGERPRINT_REQUEST_GET_FP_IDS 1003
|
||||||
|
#define FINGERPRINT_REQUEST_GET_MAX_TEMPLATE_NUMBER 1004
|
||||||
|
#define FINGERPRINT_REQUEST_GET_SENSOR_INFO 5
|
||||||
|
#define FINGERPRINT_REQUEST_GET_SENSOR_STATUS 6
|
||||||
|
#define FINGERPRINT_REQUEST_GET_TOUCH_CNT 1007
|
||||||
|
#define FINGERPRINT_REQUEST_GET_UNIQUE_ID 7
|
||||||
|
#define FINGERPRINT_REQUEST_GET_USERIDS 12
|
||||||
|
#define FINGERPRINT_REQUEST_GET_VERSION 4
|
||||||
|
#define FINGERPRINT_REQUEST_HAS_FEATURE 1006
|
||||||
|
#define FINGERPRINT_REQUEST_LOCKOUT 1001
|
||||||
|
#define FINGERPRINT_REQUEST_NAVIGATION_LCD_ONOFF 17
|
||||||
|
#define FINGERPRINT_REQUEST_NAVIGATION_MODE_END 16
|
||||||
|
#define FINGERPRINT_REQUEST_NAVIGATION_MODE_START 15
|
||||||
|
#define FINGERPRINT_REQUEST_PAUSE 0
|
||||||
|
#define FINGERPRINT_REQUEST_PROCESS_FIDO 9
|
||||||
|
#define FINGERPRINT_REQUEST_REMOVE_FINGER 1000
|
||||||
|
#define FINGERPRINT_REQUEST_RESUME 1
|
||||||
|
#define FINGERPRINT_REQUEST_SENSOR_TEST_NORMALSCAN 3
|
||||||
|
#define FINGERPRINT_REQUEST_SESSION_OPEN 2
|
||||||
|
#define FINGERPRINT_REQUEST_SET_ACTIVE_GROUP 8
|
||||||
|
#define FINGERPRINT_REQUEST_UPDATE_SID 10
|
||||||
|
|
||||||
|
#define SEM_REQUEST_FORCE_CBGE 21
|
||||||
|
#define SEM_REQUEST_GET_FINGER_ICON_REMAIN_TIME 1010
|
||||||
|
#define SEM_REQUEST_GET_SECURITY_LEVEL 30
|
||||||
|
#define SEM_REQUEST_GET_SENSOR_TEST_RESULT 19
|
||||||
|
#define SEM_REQUEST_GET_TA_VERSION 10000
|
||||||
|
#define SEM_REQUEST_GET_TSP_BLOCK_STATUS 0x3F9
|
||||||
|
#define SEM_REQUEST_HIDE_INDISPLAY_AUTH_ANIMATION 0x3F4
|
||||||
|
#define SEM_REQUEST_INSTALL_TA 10001
|
||||||
|
#define SEM_REQUEST_IS_NEW_MATCHER 27
|
||||||
|
#define SEM_REQUEST_IS_TEMPLATE_CHANGED 25
|
||||||
|
#define SEM_REQUEST_MASK_CTL 0x3F5
|
||||||
|
#define SEM_REQUEST_MOVE_INDISPLAY_ICON 0x3F3
|
||||||
|
#define SEM_REQUEST_OPTICAL_CALIBRATION 0x3F8
|
||||||
|
#define SEM_REQUEST_REMOVE_ALL_USER 0x3F6
|
||||||
|
#define SEM_REQUEST_SET_ASP_LEVEL 20
|
||||||
|
#define SEM_REQUEST_SET_BOUNCER_SCREEN_STATUS 0x3FA
|
||||||
|
#define SEM_REQUEST_SET_SCREEN_STATUS 0x3F0
|
||||||
|
#define SEM_REQUEST_SHOW_INDISPLAY_AUTH_ANIMATION 1009
|
||||||
|
#define SEM_REQUEST_TOUCH_EVENT 22
|
||||||
|
#define SEM_REQUEST_TOUCH_SENSITIVE_CHANGE 0x3F7
|
||||||
|
#define SEM_REQUEST_UPDATE_MATCHER 28
|
||||||
|
#define SEM_REQUEST_VENDOR_EGIS_CALIBRATION 23
|
||||||
|
#define SEM_REQUEST_VENDOR_QCOM_REMOVE_CBGE 24
|
||||||
|
#define SEM_REQUEST_WIRELESS_CHARGER_STATUS 29
|
||||||
|
|
||||||
|
// Fingerprint aquired codes
|
||||||
|
#define SEM_FINGERPRINT_ACQUIRED_DUPLICATED_IMAGE 1002
|
||||||
|
#define SEM_FINGERPRINT_ACQUIRED_LIGHT_TOUCH 1003
|
||||||
|
#define SEM_FINGERPRINT_ACQUIRED_TSP_BLOCK 1004
|
||||||
|
#define SEM_FINGERPRINT_ACQUIRED_TSP_UNBLOCK 1005
|
||||||
|
#define SEM_FINGERPRINT_ACQUIRED_WET_FINGER 1001
|
||||||
|
|
||||||
|
// Fingerprint errors
|
||||||
|
#define SEM_FINGERPRINT_ERROR_CALIBRATION 1001
|
||||||
|
#define SEM_FINGERPRINT_ERROR_DISABLED_BIOMETRICS 5002
|
||||||
|
#define SEM_FINGERPRINT_ERROR_INVALID_HW 1005
|
||||||
|
#define SEM_FINGERPRINT_ERROR_NEED_TO_RETRY 5000
|
||||||
|
#define SEM_FINGERPRINT_ERROR_ONE_HAND_MODE 5001
|
||||||
|
#define SEM_FINGERPRINT_ERROR_PATTERN_DETECTED 1007
|
||||||
|
#define SEM_FINGERPRINT_ERROR_SERVICE_FAILURE 1003
|
||||||
|
#define SEM_FINGERPRINT_ERROR_SMART_VIEW 5003
|
||||||
|
#define SEM_FINGERPRINT_ERROR_SYSTEM_FAILURE 1002
|
||||||
|
#define SEM_FINGERPRINT_ERROR_TA_UPDATE -100
|
||||||
|
#define SEM_FINGERPRINT_ERROR_TEMPLATE_CORRUPTED 1004
|
||||||
|
#define SEM_FINGERPRINT_ERROR_TEMPLATE_FORMAT_CHANGED 1006
|
||||||
|
#define SEM_FINGERPRINT_ERROR_WIRELESS_CHARGING 5004
|
||||||
|
|
||||||
|
// Fingerprint events
|
||||||
|
#define SEM_FINGERPRINT_EVENT_BASE 10000
|
||||||
|
#define SEM_FINGERPRINT_EVENT_CAPTURE_COMPLETED 10003
|
||||||
|
#define SEM_FINGERPRINT_EVENT_CAPTURE_FAILED 10006
|
||||||
|
#define SEM_FINGERPRINT_EVENT_CAPTURE_READY 10001
|
||||||
|
#define SEM_FINGERPRINT_EVENT_CAPTURE_STARTED 10002
|
||||||
|
#define SEM_FINGERPRINT_EVENT_CAPTURE_SUCCESS 10005
|
||||||
|
#define SEM_FINGERPRINT_EVENT_FACTORY_SNSR_SCRIPT_END 10009
|
||||||
|
#define SEM_FINGERPRINT_EVENT_FACTORY_SNSR_SCRIPT_START 10008
|
||||||
|
#define SEM_FINGERPRINT_EVENT_FINGER_LEAVE 10004
|
||||||
|
#define SEM_FINGERPRINT_EVENT_FINGER_LEAVE_TIMEOUT 10007
|
||||||
|
#define SEM_FINGERPRINT_EVENT_GESTURE_DTAP 20003
|
||||||
|
#define SEM_FINGERPRINT_EVENT_GESTURE_LPRESS 20004
|
||||||
|
#define SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_DOWN 20002
|
||||||
|
#define SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP 20001
|
||||||
|
#define SEM_FINGERPRINT_EVENT_SPEN_CONTROL_OFF 30002
|
||||||
|
#define SEM_FINGERPRINT_EVENT_SPEN_CONTROL_ON 30001
|
||||||
|
|
||||||
|
// Fingerprint sensor status codes
|
||||||
|
#define SEM_SENSOR_STATUS_CALIBRATION_ERROR 100045
|
||||||
|
#define SEM_SENSOR_STATUS_ERROR 100042
|
||||||
|
#define SEM_SENSOR_STATUS_OK 100040
|
||||||
|
#define SEM_SENSOR_STATUS_WORKING 100041
|
||||||
|
|
||||||
|
#endif // SAMSUNG_FINGERPRINT_CONSTANTS_H
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
service vendor.fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.3-service.samsung
|
||||||
|
# "class hal" causes a race condition on some devices due to files created
|
||||||
|
# in /data. As a workaround, postpone startup until later in boot once
|
||||||
|
# /data is mounted.
|
||||||
|
class late_start
|
||||||
|
user system
|
||||||
|
group system input uhid
|
||||||
|
writepid /dev/cpuset/system-background/tasks
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<manifest version="1.0" type="device">
|
||||||
|
<hal format="hidl" override="true">
|
||||||
|
<name>android.hardware.biometrics.fingerprint</name>
|
||||||
|
<transport>hwbinder</transport>
|
||||||
|
<version>2.3</version>
|
||||||
|
<interface>
|
||||||
|
<name>IBiometricsFingerprint</name>
|
||||||
|
<instance>default</instance>
|
||||||
|
</interface>
|
||||||
|
</hal>
|
||||||
|
</manifest>
|
||||||
51
universal7885-common/hidl/fingerprint/service.cpp
Normal file
51
universal7885-common/hidl/fingerprint/service.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.biometrics.fingerprint@2.3-service.samsung"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <hidl/HidlTransportSupport.h>
|
||||||
|
#include <utils/Errors.h>
|
||||||
|
|
||||||
|
#include "BiometricsFingerprint.h"
|
||||||
|
|
||||||
|
using android::hardware::configureRpcThreadpool;
|
||||||
|
using android::hardware::joinRpcThreadpool;
|
||||||
|
|
||||||
|
using android::hardware::biometrics::fingerprint::V2_3::IBiometricsFingerprint;
|
||||||
|
using android::hardware::biometrics::fingerprint::V2_3::implementation::BiometricsFingerprint;
|
||||||
|
|
||||||
|
using android::OK;
|
||||||
|
using android::sp;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
android::sp<IBiometricsFingerprint> bio = BiometricsFingerprint::getInstance();
|
||||||
|
|
||||||
|
configureRpcThreadpool(1, true);
|
||||||
|
|
||||||
|
if (bio == nullptr || bio->registerAsService() != OK) {
|
||||||
|
LOG(ERROR) << "Could not register service for Fingerprint HAL";
|
||||||
|
goto shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Fingerprint HAL service is Ready.";
|
||||||
|
joinRpcThreadpool();
|
||||||
|
|
||||||
|
shutdown:
|
||||||
|
// In normal operation, we don't expect the thread pool to shutdown
|
||||||
|
LOG(ERROR) << "Fingerprint HAL failed to join thread pool.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
46
universal7885-common/hidl/keymaster/Android.mk
Normal file
46
universal7885-common/hidl/keymaster/Android.mk
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 The LineageOS Project
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
ifeq ($(TARGET_KEYMASTER_VARIANT),samsung)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
service.cpp
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
|
android.hardware.keymaster@4.0 \
|
||||||
|
libbase \
|
||||||
|
libcutils \
|
||||||
|
libhardware \
|
||||||
|
libhidlbase \
|
||||||
|
libkeymaster4 \
|
||||||
|
liblog \
|
||||||
|
libskeymaster4device \
|
||||||
|
libutils
|
||||||
|
|
||||||
|
LOCAL_MODULE := android.hardware.keymaster@4.0-service.samsung
|
||||||
|
LOCAL_INIT_RC := android.hardware.keymaster@4.0-service.samsung.rc
|
||||||
|
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_OWNER := samsung
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
endif # TARGET_KEYMASTER_VARIANT
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
service vendor.keymaster-4-0 /vendor/bin/hw/android.hardware.keymaster@4.0-service.samsung
|
||||||
|
class early_hal
|
||||||
|
user system
|
||||||
|
group system drmrpc
|
||||||
|
|
||||||
|
on post-fs-data
|
||||||
|
mkdir /mnt/vendor/efs/DAK 0775 system system
|
||||||
|
restorecon -R /mnt/vendor/efs/DAK
|
||||||
58
universal7885-common/hidl/keymaster/service.cpp
Normal file
58
universal7885-common/hidl/keymaster/service.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "android.hardware.keymaster@4.0-service.samsung"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
|
||||||
|
#include <hidl/HidlTransportSupport.h>
|
||||||
|
|
||||||
|
#include <AndroidKeymaster4Device.h>
|
||||||
|
|
||||||
|
using android::hardware::configureRpcThreadpool;
|
||||||
|
using android::hardware::joinRpcThreadpool;
|
||||||
|
|
||||||
|
using android::hardware::keymaster::V4_0::IKeymasterDevice;
|
||||||
|
using android::hardware::keymaster::V4_0::SecurityLevel;
|
||||||
|
|
||||||
|
using android::OK;
|
||||||
|
using android::status_t;
|
||||||
|
|
||||||
|
namespace skeymaster {
|
||||||
|
IKeymasterDevice* CreateSKeymasterDevice(SecurityLevel securityLevel);
|
||||||
|
} // namespace skeymaster
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
IKeymasterDevice* keymaster =
|
||||||
|
skeymaster::CreateSKeymasterDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
|
||||||
|
|
||||||
|
configureRpcThreadpool(1, true);
|
||||||
|
|
||||||
|
status_t status = keymaster->registerAsService();
|
||||||
|
|
||||||
|
if (status != OK) {
|
||||||
|
LOG(ERROR) << "Could not register service for Keymaster HAL";
|
||||||
|
goto shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Keymaster HAL service is Ready.";
|
||||||
|
joinRpcThreadpool();
|
||||||
|
|
||||||
|
shutdown:
|
||||||
|
// In normal operation, we don't expect the thread pool to shutdown
|
||||||
|
LOG(ERROR) << "Keymaster HAL failed to join thread pool.";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
20
universal7885-common/hidl/sensors/Android.bp
Normal file
20
universal7885-common/hidl/sensors/Android.bp
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
cc_library_shared {
|
||||||
|
name: "android.hardware.sensors@1.0-impl.samsung",
|
||||||
|
defaults: ["hidl_defaults"],
|
||||||
|
proprietary: true,
|
||||||
|
relative_install_path: "hw",
|
||||||
|
srcs: ["Sensors.cpp"],
|
||||||
|
shared_libs: [
|
||||||
|
"liblog",
|
||||||
|
"libcutils",
|
||||||
|
"libhardware",
|
||||||
|
"libbase",
|
||||||
|
"libutils",
|
||||||
|
"libhidlbase",
|
||||||
|
"android.hardware.sensors@1.0",
|
||||||
|
],
|
||||||
|
static_libs: [
|
||||||
|
"android.hardware.sensors@1.0-convert",
|
||||||
|
"multihal",
|
||||||
|
],
|
||||||
|
}
|
||||||
385
universal7885-common/hidl/sensors/Sensors.cpp
Normal file
385
universal7885-common/hidl/sensors/Sensors.cpp
Normal file
|
|
@ -0,0 +1,385 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define VERBOSE
|
||||||
|
|
||||||
|
#include "Sensors.h"
|
||||||
|
#include <sensors/convert.h>
|
||||||
|
#include "multihal.h"
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace sensors {
|
||||||
|
namespace V1_0 {
|
||||||
|
namespace implementation {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a multi-hal configuration file exists in the proper location,
|
||||||
|
* return true indicating we need to use multi-hal functionality.
|
||||||
|
*/
|
||||||
|
static bool UseMultiHal() {
|
||||||
|
const std::string& name = MULTI_HAL_CONFIG_FILE_PATH;
|
||||||
|
struct stat buffer;
|
||||||
|
return (stat (name.c_str(), &buffer) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result ResultFromStatus(status_t err) {
|
||||||
|
switch (err) {
|
||||||
|
case OK:
|
||||||
|
return Result::OK;
|
||||||
|
case PERMISSION_DENIED:
|
||||||
|
return Result::PERMISSION_DENIED;
|
||||||
|
case NO_MEMORY:
|
||||||
|
return Result::NO_MEMORY;
|
||||||
|
case BAD_VALUE:
|
||||||
|
return Result::BAD_VALUE;
|
||||||
|
default:
|
||||||
|
return Result::INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sensors::Sensors()
|
||||||
|
: mInitCheck(NO_INIT),
|
||||||
|
mSensorModule(nullptr),
|
||||||
|
mSensorDevice(nullptr) {
|
||||||
|
status_t err = OK;
|
||||||
|
if (UseMultiHal()) {
|
||||||
|
mSensorModule = ::get_multi_hal_module_info();
|
||||||
|
} else {
|
||||||
|
err = hw_get_module(
|
||||||
|
SENSORS_HARDWARE_MODULE_ID,
|
||||||
|
(hw_module_t const **)&mSensorModule);
|
||||||
|
}
|
||||||
|
if (mSensorModule == NULL) {
|
||||||
|
err = UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
LOG(ERROR) << "Couldn't load "
|
||||||
|
<< SENSORS_HARDWARE_MODULE_ID
|
||||||
|
<< " module ("
|
||||||
|
<< strerror(-err)
|
||||||
|
<< ")";
|
||||||
|
|
||||||
|
mInitCheck = err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
LOG(ERROR) << "Couldn't open device for module "
|
||||||
|
<< SENSORS_HARDWARE_MODULE_ID
|
||||||
|
<< " ("
|
||||||
|
<< strerror(-err)
|
||||||
|
<< ")";
|
||||||
|
|
||||||
|
mInitCheck = err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require all the old HAL APIs to be present except for injection, which
|
||||||
|
// is considered optional.
|
||||||
|
CHECK_GE(getHalDeviceVersion(), SENSORS_DEVICE_API_VERSION_1_3);
|
||||||
|
|
||||||
|
if (getHalDeviceVersion() == SENSORS_DEVICE_API_VERSION_1_4) {
|
||||||
|
if (mSensorDevice->inject_sensor_data == nullptr) {
|
||||||
|
LOG(ERROR) << "HAL specifies version 1.4, but does not implement inject_sensor_data()";
|
||||||
|
}
|
||||||
|
if (mSensorModule->set_operation_mode == nullptr) {
|
||||||
|
LOG(ERROR) << "HAL specifies version 1.4, but does not implement set_operation_mode()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get us all sensors */
|
||||||
|
setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(5555));
|
||||||
|
|
||||||
|
mInitCheck = OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Sensors::initCheck() const {
|
||||||
|
return mInitCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
|
||||||
|
sensor_t const *list;
|
||||||
|
size_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
|
||||||
|
|
||||||
|
hidl_vec<SensorInfo> out;
|
||||||
|
out.resize(count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
const sensor_t *src = &list[i];
|
||||||
|
SensorInfo *dst = &out[i];
|
||||||
|
|
||||||
|
convertFromSensor(*src, dst);
|
||||||
|
|
||||||
|
if (dst->requiredPermission == "com.samsung.permission.SSENSOR") {
|
||||||
|
dst->requiredPermission = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst->typeAsString == "com.samsung.sensor.physical_proximity") {
|
||||||
|
LOG(INFO) << "Fixing com.samsung.sensor.physical_proximity";
|
||||||
|
dst->type = SensorType::PROXIMITY;
|
||||||
|
dst->typeAsString = SENSOR_STRING_TYPE_PROXIMITY;
|
||||||
|
dst->maxRange = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
LOG(INFO) << "SENSOR NAME: " << dst->name;
|
||||||
|
LOG(INFO) << " VENDOR: " << dst->name;
|
||||||
|
LOG(INFO) << " TYPE: " << (uint32_t)dst->type;
|
||||||
|
LOG(INFO) << " TYPE_AS_STRING: " << dst->typeAsString;
|
||||||
|
LOG(INFO) << " FLAGS: " << std::hex << dst->flags;
|
||||||
|
LOG(INFO) << "";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
_hidl_cb(out);
|
||||||
|
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Sensors::getHalDeviceVersion() const {
|
||||||
|
if (!mSensorDevice) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mSensorDevice->common.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::setOperationMode(OperationMode mode) {
|
||||||
|
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4
|
||||||
|
|| mSensorModule->set_operation_mode == nullptr) {
|
||||||
|
return Result::INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
return ResultFromStatus(mSensorModule->set_operation_mode((uint32_t)mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::activate(
|
||||||
|
int32_t sensor_handle, bool enabled) {
|
||||||
|
return ResultFromStatus(
|
||||||
|
mSensorDevice->activate(
|
||||||
|
reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
|
||||||
|
sensor_handle,
|
||||||
|
enabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> Sensors::poll(int32_t maxCount, poll_cb _hidl_cb) {
|
||||||
|
|
||||||
|
hidl_vec<Event> out;
|
||||||
|
hidl_vec<SensorInfo> dynamicSensorsAdded;
|
||||||
|
|
||||||
|
std::unique_ptr<sensors_event_t[]> data;
|
||||||
|
int err = android::NO_ERROR;
|
||||||
|
|
||||||
|
{ // scope of reentry lock
|
||||||
|
|
||||||
|
// This enforces a single client, meaning that a maximum of one client can call poll().
|
||||||
|
// If this function is re-entred, it means that we are stuck in a state that may prevent
|
||||||
|
// the system from proceeding normally.
|
||||||
|
//
|
||||||
|
// Exit and let the system restart the sensor-hal-implementation hidl service.
|
||||||
|
//
|
||||||
|
// This function must not call _hidl_cb(...) or return until there is no risk of blocking.
|
||||||
|
std::unique_lock<std::mutex> lock(mPollLock, std::try_to_lock);
|
||||||
|
if(!lock.owns_lock()){
|
||||||
|
// cannot get the lock, hidl service will go into deadlock if it is not restarted.
|
||||||
|
// This is guaranteed to not trigger in passthrough mode.
|
||||||
|
LOG(ERROR) <<
|
||||||
|
"ISensors::poll() re-entry. I do not know what to do except killing myself.";
|
||||||
|
::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxCount <= 0) {
|
||||||
|
err = android::BAD_VALUE;
|
||||||
|
} else {
|
||||||
|
int bufferSize = maxCount <= kPollMaxBufferSize ? maxCount : kPollMaxBufferSize;
|
||||||
|
data.reset(new sensors_event_t[bufferSize]);
|
||||||
|
err = mSensorDevice->poll(
|
||||||
|
reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
|
||||||
|
data.get(), bufferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
_hidl_cb(ResultFromStatus(err), out, dynamicSensorsAdded);
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t count = (size_t)err;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
if (data[i].type != SENSOR_TYPE_DYNAMIC_SENSOR_META) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dynamic_sensor_meta_event_t *dyn = &data[i].dynamic_sensor_meta;
|
||||||
|
|
||||||
|
if (!dyn->connected) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(dyn->sensor != nullptr);
|
||||||
|
CHECK_EQ(dyn->sensor->handle, dyn->handle);
|
||||||
|
|
||||||
|
SensorInfo info;
|
||||||
|
convertFromSensor(*dyn->sensor, &info);
|
||||||
|
|
||||||
|
size_t numDynamicSensors = dynamicSensorsAdded.size();
|
||||||
|
dynamicSensorsAdded.resize(numDynamicSensors + 1);
|
||||||
|
dynamicSensorsAdded[numDynamicSensors] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.resize(count);
|
||||||
|
convertFromSensorEvents(err, data.get(), &out);
|
||||||
|
|
||||||
|
_hidl_cb(Result::OK, out, dynamicSensorsAdded);
|
||||||
|
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::batch(
|
||||||
|
int32_t sensor_handle,
|
||||||
|
int64_t sampling_period_ns,
|
||||||
|
int64_t max_report_latency_ns) {
|
||||||
|
return ResultFromStatus(
|
||||||
|
mSensorDevice->batch(
|
||||||
|
mSensorDevice,
|
||||||
|
sensor_handle,
|
||||||
|
0, /*flags*/
|
||||||
|
sampling_period_ns,
|
||||||
|
max_report_latency_ns));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::flush(int32_t sensor_handle) {
|
||||||
|
return ResultFromStatus(mSensorDevice->flush(mSensorDevice, sensor_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::injectSensorData(const Event& event) {
|
||||||
|
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4
|
||||||
|
|| mSensorDevice->inject_sensor_data == nullptr) {
|
||||||
|
return Result::INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors_event_t out;
|
||||||
|
convertToSensorEvent(event, &out);
|
||||||
|
|
||||||
|
return ResultFromStatus(
|
||||||
|
mSensorDevice->inject_sensor_data(mSensorDevice, &out));
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> Sensors::registerDirectChannel(
|
||||||
|
const SharedMemInfo& mem, registerDirectChannel_cb _hidl_cb) {
|
||||||
|
if (mSensorDevice->register_direct_channel == nullptr
|
||||||
|
|| mSensorDevice->config_direct_report == nullptr) {
|
||||||
|
// HAL does not support
|
||||||
|
_hidl_cb(Result::INVALID_OPERATION, -1);
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors_direct_mem_t m;
|
||||||
|
if (!convertFromSharedMemInfo(mem, &m)) {
|
||||||
|
_hidl_cb(Result::BAD_VALUE, -1);
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = mSensorDevice->register_direct_channel(mSensorDevice, &m, -1);
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
_hidl_cb(ResultFromStatus(err), -1);
|
||||||
|
} else {
|
||||||
|
int32_t channelHandle = static_cast<int32_t>(err);
|
||||||
|
_hidl_cb(Result::OK, channelHandle);
|
||||||
|
}
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<Result> Sensors::unregisterDirectChannel(int32_t channelHandle) {
|
||||||
|
if (mSensorDevice->register_direct_channel == nullptr
|
||||||
|
|| mSensorDevice->config_direct_report == nullptr) {
|
||||||
|
// HAL does not support
|
||||||
|
return Result::INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle);
|
||||||
|
|
||||||
|
return Result::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Return<void> Sensors::configDirectReport(
|
||||||
|
int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
|
||||||
|
configDirectReport_cb _hidl_cb) {
|
||||||
|
if (mSensorDevice->register_direct_channel == nullptr
|
||||||
|
|| mSensorDevice->config_direct_report == nullptr) {
|
||||||
|
// HAL does not support
|
||||||
|
_hidl_cb(Result::INVALID_OPERATION, -1);
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors_direct_cfg_t cfg = {
|
||||||
|
.rate_level = convertFromRateLevel(rate)
|
||||||
|
};
|
||||||
|
if (cfg.rate_level < 0) {
|
||||||
|
_hidl_cb(Result::BAD_VALUE, -1);
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = mSensorDevice->config_direct_report(mSensorDevice,
|
||||||
|
sensorHandle, channelHandle, &cfg);
|
||||||
|
|
||||||
|
if (rate == RateLevel::STOP) {
|
||||||
|
_hidl_cb(ResultFromStatus(err), -1);
|
||||||
|
} else {
|
||||||
|
_hidl_cb(err > 0 ? Result::OK : ResultFromStatus(err), err);
|
||||||
|
}
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Sensors::convertFromSensorEvents(
|
||||||
|
size_t count,
|
||||||
|
const sensors_event_t *srcArray,
|
||||||
|
hidl_vec<Event> *dstVec) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
const sensors_event_t &src = srcArray[i];
|
||||||
|
Event *dst = &(*dstVec)[i];
|
||||||
|
|
||||||
|
convertFromSensorEvent(src, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISensors *HIDL_FETCH_ISensors(const char * /* hal */) {
|
||||||
|
Sensors *sensors = new Sensors;
|
||||||
|
if (sensors->initCheck() != OK) {
|
||||||
|
delete sensors;
|
||||||
|
sensors = nullptr;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V1_0
|
||||||
|
} // namespace sensors
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
88
universal7885-common/hidl/sensors/Sensors.h
Normal file
88
universal7885-common/hidl/sensors/Sensors.h
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HARDWARE_INTERFACES_SENSORS_V1_0_SAMSUNG_SENSORS_H_
|
||||||
|
|
||||||
|
#define HARDWARE_INTERFACES_SENSORS_V1_0_SAMSUNG_SENSORS_H_
|
||||||
|
|
||||||
|
#include <android-base/macros.h>
|
||||||
|
#include <android/hardware/sensors/1.0/ISensors.h>
|
||||||
|
#include <hardware/sensors.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace hardware {
|
||||||
|
namespace sensors {
|
||||||
|
namespace V1_0 {
|
||||||
|
namespace implementation {
|
||||||
|
|
||||||
|
|
||||||
|
struct Sensors : public ::android::hardware::sensors::V1_0::ISensors {
|
||||||
|
Sensors();
|
||||||
|
|
||||||
|
status_t initCheck() const;
|
||||||
|
|
||||||
|
Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
|
||||||
|
|
||||||
|
Return<Result> setOperationMode(OperationMode mode) override;
|
||||||
|
|
||||||
|
Return<Result> activate(
|
||||||
|
int32_t sensor_handle, bool enabled) override;
|
||||||
|
|
||||||
|
Return<void> poll(int32_t maxCount, poll_cb _hidl_cb) override;
|
||||||
|
|
||||||
|
Return<Result> batch(
|
||||||
|
int32_t sensor_handle,
|
||||||
|
int64_t sampling_period_ns,
|
||||||
|
int64_t max_report_latency_ns) override;
|
||||||
|
|
||||||
|
Return<Result> flush(int32_t sensor_handle) override;
|
||||||
|
|
||||||
|
Return<Result> injectSensorData(const Event& event) override;
|
||||||
|
|
||||||
|
Return<void> registerDirectChannel(
|
||||||
|
const SharedMemInfo& mem, registerDirectChannel_cb _hidl_cb) override;
|
||||||
|
|
||||||
|
Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
|
||||||
|
|
||||||
|
Return<void> configDirectReport(
|
||||||
|
int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
|
||||||
|
configDirectReport_cb _hidl_cb) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int32_t kPollMaxBufferSize = 128;
|
||||||
|
status_t mInitCheck;
|
||||||
|
sensors_module_t *mSensorModule;
|
||||||
|
sensors_poll_device_1_t *mSensorDevice;
|
||||||
|
std::mutex mPollLock;
|
||||||
|
|
||||||
|
int getHalDeviceVersion() const;
|
||||||
|
|
||||||
|
static void convertFromSensorEvents(
|
||||||
|
size_t count, const sensors_event_t *src, hidl_vec<Event> *dst);
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Sensors);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" ISensors *HIDL_FETCH_ISensors(const char *name);
|
||||||
|
|
||||||
|
} // namespace implementation
|
||||||
|
} // namespace V1_0
|
||||||
|
} // namespace sensors
|
||||||
|
} // namespace hardware
|
||||||
|
} // namespace android
|
||||||
|
|
||||||
|
#endif // HARDWARE_INTERFACES_SENSORS_V1_0_SAMSUNG_SENSORS_H_
|
||||||
24
universal7885-common/secril_config_svc/Android.bp
Normal file
24
universal7885-common/secril_config_svc/Android.bp
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 The LineageOS Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "secril_config_svc",
|
||||||
|
vendor: true,
|
||||||
|
srcs: ["secril_config_svc.cpp"],
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
],
|
||||||
|
}
|
||||||
70
universal7885-common/secril_config_svc/secril_config_svc.cpp
Normal file
70
universal7885-common/secril_config_svc/secril_config_svc.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021, The LineageOS Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "secril_config_svc"
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <android-base/strings.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define EFS_OLD "/efs/"
|
||||||
|
#define EFS_NEW "/mnt/vendor/efs/"
|
||||||
|
#define FACTORY_PROP "factory.prop"
|
||||||
|
#define TELEPHONY_PROP "telephony.prop"
|
||||||
|
|
||||||
|
void LoadProperties(std::string data) {
|
||||||
|
for (std::string line : android::base::Split(data, "\n")) {
|
||||||
|
if (line == "\0") break;
|
||||||
|
|
||||||
|
std::vector<std::string> parts = android::base::Split(line, "=");
|
||||||
|
if (parts.size() == 2) {
|
||||||
|
LOG(INFO) << "Setting property: " << line;
|
||||||
|
android::base::SetProperty(parts.at(0), parts.at(1));
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Invalid data: " << line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
std::string prop = FACTORY_PROP;
|
||||||
|
|
||||||
|
if (argc > 1 && std::string(argv[1]) == "NetworkConfig")
|
||||||
|
prop = TELEPHONY_PROP;
|
||||||
|
|
||||||
|
std::ifstream in(EFS_NEW + prop);
|
||||||
|
if (in.good()) {
|
||||||
|
in.close();
|
||||||
|
prop = EFS_NEW + prop;
|
||||||
|
} else {
|
||||||
|
prop = EFS_OLD + prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Loading properties from " << prop;
|
||||||
|
|
||||||
|
std::string content;
|
||||||
|
if (android::base::ReadFileToString(prop, &content)) {
|
||||||
|
LoadProperties(content.c_str());
|
||||||
|
} else if (prop == FACTORY_PROP) {
|
||||||
|
LOG(WARNING) << "Could not read " << prop << ", setting defaults!";
|
||||||
|
LoadProperties("ro.vendor.multisim.simslotcount=1");
|
||||||
|
} else {
|
||||||
|
LOG(WARNING) << "Could not read " << prop << "!";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue