universal7885: Remove useless stuffs

Also reorganize
This commit is contained in:
roynatech2544 2022-04-20 08:03:45 +09:00
commit 134d87b132
111 changed files with 0 additions and 72 deletions

View file

@ -0,0 +1,23 @@
//
// Copyright (C) 2021 Soo Hwan Na "Royna"
//
// 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: "eklogger",
srcs: [
"Logger.cpp",
],
init_rc: ["eklogger.rc"],
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2021 Soo Hwan Na "Royna"
*
* 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 <thread>
#define KMSG_PATH "/proc/kmsg"
#define WRITE_KMSG "/data/debug/kmsg.txt"
#include <fstream>
#include <iostream>
void copy_kmsg() {
std::ifstream readfile(KMSG_PATH);
std::ofstream writefile(WRITE_KMSG);
writefile << readfile.rdbuf();
}
void copy_logcat() {
system("/system/bin/logcat -b all -f /data/debug/logcat.txt");
}
int main() {
std::thread kmsg(copy_kmsg);
std::thread logcat(copy_logcat);
kmsg.join();
logcat.join();
return 0;
}

View file

@ -0,0 +1,14 @@
service eureka_debugger /system/bin/eklogger
user root
group system
oneshot
disabled
on post-fs-data
mkdir /data/debug 0755 root system encryption=None
rm /data/debug/logcat.txt
rm /data/debug/kmsg.txt
start eureka_debugger
on property:sys.boot_completed=1
stop eureka_debugger

View file

@ -0,0 +1,3 @@
hidl_package_root{
name: "vendor.eureka",
}

View file

@ -0,0 +1,12 @@
hidl_interface {
name: "vendor.eureka.hardware.fmradio@1.0",
root: "vendor.eureka",
srcs: [
"types.hal",
"IFMRadio.hal",
],
interfaces: [
"android.hidl.base@1.0",
],
gen_java: true,
}

View file

@ -0,0 +1,20 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.0;
interface IFMRadio {
setManualFreq(float freq);
adjustFreqByStep(Direction dir);
};

View file

@ -0,0 +1,20 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.0;
enum Direction : int32_t {
UP,
DOWN,
};

View file

@ -0,0 +1,13 @@
hidl_interface {
name: "vendor.eureka.hardware.fmradio@1.1",
root: "vendor.eureka",
srcs: [
"types.hal",
"IFMRadio.hal",
],
interfaces: [
"android.hidl.base@1.0",
"vendor.eureka.hardware.fmradio@1.0",
],
gen_java: true,
}

View file

@ -0,0 +1,22 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.1;
import @1.0::IFMRadio;
interface IFMRadio extends @1.0::IFMRadio {
getFreqFromSysfs() generates (int32_t freq);
isAvailable() generates (Status status);
};

View file

@ -0,0 +1,20 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.1;
enum Status : int32_t {
YES,
NO,
};

View file

@ -0,0 +1,14 @@
hidl_interface {
name: "vendor.eureka.hardware.fmradio@1.2",
root: "vendor.eureka",
srcs: [
"types.hal",
"IFMRadio.hal",
],
interfaces: [
"android.hidl.base@1.0",
"vendor.eureka.hardware.fmradio@1.1",
"vendor.eureka.hardware.fmradio@1.0",
],
gen_java: true,
}

View file

@ -0,0 +1,22 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.2;
import @1.1::IFMRadio;
interface IFMRadio extends @1.1::IFMRadio {
setChannelSpacing(Space space);
getChannelSpacing() generates (Space space);
};

View file

@ -0,0 +1,20 @@
// FIXME: your file license if you have one
cc_binary {
name: "vendor.eureka.hardware.fmradio@1.2-service",
proprietary: true,
srcs: [
"FMRadio.cpp",
"service.cpp",
],
shared_libs: [
"libhidlbase",
"libutils",
"liblog",
"vendor.eureka.hardware.fmradio@1.0",
"vendor.eureka.hardware.fmradio@1.1",
"vendor.eureka.hardware.fmradio@1.2",
],
init_rc: [ "vendor.eureka.hardware.fmradio@1.2-service.rc" ],
vintf_fragments: [ "vendor.eureka.hardware.fmradio@1.2.xml" ],
}

View file

@ -0,0 +1,84 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "FMRadio.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
static int mChannelSpacing = 3;
namespace vendor::eureka::hardware::fmradio::V1_2 {
Return<void> FMRadio::setManualFreq(float freq) {
std::ofstream file;
file.open("/sys/devices/virtual/s610_radio/s610_radio/radio_freq_ctrl");
file << freq * 1000;
file.close();
return Void();
}
Return<void> FMRadio::adjustFreqByStep(fmradio::V1_0::Direction dir) {
std::ofstream file;
std::string value = "";
if (dir == V1_0::Direction::UP) {
value = "1 " + std::to_string(mChannelSpacing * 10);
} else if (dir == V1_0::Direction::DOWN) {
value = "0 " + std::to_string(mChannelSpacing * 10);
}
file.open("/sys/devices/virtual/s610_radio/s610_radio/radio_freq_seek");
file << value;
file.close();
return Void();
}
Return<V1_1::Status> FMRadio::isAvailable() {
struct stat info;
if (stat("/sys/devices/virtual/s610_radio/s610_radio/", &info) != 0) {
return V1_1::Status::NO;
} else {
return V1_1::Status::YES;
}
}
Return<void> FMRadio::setChannelSpacing(V1_2::Space space) {
mChannelSpacing = (int)space;
return Void();
}
Return<int32_t> FMRadio::getFreqFromSysfs() {
std::ifstream file;
std::string value;
file.open("/sys/devices/virtual/s610_radio/s610_radio/radio_freq_ctrl");
std::getline(file, value);
file.close();
return std::stoi(value);
}
Return<V1_2::Space> FMRadio::getChannelSpacing() {
switch (mChannelSpacing) {
case 1:
return V1_2::Space::CHANNEL_SPACING_10HZ;
case 2:
return V1_2::Space::CHANNEL_SPACING_20HZ;
case 3:
return V1_2::Space::CHANNEL_SPACING_30HZ;
case 4:
return V1_2::Space::CHANNEL_SPACING_40HZ;
case 5:
return V1_2::Space::CHANNEL_SPACING_50HZ;
default:
return V1_2::Space::CHANNEL_SPACING_30HZ;
}
}
IFMRadio *FMRadio::getInstance(void) { return new FMRadio(); }
} // namespace vendor::eureka::hardware::fmradio::V1_2

View file

@ -0,0 +1,44 @@
// Copyright (C) 2021 Eureka Team
//
// 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/fmradio/1.2/IFMRadio.h>
namespace vendor::eureka::hardware::fmradio::V1_2 {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct FMRadio : public IFMRadio {
// Methods from ::vendor::eureka::hardware::fmradio::V1_0::IFMRadio follow.
Return<void> setManualFreq(float freq);
Return<void> adjustFreqByStep(V1_0::Direction dir);
// Methods from ::vendor::eureka::hardware::fmradio::V1_1::IFMRadio follow.
Return<V1_1::Status> isAvailable();
Return<int32_t> getFreqFromSysfs();
// Methods from ::vendor::eureka::hardware::fmradio::V1_2::IFMRadio follow.
Return<void> setChannelSpacing(V1_2::Space space);
Return<V1_2::Space> getChannelSpacing();
// Methods from ::android::hidl::base::V1_0::IBase follow.
static IFMRadio *getInstance(void);
};
} // namespace vendor::eureka::hardware::fmradio::V1_2

View file

@ -0,0 +1,47 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "vendor.eureka.hardware.fmradio@1.2-service"
#include <vendor/eureka/hardware/fmradio/1.2/IFMRadio.h>
#include <hidl/LegacySupport.h>
#include "FMRadio.h"
using android::sp;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using vendor::eureka::hardware::fmradio::V1_2::FMRadio;
using vendor::eureka::hardware::fmradio::V1_2::IFMRadio;
int main() {
int ret;
android::sp<IFMRadio> mFMService = FMRadio::getInstance();
configureRpcThreadpool(1, true /*callerWillJoin*/);
if (mFMService != nullptr) {
ret = mFMService->registerAsService();
if (ret != 0) {
ALOGE("Can't register instance of FMRadio HAL, nullptr");
} else {
ALOGI("registered FMRadio HAL");
}
} else {
ALOGE("Can't create instance of FMRadio HAL, nullptr");
}
joinRpcThreadpool();
return -1; // should never get here
}

View file

@ -0,0 +1,7 @@
service vendor.fm-hal /vendor/bin/vendor.eureka.hardware.fmradio@1.2-service
interface vendor.eureka.hardware.fmradio@1.0::IFMRadio default
interface vendor.eureka.hardware.fmradio@1.1::IFMRadio default
interface vendor.eureka.hardware.fmradio@1.2::IFMRadio default
class hal
user root
group root

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="hidl">
<name>vendor.eureka.hardware.fmradio</name>
<transport>hwbinder</transport>
<version>1.2</version>
<interface>
<name>IFMRadio</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View file

@ -0,0 +1,23 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.fmradio@1.2;
enum Space : int32_t {
CHANNEL_SPACING_10HZ = 1,
CHANNEL_SPACING_20HZ,
CHANNEL_SPACING_30HZ,
CHANNEL_SPACING_40HZ,
CHANNEL_SPACING_50HZ = 5,
};

View file

@ -0,0 +1,13 @@
hidl_interface {
name: "vendor.eureka.hardware.parts@1.0",
root: "vendor.eureka",
srcs: [
"types.hal",
"IBatteryStats.hal",
"IFlashBrightness.hal",
"IDisplayConfigs.hal",
"ISwapOnData.hal",
],
interfaces: [ "android.hidl.base@1.0" ],
gen_java: false,
}

View file

@ -0,0 +1,20 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.parts@1.0;
interface IBatteryStats {
getBatteryStats(SysfsType stats) generates (int32_t result);
setBatteryWritable(SysfsType stats, Number value);
};

View file

@ -0,0 +1,19 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.parts@1.0;
interface IDisplayConfigs {
writeDisplay(Number enable, Display type);
};

View file

@ -0,0 +1,21 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.parts@1.0;
interface IFlashBrightness {
setFlashlightWritable(Value value);
setFlashlightEnable(Number enable);
readFlashlightstats(Device device) generates (int32_t value);
};

View file

@ -0,0 +1,21 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.parts@1.0;
interface ISwapOnData {
setSwapSize(int32_t size /* Size in megabytes */);
setSwapOn();
setSwapOff();
};

View file

@ -0,0 +1,21 @@
// FIXME: your file license if you have one
cc_binary {
name: "vendor.eureka.hardware.parts@1.0-service",
proprietary: true,
srcs: [
"Battery.cpp",
"FlashLight.cpp",
"Display.cpp",
"Swap.cpp",
"service.cpp",
],
shared_libs: [
"libhidlbase",
"libutils",
"liblog",
"vendor.eureka.hardware.parts@1.0",
],
init_rc: [ "vendor.eureka.hardware.parts@1.0-service.rc" ],
vintf_fragments: [ "vendor.eureka.hardware.parts@1.0.xml" ],
}

View file

@ -0,0 +1,111 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "Battery.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <unistd.h>
namespace vendor::eureka::hardware::parts::V1_0 {
// Methods from ::android::hardware::battery::V1_0::IBattery follow.
Return<int32_t> BatteryStats::getBatteryStats(parts::V1_0::SysfsType stats) {
std::ifstream file;
std::string filename;
switch (stats) {
case SysfsType::CAPACITY_MAX:
filename = "/sys/devices/platform/battery/power_supply/battery/charge_full";
break;
case SysfsType::TEMP:
filename = "/sys/devices/platform/battery/power_supply/battery/batt_temp";
break;
case SysfsType::CAPACITY_CURRENT:
filename = "/sys/devices/platform/battery/power_supply/battery/capacity";
break;
case SysfsType::CURRENT:
filename = "/sys/devices/platform/battery/power_supply/battery/current_now";
break;
case SysfsType::FASTCHARGE:
filename = "/sys/class/sec/switch/afc_disable";
break;
case SysfsType::CHARGE:
filename =
"/sys/devices/platform/battery/power_supply/battery/batt_slate_mode";
break;
default:
filename = "";
break;
}
std::string value;
int32_t intvalue;
file.open(filename);
if (file.is_open()) {
getline(file, value);
file.close();
std::stringstream val(value);
val >> intvalue;
return intvalue;
}
return -1;
}
Return<void> BatteryStats::setBatteryWritable(parts::V1_0::SysfsType stats,
parts::V1_0::Number value) {
std::ofstream file;
std::string filename;
bool FastCharge = false;
switch (stats) {
case SysfsType::CAPACITY_MAX:
filename = "/sys/devices/platform/battery/power_supply/battery/charge_full";
break;
case SysfsType::TEMP:
filename = "/sys/devices/platform/battery/power_supply/battery/batt_temp";
break;
case SysfsType::CAPACITY_CURRENT:
filename = "/sys/devices/platform/battery/power_supply/battery/capacity";
break;
case SysfsType::CURRENT:
filename = "/sys/devices/platform/battery/power_supply/battery/current_now";
break;
case SysfsType::FASTCHARGE:
filename = "/sys/class/sec/switch/afc_disable";
FastCharge = true;
break;
case SysfsType::CHARGE:
filename =
"/sys/devices/platform/battery/power_supply/battery/batt_slate_mode";
break;
default:
filename = "";
break;
}
if (FastCharge)
seteuid(ANDROID_SYSTEM_UID);
file.open(filename);
int write;
if (value == Number::ENABLE) {
write = 1;
} else {
write = 0;
}
file << write;
file.close();
if (FastCharge)
seteuid(ANDROID_ROOT_UID);
return Void();
}
IBatteryStats *BatteryStats::getInstance(void) { return new BatteryStats(); }
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,42 @@
// Copyright (C) 2021 Eureka Team
//
// 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/parts/1.0/IBatteryStats.h>
#define ANDROID_SYSTEM_UID 1000
#define ANDROID_ROOT_UID 0
namespace vendor::eureka::hardware::parts::V1_0 {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct BatteryStats : public IBatteryStats {
// Methods from ::vendor::eureka::hardware::parts::V1_0::IBatteryStats follow.
Return<int32_t> getBatteryStats(SysfsType stats) override;
Return<void> setBatteryWritable(SysfsType stats, Number value) override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
static IBatteryStats *getInstance(void);
};
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,45 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "Display.h"
#include <fstream>
#include <iostream>
#include <sstream>
namespace vendor::eureka::hardware::parts::V1_0 {
Return<void> DisplayConfigs::writeDisplay(parts::V1_0::Number enable,
parts::V1_0::Display type) {
std::ofstream file;
std::string writevalue;
if (type == Display::DOUBLE_TAP) {
writevalue = "aot_enable";
} else if (type == Display::GLOVE_MODE) {
writevalue = "glove_mode";
}
writevalue += ",";
if (enable == Number::ENABLE) {
writevalue += "1";
} else {
writevalue += "0";
}
file.open("/sys/class/sec/tsp/cmd");
file << writevalue;
file.close();
return Void();
}
IDisplayConfigs *DisplayConfigs::getInstance(void) {
return new DisplayConfigs();
}
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,38 @@
// Copyright (C) 2021 Eureka Team
//
// 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/parts/1.0/IDisplayConfigs.h>
namespace vendor::eureka::hardware::parts::V1_0 {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct DisplayConfigs : public IDisplayConfigs {
// Methods from ::vendor::eureka::hardware::parts::V1_0::IDisplayConfigs
// follow.
Return<void> writeDisplay(Number enable, Display type);
// Methods from ::android::hidl::base::V1_0::IBase follow.
static IDisplayConfigs *getInstance(void);
};
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,76 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "FlashLight.h"
#include <fstream>
#include <iostream>
#include <sstream>
namespace vendor::eureka::hardware::parts::V1_0 {
// Methods from ::android::hardware::parts::V1_0::IFlashLight follow.
Return<void> FlashBrightness::setFlashlightEnable(parts::V1_0::Number enable) {
std::ofstream file;
std::string writevalue;
switch (enable) {
case Number::ENABLE:
writevalue = "1";
break;
case Number::DISABLE:
writevalue = "0";
break;
default:
writevalue = "";
break;
}
file.open("/sys/class/camera/flash/torch_brightness_lvl_enable");
file << writevalue;
file.close();
return Void();
}
Return<void> FlashBrightness::setFlashlightWritable(parts::V1_0::Value value) {
std::ofstream file;
std::string writevalue = std::to_string((int)value);
file.open("/sys/class/camera/flash/torch_brightness_lvl");
file << writevalue;
file.close();
return Void();
}
Return<int32_t>
FlashBrightness::readFlashlightstats(parts::V1_0::Device device) {
std::ifstream file;
std::string value;
int32_t intvalue;
file.open("/sys/class/camera/flash/torch_brightness_lvl");
if (file.is_open()) {
getline(file, value);
file.close();
std::stringstream val(value);
val >> intvalue;
if (device == Device::A10) {
return intvalue;
} else if (device == Device::NOTA10) {
return intvalue / 21;
}
// Never Here
return -1;
}
return -1;
}
IFlashBrightness *FlashBrightness::getInstance(void) {
return new FlashBrightness();
}
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,40 @@
// Copyright (C) 2021 Eureka Team
//
// 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/parts/1.0/IFlashBrightness.h>
namespace vendor::eureka::hardware::parts::V1_0 {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct FlashBrightness : public IFlashBrightness {
// Methods from ::vendor::eureka::hardware::parts::V1_0::IFlashBrightness
// follow.
Return<void> setFlashlightEnable(Number enable);
Return<void> setFlashlightWritable(Value value);
Return<int32_t> readFlashlightstats(Device device);
// Methods from ::android::hidl::base::V1_0::IBase follow.
static IFlashBrightness *getInstance(void);
};
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,52 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "Swap.h"
#include <fstream>
#include <iostream>
static int mSwapSize = 100;
#define SWAP_PATH "/data/swap/swapfile"
using namespace std;
namespace vendor::eureka::hardware::parts::V1_0 {
Return<void> SwapOnData::setSwapSize(int32_t size) {
mSwapSize = size;
return Void();
}
Return<void> SwapOnData::setSwapOn(){
string cmd = string("dd if=/dev/zero of=") + string(SWAP_PATH) + string(" bs=") + std::to_string(mSwapSize)
+ "M count=10";
system(cmd.c_str());
cmd = string("mkswap ") + string(SWAP_PATH);
system(cmd.c_str());
cmd = string("swapon -p 99 ") + string(SWAP_PATH);
system(cmd.c_str());
return Void();
}
Return<void> SwapOnData::setSwapOff(){
std::string cmd = string("swapoff ") + string(SWAP_PATH);
system(cmd.c_str());
cmd = string("rm ") + string(SWAP_PATH);
system(cmd.c_str());
return Void();
}
ISwapOnData *SwapOnData::getInstance(void) {
return new SwapOnData();
}
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,40 @@
// Copyright (C) 2021 Eureka Team
//
// 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/parts/1.0/ISwapOnData.h>
namespace vendor::eureka::hardware::parts::V1_0 {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct SwapOnData : public ISwapOnData {
// Methods from ::vendor::eureka::hardware::parts::V1_0::ISwapOnData
// follow.
Return<void> setSwapSize(int32_t size);
Return<void> setSwapOn();
Return<void> setSwapOff();
// Methods from ::android::hidl::base::V2_0::IBase follow.
static ISwapOnData *getInstance(void);
};
} // namespace vendor::eureka::hardware::parts::V1_0

View file

@ -0,0 +1,92 @@
// Copyright (C) 2021 Eureka Team
//
// 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 "vendor.eureka.hardware.parts@1.0-service"
#include <hidl/LegacySupport.h>
#include <vendor/eureka/hardware/parts/1.0/IBatteryStats.h>
#include <vendor/eureka/hardware/parts/1.0/IDisplayConfigs.h>
#include <vendor/eureka/hardware/parts/1.0/IFlashBrightness.h>
#include <vendor/eureka/hardware/parts/1.0/ISwapOnData.h>
#include "Battery.h"
#include "Display.h"
#include "FlashLight.h"
#include "Swap.h"
using android::sp;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using vendor::eureka::hardware::parts::V1_0::BatteryStats;
using vendor::eureka::hardware::parts::V1_0::DisplayConfigs;
using vendor::eureka::hardware::parts::V1_0::FlashBrightness;
using vendor::eureka::hardware::parts::V1_0::SwapOnData;
using vendor::eureka::hardware::parts::V1_0::IBatteryStats;
using vendor::eureka::hardware::parts::V1_0::IDisplayConfigs;
using vendor::eureka::hardware::parts::V1_0::IFlashBrightness;
using vendor::eureka::hardware::parts::V1_0::ISwapOnData;
int main() {
int ret;
android::sp<IBatteryStats> mBatteryService = BatteryStats::getInstance();
android::sp<IFlashBrightness> mFlashLightService =
FlashBrightness::getInstance();
android::sp<IDisplayConfigs> mDisplayService = DisplayConfigs::getInstance();
android::sp<ISwapOnData> mSwapService = SwapOnData::getInstance();
configureRpcThreadpool(4, true /*callerWillJoin*/);
if (mBatteryService != nullptr) {
ret = mBatteryService->registerAsService();
if (ret != 0) {
ALOGE("Can't register instance of Battery HAL, nullptr");
} else {
ALOGI("registered Battery HAL");
}
} else {
ALOGE("Can't create instance of Battery HAL, nullptr");
}
if (mFlashLightService != nullptr) {
ret = mFlashLightService->registerAsService();
if (ret != 0) {
ALOGE("Can't register instance of FlashLight HAL, nullptr");
} else {
ALOGI("registered FlashLight HAL");
}
} else {
ALOGE("Can't create instance of FlashLight HAL, nullptr");
}
if (mDisplayService != nullptr) {
ret = mDisplayService->registerAsService();
if (ret != 0) {
ALOGE("Can't register instance of Display HAL, nullptr");
} else {
ALOGI("registered Display HAL");
}
} else {
ALOGE("Can't create instance of Display HAL, nullptr");
}
if (mSwapService != nullptr) {
ret = mSwapService->registerAsService();
if (ret != 0) {
ALOGE("Can't register instance of Swap HAL, nullptr");
} else {
ALOGI("registered Swap HAL");
}
} else {
ALOGE("Can't create instance of Swap HAL, nullptr");
}
joinRpcThreadpool();
return -1; // should never get here
}

View file

@ -0,0 +1,11 @@
service vendor.parts-hal /vendor/bin/vendor.eureka.hardware.parts@1.0-service
interface vendor.eureka.hardware.parts@1.0::IBatteryStats default
interface vendor.eureka.hardware.parts@1.0::IDisplayConfigs default
interface vendor.eureka.hardware.parts@1.0::IFlashBrightness default
interface vendor.eureka.hardware.parts@1.0::ISwapOnData default
class hal
user root
group root
on post-fs-data
mkdir /data/swap 0755 root root encryption=None

View file

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="hidl">
<name>vendor.eureka.hardware.parts</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IBatteryStats</name>
<instance>default</instance>
</interface>
<interface>
<name>IFlashBrightness</name>
<instance>default</instance>
</interface>
<interface>
<name>IDisplayConfigs</name>
<instance>default</instance>
</interface>
<interface>
<name>ISwapOnData</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View file

@ -0,0 +1,52 @@
// Copyright (C) 2021 Eureka Team
//
// 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.
package vendor.eureka.hardware.parts@1.0;
enum SysfsType : int32_t {
CAPACITY_MAX,
TEMP,
CAPACITY_CURRENT,
CURRENT,
FASTCHARGE,
CHARGE,
};
enum Display : int32_t {
DOUBLE_TAP,
GLOVE_MODE,
};
enum Number : int32_t {
ENABLE = 1,
DISABLE = 0,
};
enum Device : int32_t {
A10,
NOTA10,
};
enum Value : int32_t {
ONEUI = 1,
TWOUI,
THREEUI,
FOURUI,
FIVEUI,
SIXUI,
SEVENUI,
EIGHTUI,
NINEUI,
TENUI = 10,
};

View file

@ -0,0 +1,45 @@
//
// 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: "android.hardware.camera.provider@2.5-service.exynos7885",
defaults: [
"hidl_defaults",
],
compile_multilib: "32",
proprietary: true,
relative_install_path: "hw",
srcs: [
"SamsungCameraProvider.cpp",
"service.cpp"
],
init_rc: ["android.hardware.camera.provider@2.5-service.exynos7885.rc"],
shared_libs: [
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.4-legacy",
"android.hardware.camera.provider@2.5",
"android.hardware.camera.provider@2.5-legacy",
"libbinder",
"libcamera_metadata",
"libcutils",
"libhardware",
"libhidlbase",
"liblog",
"libutils",
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
],
}

View file

@ -0,0 +1,91 @@
/*
* 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 "SamsungCameraProvider@2.5"
#include "SamsungCameraProvider.h"
#include <algorithm>
using ::android::NO_ERROR;
using ::android::OK;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Void;
const int kMaxCameraIdLen = 16;
SamsungCameraProvider::SamsungCameraProvider()
: LegacyCameraProviderImpl_2_5() {
mExtraIDs.push_back(50);
mDisabledIDs.push_back(2);
if (!mInitFailed) {
for (int i : mExtraIDs) {
struct camera_info info;
auto rc = mModule->getCameraInfo(i, &info);
if (rc != NO_ERROR) {
continue;
}
if (checkCameraVersion(i, info) != OK) {
ALOGE("Camera version check failed!");
mModule.clear();
mInitFailed = true;
return;
}
#ifdef SAMSUNG_CAMERA_DEBUG
ALOGI("ID=%d is at index %d", i, mNumberOfLegacyCameras);
#endif
char cameraId[kMaxCameraIdLen];
snprintf(cameraId, sizeof(cameraId), "%d", i);
std::string cameraIdStr(cameraId);
mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
addDeviceNames(i);
mNumberOfLegacyCameras++;
}
}
}
Return<void> SamsungCameraProvider::getCameraIdList(
ICameraProvider::getCameraIdList_cb _hidl_cb) {
std::vector<hidl_string> deviceNameList;
for (auto const &deviceNamePair : mCameraDeviceNames) {
int id = std::stoi(deviceNamePair.first);
if (id >= mNumberOfLegacyCameras ||
std::find(mDisabledIDs.begin(), mDisabledIDs.end(), id) !=
mDisabledIDs.end()) {
// External camera devices must be reported through the device status
// change callback, not in this list. Linux4: Also skip disabled camera
// IDs.
continue;
}
if (mCameraStatusMap[deviceNamePair.first] ==
CAMERA_DEVICE_STATUS_PRESENT) {
deviceNameList.push_back(deviceNamePair.second);
}
}
hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
_hidl_cb(::android::hardware::camera::common::V1_0::Status::OK,
hidlDeviceNameList);
return Void();
}
SamsungCameraProvider::~SamsungCameraProvider() {}

View file

@ -0,0 +1,40 @@
/*
* 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.
*/
#ifndef SAMSUNG_CAMERA_PROVIDER_H
#include "LegacyCameraProviderImpl_2_5.h"
#define SAMSUNG_CAMERA_DEBUG
using ::android::hardware::Return;
using ::android::hardware::camera::provider::V2_5::ICameraProvider;
using ::android::hardware::camera::provider::V2_5::implementation::
LegacyCameraProviderImpl_2_5;
class SamsungCameraProvider : public LegacyCameraProviderImpl_2_5 {
public:
SamsungCameraProvider();
~SamsungCameraProvider();
Return<void> getCameraIdList(ICameraProvider::getCameraIdList_cb _hidl_cb);
private:
std::vector<int> mExtraIDs;
std::vector<int> mDisabledIDs;
};
#endif // SAMSUNG_CAMERA_PROVIDER_H

View file

@ -0,0 +1,9 @@
service vendor.camera-provider-2-5 /vendor/bin/hw/android.hardware.camera.provider@2.5-service.exynos7885
interface android.hardware.camera.provider@2.5::ICameraProvider legacy/0
interface android.hardware.camera.provider@2.4::ICameraProvider legacy/0
class hal
user cameraserver
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
task_profiles CameraServiceCapacity MaxPerformance

View file

@ -0,0 +1,49 @@
/*
* Copyright 2019 The Android Open Source Project
* Copyright 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 "android.hardware.camera.provider@2.5-service.samsung"
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
#include <binder/ProcessState.h>
#include <hidl/HidlLazyUtils.h>
#include <hidl/HidlTransportSupport.h>
#include "CameraProvider_2_5.h"
#include "SamsungCameraProvider.h"
using android::status_t;
using android::hardware::camera::provider::V2_5::ICameraProvider;
int main() {
using namespace android::hardware::camera::provider::V2_5::implementation;
ALOGI("CameraProvider@2.5 legacy service is starting.");
::android::hardware::configureRpcThreadpool(/*threads*/ HWBINDER_THREAD_COUNT,
/*willJoin*/ true);
::android::sp<ICameraProvider> provider =
new CameraProvider<SamsungCameraProvider>();
status_t status = provider->registerAsService("legacy/0");
LOG_ALWAYS_FATAL_IF(status != android::OK,
"Error while registering provider service: %d", status);
::android::hardware::joinRpcThreadpool();
return 0;
}

View file

@ -0,0 +1,24 @@
cc_binary {
name: "android.hardware.biometrics.fingerprint@2.3-service.samsung",
defaults: ["hidl_defaults"],
proprietary: true,
init_rc: ["android.hardware.biometrics.fingerprint@2.3-service.samsung.rc"],
vintf_fragments: ["android.hardware.biometrics.fingerprint@2.3-service.samsung.xml"],
relative_install_path: "hw",
cflags: ["-DHAS_FINGERPRINT_GESTURES"],
srcs: [
"BiometricsFingerprint.cpp",
"service.cpp",
],
shared_libs: [
"liblog",
"libcutils",
"libhardware",
"libbase",
"libutils",
"libhidlbase",
"android.hardware.biometrics.fingerprint@2.1",
"android.hardware.biometrics.fingerprint@2.2",
"android.hardware.biometrics.fingerprint@2.3",
],
}

View file

@ -0,0 +1,539 @@
/*
* 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 "BiometricsFingerprint.h"
#include <hardware/fingerprint.h>
#include <hardware/hardware.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

View file

@ -0,0 +1,138 @@
/*
* 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 <android/hardware/biometrics/fingerprint/2.1/types.h>
#include <android/hardware/biometrics/fingerprint/2.3/IBiometricsFingerprint.h>
#include <hardware/fingerprint.h>
#include <hardware/hardware.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.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_1::
FingerprintAcquiredInfo;
using ::android::hardware::biometrics::fingerprint::V2_1::FingerprintError;
using ::android::hardware::biometrics::fingerprint::V2_1::
IBiometricsFingerprintClientCallback;
using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
using ::android::hardware::biometrics::fingerprint::V2_3::
IBiometricsFingerprint;
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

View 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

View file

@ -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

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<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>

View file

@ -0,0 +1,53 @@
/*
* 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;
}

View file

@ -0,0 +1,42 @@
#
# 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 := \
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)

View file

@ -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

View 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;
}

View 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,
}

View file

@ -0,0 +1,196 @@
/*
* 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

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "samsung_lights.h"
#include <aidl/android/hardware/light/BnLights.h>
#include <unordered_map>
using ::aidl::android::hardware::light::HwLight;
using ::aidl::android::hardware::light::HwLightState;
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

View file

@ -0,0 +1,5 @@
service vendor.light-default /vendor/bin/hw/android.hardware.light-service.samsung
class hal
user system
group system
shutdown critical

View file

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.light</name>
<fqname>ILights/default</fqname>
</hal>
</manifest>

View 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

View file

@ -0,0 +1,28 @@
/*
* 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-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.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
}

View 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"
],
}

View file

@ -0,0 +1,265 @@
/*
* 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 <memory>
#include <poll.h>
#include <sys/eventfd.h>
#include <time.h>
#include <unistd.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#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();
}
}

View file

@ -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_

View 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

View 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

View file

@ -0,0 +1,90 @@
/*
* 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

View file

@ -0,0 +1,56 @@
/*
* 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

View file

@ -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

View file

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="aidl" override="true">
<name>android.hardware.power</name>
<fqname>IPower/default</fqname>
</hal>
</manifest>

View file

@ -0,0 +1,77 @@
/*
* 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;
}

View 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",
],
}

View file

@ -0,0 +1,71 @@
/*
* 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 << "!";
}
}

View 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",
],
}

View file

@ -0,0 +1,366 @@
/*
* 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 "multihal.h"
#include <sensors/convert.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

View file

@ -0,0 +1,85 @@
/*
* 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_

View file

@ -0,0 +1,31 @@
//
// Copyright (C) 2017-2018,2020 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: "android.hardware.usb@1.0-service.a10",
relative_install_path: "hw",
init_rc: ["android.hardware.usb@1.0-service.a10.rc"],
vintf_fragments: ["android.hardware.usb@1.0-service.a10.xml"],
srcs: ["service.cpp", "Usb.cpp"],
shared_libs: [
"libbase",
"libcutils",
"libhidlbase",
"libutils",
"libhardware",
"android.hardware.usb@1.0",
],
proprietary: true,
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (C) 2017-2018 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 <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <android-base/logging.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include "Usb.h"
namespace android {
namespace hardware {
namespace usb {
namespace V1_0 {
namespace implementation {
Return<void> Usb::switchRole(const hidl_string &portName __unused,
const PortRole &newRole __unused) {
LOG(ERROR) << __func__ << ": Not supported";
return Void();
}
Return<void> Usb::queryPortStatus() {
hidl_vec<PortStatus> currentPortStatus;
currentPortStatus.resize(1);
currentPortStatus[0].portName = "otg_default";
currentPortStatus[0].currentDataRole = PortDataRole::DEVICE;
currentPortStatus[0].currentPowerRole = PortPowerRole::SINK;
currentPortStatus[0].currentMode = PortMode::UFP;
currentPortStatus[0].canChangeMode = false;
currentPortStatus[0].canChangeDataRole = false;
currentPortStatus[0].canChangePowerRole = false;
currentPortStatus[0].supportedModes = PortMode::UFP;
pthread_mutex_lock(&mLock);
if (mCallback != NULL) {
Return<void> ret =
mCallback->notifyPortStatusChange(currentPortStatus, Status::SUCCESS);
if (!ret.isOk()) {
LOG(ERROR) << "queryPortStatus error " << ret.description();
}
} else {
LOG(INFO) << "Notifying userspace skipped. Callback is NULL";
}
pthread_mutex_unlock(&mLock);
return Void();
}
Return<void> Usb::setCallback(const sp<IUsbCallback> &callback) {
pthread_mutex_lock(&mLock);
mCallback = callback;
LOG(INFO) << "registering callback";
pthread_mutex_unlock(&mLock);
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace usb
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017-2018 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_USB_V1_0_USB_H
#define ANDROID_HARDWARE_USB_V1_0_USB_H
#include <android/hardware/usb/1.0/IUsb.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <utils/Log.h>
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "android.hardware.usb@1.0-service-a10"
#define UEVENT_MSG_LEN 2048
namespace android {
namespace hardware {
namespace usb {
namespace V1_0 {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::usb::V1_0::IUsb;
using ::android::hardware::usb::V1_0::IUsbCallback;
using ::android::hardware::usb::V1_0::PortRole;
using ::android::hidl::base::V1_0::IBase;
struct Usb : public IUsb {
Return<void> switchRole(const hidl_string &portName,
const PortRole &role) override;
Return<void> setCallback(const sp<IUsbCallback> &callback) override;
Return<void> queryPortStatus() override;
sp<IUsbCallback> mCallback;
pthread_mutex_t mLock = PTHREAD_MUTEX_INITIALIZER;
};
} // namespace implementation
} // namespace V1_0
} // namespace usb
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_USB_V1_0_USB_H

View file

@ -0,0 +1,5 @@
service vendor.usb-hal-1-0 /vendor/bin/hw/android.hardware.usb@1.0-service.a10
interface android.hardware.usb@1.0::IUsb default
class hal
user system
group system

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="hidl" override="true">
<name>android.hardware.usb</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2017-2018 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 "Usb.h"
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
using android::sp;
// libhwbinder:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::usb::V1_0::IUsb;
using android::hardware::usb::V1_0::implementation::Usb;
int main() {
android::sp<IUsb> service = new Usb();
configureRpcThreadpool(1, true /*callerWillJoin*/);
android::status_t status = service->registerAsService();
if (status != android::OK) {
LOG(ERROR) << "Cannot register USB HAL service";
return 1;
}
LOG(INFO) << "USB HAL Ready.";
joinRpcThreadpool();
// Under normal cases, execution will not reach this line.
LOG(ERROR) << "USB HAL failed to join thread pool.";
return 1;
}

View file

@ -0,0 +1,41 @@
//
// Copyright (C) 2017 The Android Open Source Project
// Copyright (C) 2022 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: "android.hardware.usb@1.3-service.samsung",
relative_install_path: "hw",
init_rc: ["android.hardware.usb@1.3-service.samsung.rc"],
vintf_fragments: [
"android.hardware.usb@1.3-service.samsung.xml",
],
srcs: ["service.cpp", "Usb.cpp"],
cflags: ["-Wall", "-Werror"],
shared_libs: [
"libbase",
"libbinder",
"libhidlbase",
"liblog",
"libutils",
"libhardware",
"android.hardware.usb@1.0",
"android.hardware.usb@1.1",
"android.hardware.usb@1.2",
"android.hardware.usb@1.3",
"libcutils",
"libbinder_ndk",
],
proprietary: true,
}

View file

@ -0,0 +1,845 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2022 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.usb@1.3-service.samsung"
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <assert.h>
#include <chrono>
#include <dirent.h>
#include <pthread.h>
#include <regex>
#include <stdio.h>
#include <sys/types.h>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include <cutils/uevent.h>
#include <sys/epoll.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
#include "Usb.h"
using android::base::GetProperty;
namespace android {
namespace hardware {
namespace usb {
namespace V1_3 {
namespace implementation {
Return<bool> Usb::enableUsbDataSignal(bool enable) {
bool result = true;
ALOGI("Userspace turn %s USB data signaling", enable ? "on" : "off");
if (enable) {
if (!WriteStringToFile("1", USB_DATA_PATH)) {
ALOGE("Not able to turn on usb connection notification");
result = false;
}
} else {
if (!WriteStringToFile("0", USB_DATA_PATH)) {
ALOGE("Not able to turn off usb connection notification");
result = false;
}
}
return result;
}
// Set by the signal handler to destroy the thread
volatile bool destroyThread;
bool moistureDetectionEnabled = true;
constexpr char kContaminantDetectionPath[] =
"/sys/devices/virtual/sec/ccic/water";
constexpr char kTypecPath[] = "/sys/class/typec";
constexpr char kDisableContaminantDetection[] = "vendor.usb.contaminantdisable";
int32_t readFile(const std::string &filename, std::string *contents) {
FILE *fp;
ssize_t read = 0;
char *line = NULL;
size_t len = 0;
fp = fopen(filename.c_str(), "r");
if (fp != NULL) {
if ((read = getline(&line, &len, fp)) != -1) {
char *pos;
if ((pos = strchr(line, '\n')) != NULL)
*pos = '\0';
*contents = line;
}
free(line);
fclose(fp);
return 0;
} else {
ALOGE("fopen failed");
}
return -1;
}
int32_t writeFile(const std::string &filename, const std::string &contents) {
FILE *fp;
std::string written;
fp = fopen(filename.c_str(), "w");
if (fp != NULL) {
// FAILURE RETRY
int ret = fputs(contents.c_str(), fp);
fclose(fp);
if ((ret != EOF) && !readFile(filename, &written) && written == contents)
return 0;
}
return -1;
}
Status
queryMoistureDetectionStatus(hidl_vec<PortStatus> *currentPortStatus_1_2) {
std::string enabled, status, path, DetectedPath;
if (currentPortStatus_1_2 == NULL || currentPortStatus_1_2->size() == 0) {
ALOGE("currentPortStatus_1_2 is not available");
return Status::ERROR;
}
(*currentPortStatus_1_2)[0].supportedContaminantProtectionModes = 0;
(*currentPortStatus_1_2)[0].supportedContaminantProtectionModes |=
V1_2::ContaminantProtectionMode::FORCE_SINK;
(*currentPortStatus_1_2)[0].contaminantProtectionStatus =
V1_2::ContaminantProtectionStatus::NONE;
(*currentPortStatus_1_2)[0].contaminantDetectionStatus =
V1_2::ContaminantDetectionStatus::DISABLED;
(*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceDetection = true;
(*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceProtection =
false;
if (moistureDetectionEnabled) {
if (readFile(kContaminantDetectionPath, &status)) {
ALOGE("Failed to open moisture_detected");
return Status::ERROR;
}
if (status == "1") {
(*currentPortStatus_1_2)[0].contaminantDetectionStatus =
V1_2::ContaminantDetectionStatus::DETECTED;
(*currentPortStatus_1_2)[0].contaminantProtectionStatus =
V1_2::ContaminantProtectionStatus::FORCE_SINK;
} else
(*currentPortStatus_1_2)[0].contaminantDetectionStatus =
V1_2::ContaminantDetectionStatus::NOT_DETECTED;
}
ALOGI("ContaminantDetectionStatus:%d ContaminantProtectionStatus:%d",
(*currentPortStatus_1_2)[0].contaminantDetectionStatus,
(*currentPortStatus_1_2)[0].contaminantProtectionStatus);
return Status::SUCCESS;
}
std::string appendRoleNodeHelper(const std::string &portName,
PortRoleType type) {
std::string node("/sys/class/typec/" + portName);
switch (type) {
case PortRoleType::DATA_ROLE:
return node + "/data_role";
case PortRoleType::POWER_ROLE:
return node + "/power_role";
case PortRoleType::MODE:
return node + "/port_type";
default:
return "";
}
}
std::string convertRoletoString(PortRole role) {
if (role.type == PortRoleType::POWER_ROLE) {
if (role.role == static_cast<uint32_t>(PortPowerRole::SOURCE))
return "source";
else if (role.role == static_cast<uint32_t>(PortPowerRole::SINK))
return "sink";
} else if (role.type == PortRoleType::DATA_ROLE) {
if (role.role == static_cast<uint32_t>(PortDataRole::HOST))
return "host";
if (role.role == static_cast<uint32_t>(PortDataRole::DEVICE))
return "device";
} else if (role.type == PortRoleType::MODE) {
if (role.role == static_cast<uint32_t>(PortMode_1_1::UFP))
return "sink";
if (role.role == static_cast<uint32_t>(PortMode_1_1::DFP))
return "source";
}
return "none";
}
void extractRole(std::string *roleName) {
std::size_t first, last;
first = roleName->find("[");
last = roleName->find("]");
if (first != std::string::npos && last != std::string::npos) {
*roleName = roleName->substr(first + 1, last - first - 1);
}
}
void switchToDrp(const std::string &portName) {
std::string filename =
appendRoleNodeHelper(std::string(portName.c_str()), PortRoleType::MODE);
FILE *fp;
if (filename != "") {
fp = fopen(filename.c_str(), "w");
if (fp != NULL) {
int ret = fputs("dual", fp);
fclose(fp);
if (ret == EOF)
ALOGE("Fatal: Error while switching back to drp");
} else {
ALOGE("Fatal: Cannot open file to switch back to drp");
}
} else {
ALOGE("Fatal: invalid node type");
}
}
bool switchMode(const hidl_string &portName, const PortRole &newRole,
struct Usb *usb) {
std::string filename =
appendRoleNodeHelper(std::string(portName.c_str()), newRole.type);
std::string written;
FILE *fp;
bool roleSwitch = false;
if (filename == "") {
ALOGE("Fatal: invalid node type");
return false;
}
fp = fopen(filename.c_str(), "w");
if (fp != NULL) {
// Hold the lock here to prevent loosing connected signals
// as once the file is written the partner added signal
// can arrive anytime.
pthread_mutex_lock(&usb->mPartnerLock);
usb->mPartnerUp = false;
int ret = fputs(convertRoletoString(newRole).c_str(), fp);
fclose(fp);
if (ret != EOF) {
struct timespec to;
struct timespec now;
wait_again:
clock_gettime(CLOCK_MONOTONIC, &now);
to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT;
to.tv_nsec = now.tv_nsec;
int err =
pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to);
// There are no uevent signals which implies role swap timed out.
if (err == ETIMEDOUT) {
ALOGI("uevents wait timedout");
// Validity check.
} else if (!usb->mPartnerUp) {
goto wait_again;
// Role switch succeeded since usb->mPartnerUp is true.
} else {
roleSwitch = true;
}
} else {
ALOGI("Role switch failed while wrting to file");
}
pthread_mutex_unlock(&usb->mPartnerLock);
}
if (!roleSwitch)
switchToDrp(std::string(portName.c_str()));
return roleSwitch;
}
Usb::Usb()
: mLock(PTHREAD_MUTEX_INITIALIZER),
mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
mPartnerLock(PTHREAD_MUTEX_INITIALIZER), mPartnerUp(false) {
pthread_condattr_t attr;
if (pthread_condattr_init(&attr)) {
ALOGE("pthread_condattr_init failed: %s", strerror(errno));
abort();
}
if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
ALOGE("pthread_condattr_setclock failed: %s", strerror(errno));
abort();
}
if (pthread_cond_init(&mPartnerCV, &attr)) {
ALOGE("pthread_cond_init failed: %s", strerror(errno));
abort();
}
if (pthread_condattr_destroy(&attr)) {
ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
abort();
}
}
Return<void> Usb::switchRole(const hidl_string &portName,
const V1_0::PortRole &newRole) {
std::string filename =
appendRoleNodeHelper(std::string(portName.c_str()), newRole.type);
std::string written;
FILE *fp;
bool roleSwitch = false;
if (filename == "") {
ALOGE("Fatal: invalid node type");
return Void();
}
pthread_mutex_lock(&mRoleSwitchLock);
ALOGI("filename write: %s role:%s", filename.c_str(),
convertRoletoString(newRole).c_str());
if (newRole.type == PortRoleType::MODE) {
roleSwitch = switchMode(portName, newRole, this);
} else {
fp = fopen(filename.c_str(), "w");
if (fp != NULL) {
int ret = fputs(convertRoletoString(newRole).c_str(), fp);
fclose(fp);
if ((ret != EOF) && !readFile(filename, &written)) {
extractRole(&written);
ALOGI("written: %s", written.c_str());
if (written == convertRoletoString(newRole)) {
roleSwitch = true;
} else {
ALOGE("Role switch failed");
}
} else {
ALOGE("failed to update the new role");
}
} else {
ALOGE("fopen failed");
}
}
pthread_mutex_lock(&mLock);
if (mCallback_1_0 != NULL) {
Return<void> ret = mCallback_1_0->notifyRoleSwitchStatus(
portName, newRole, roleSwitch ? Status::SUCCESS : Status::ERROR);
if (!ret.isOk())
ALOGE("RoleSwitchStatus error %s", ret.description().c_str());
} else {
ALOGE("Not notifying the userspace. Callback is not set");
}
pthread_mutex_unlock(&mLock);
pthread_mutex_unlock(&mRoleSwitchLock);
return Void();
}
Status getAccessoryConnected(const std::string &portName,
std::string *accessory) {
std::string filename =
"/sys/class/typec/" + portName + "-partner/accessory_mode";
if (readFile(filename, accessory)) {
ALOGE("getAccessoryConnected: Failed to open filesystem node: %s",
filename.c_str());
return Status::ERROR;
}
return Status::SUCCESS;
}
Status getCurrentRoleHelper(const std::string &portName, bool connected,
PortRoleType type, uint32_t *currentRole) {
std::string filename;
std::string roleName;
std::string accessory;
// Mode
if (type == PortRoleType::POWER_ROLE) {
filename = "/sys/class/typec/" + portName + "/power_role";
*currentRole = static_cast<uint32_t>(PortPowerRole::NONE);
} else if (type == PortRoleType::DATA_ROLE) {
filename = "/sys/class/typec/" + portName + "/data_role";
*currentRole = static_cast<uint32_t>(PortDataRole::NONE);
} else if (type == PortRoleType::MODE) {
filename = "/sys/class/typec/" + portName + "/data_role";
*currentRole = static_cast<uint32_t>(PortMode_1_1::NONE);
} else {
return Status::ERROR;
}
if (!connected)
return Status::SUCCESS;
if (type == PortRoleType::MODE) {
if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) {
return Status::ERROR;
}
if (accessory == "analog_audio") {
*currentRole = static_cast<uint32_t>(PortMode_1_1::AUDIO_ACCESSORY);
return Status::SUCCESS;
} else if (accessory == "debug") {
*currentRole = static_cast<uint32_t>(PortMode_1_1::DEBUG_ACCESSORY);
return Status::SUCCESS;
}
}
if (readFile(filename, &roleName)) {
ALOGE("getCurrentRole: Failed to open filesystem node: %s",
filename.c_str());
return Status::ERROR;
}
extractRole(&roleName);
if (roleName == "source") {
*currentRole = static_cast<uint32_t>(PortPowerRole::SOURCE);
} else if (roleName == "sink") {
*currentRole = static_cast<uint32_t>(PortPowerRole::SINK);
} else if (roleName == "host") {
if (type == PortRoleType::DATA_ROLE)
*currentRole = static_cast<uint32_t>(PortDataRole::HOST);
else
*currentRole = static_cast<uint32_t>(PortMode_1_1::DFP);
} else if (roleName == "device") {
if (type == PortRoleType::DATA_ROLE)
*currentRole = static_cast<uint32_t>(PortDataRole::DEVICE);
else
*currentRole = static_cast<uint32_t>(PortMode_1_1::UFP);
} else if (roleName != "none") {
/* case for none has already been addressed.
* so we check if the role isn't none.
*/
return Status::UNRECOGNIZED_ROLE;
}
return Status::SUCCESS;
}
Status getTypeCPortNamesHelper(std::unordered_map<std::string, bool> *names) {
DIR *dp;
dp = opendir(kTypecPath);
if (dp != NULL) {
struct dirent *ep;
while ((ep = readdir(dp))) {
if (ep->d_type == DT_LNK) {
if (std::string::npos == std::string(ep->d_name).find("-partner")) {
std::unordered_map<std::string, bool>::const_iterator portName =
names->find(ep->d_name);
if (portName == names->end()) {
names->insert({ep->d_name, false});
}
} else {
(*names)[std::strtok(ep->d_name, "-")] = true;
}
}
}
closedir(dp);
return Status::SUCCESS;
}
ALOGE("Failed to open /sys/class/typec");
return Status::ERROR;
}
bool canSwitchRoleHelper(const std::string &portName, PortRoleType /*type*/) {
std::string filename =
"/sys/class/typec/" + portName + "-partner/supports_usb_power_delivery";
std::string supportsPD;
if (!readFile(filename, &supportsPD)) {
if (supportsPD == "yes") {
return true;
}
}
return false;
}
/*
* Reuse the same method for both V1_0 and V1_1 callback objects.
* The caller of this method would reconstruct the V1_0::PortStatus
* object if required.
*/
Status getPortStatusHelper(hidl_vec<PortStatus> *currentPortStatus_1_2,
HALVersion version) {
std::unordered_map<std::string, bool> names;
Status result = getTypeCPortNamesHelper(&names);
int i = -1;
if (result == Status::SUCCESS) {
currentPortStatus_1_2->resize(names.size());
for (std::pair<std::string, bool> port : names) {
i++;
ALOGI("%s", port.first.c_str());
(*currentPortStatus_1_2)[i].status_1_1.status.portName = port.first;
uint32_t currentRole;
if (getCurrentRoleHelper(port.first, port.second,
PortRoleType::POWER_ROLE,
&currentRole) == Status::SUCCESS) {
(*currentPortStatus_1_2)[i].status_1_1.status.currentPowerRole =
static_cast<PortPowerRole>(currentRole);
} else {
ALOGE("Error while retrieving portNames");
goto done;
}
if (getCurrentRoleHelper(port.first, port.second, PortRoleType::DATA_ROLE,
&currentRole) == Status::SUCCESS) {
(*currentPortStatus_1_2)[i].status_1_1.status.currentDataRole =
static_cast<PortDataRole>(currentRole);
} else {
ALOGE("Error while retrieving current port role");
goto done;
}
if (getCurrentRoleHelper(port.first, port.second, PortRoleType::MODE,
&currentRole) == Status::SUCCESS) {
(*currentPortStatus_1_2)[i].status_1_1.currentMode =
static_cast<PortMode_1_1>(currentRole);
(*currentPortStatus_1_2)[i].status_1_1.status.currentMode =
static_cast<V1_0::PortMode>(currentRole);
} else {
ALOGE("Error while retrieving current data role");
goto done;
}
(*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode = true;
(*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole =
port.second ? canSwitchRoleHelper(port.first, PortRoleType::DATA_ROLE)
: false;
(*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole =
port.second
? canSwitchRoleHelper(port.first, PortRoleType::POWER_ROLE)
: false;
if (version == HALVersion::V1_0) {
ALOGI("HAL version V1_0");
(*currentPortStatus_1_2)[i].status_1_1.status.supportedModes =
V1_0::PortMode::DRP;
} else {
if (version == HALVersion::V1_1)
ALOGI("HAL version V1_1");
else
ALOGI("HAL version V1_2");
(*currentPortStatus_1_2)[i].status_1_1.supportedModes =
0 | PortMode_1_1::DRP;
(*currentPortStatus_1_2)[i].status_1_1.status.supportedModes =
V1_0::PortMode::NONE;
(*currentPortStatus_1_2)[i].status_1_1.status.currentMode =
V1_0::PortMode::NONE;
}
ALOGI("%d:%s connected:%d canChangeMode:%d canChagedata:%d "
"canChangePower:%d "
"supportedModes:%d",
i, port.first.c_str(), port.second,
(*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode,
(*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole,
(*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole,
(*currentPortStatus_1_2)[i].status_1_1.supportedModes);
}
return Status::SUCCESS;
}
done:
return Status::ERROR;
}
void queryVersionHelper(android::hardware::usb::V1_3::implementation::Usb *usb,
hidl_vec<PortStatus> *currentPortStatus_1_2) {
hidl_vec<V1_1::PortStatus_1_1> currentPortStatus_1_1;
hidl_vec<V1_0::PortStatus> currentPortStatus;
Status status;
sp<V1_1::IUsbCallback> callback_V1_1 =
V1_1::IUsbCallback::castFrom(usb->mCallback_1_0);
sp<IUsbCallback> callback_V1_2 = IUsbCallback::castFrom(usb->mCallback_1_0);
pthread_mutex_lock(&usb->mLock);
if (usb->mCallback_1_0 != NULL) {
if (callback_V1_2 != NULL) {
status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_2);
if (status == Status::SUCCESS)
queryMoistureDetectionStatus(currentPortStatus_1_2);
} else if (callback_V1_1 != NULL) {
status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_1);
currentPortStatus_1_1.resize(currentPortStatus_1_2->size());
for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
currentPortStatus_1_1[i] = (*currentPortStatus_1_2)[i].status_1_1;
} else {
status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_0);
currentPortStatus.resize(currentPortStatus_1_2->size());
for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
currentPortStatus[i] = (*currentPortStatus_1_2)[i].status_1_1.status;
}
Return<void> ret;
if (callback_V1_2 != NULL)
ret = callback_V1_2->notifyPortStatusChange_1_2(*currentPortStatus_1_2,
status);
else if (callback_V1_1 != NULL)
ret = callback_V1_1->notifyPortStatusChange_1_1(currentPortStatus_1_1,
status);
else
ret =
usb->mCallback_1_0->notifyPortStatusChange(currentPortStatus, status);
if (!ret.isOk())
ALOGE("queryPortStatus_1_2 error %s", ret.description().c_str());
} else {
ALOGI("Notifying userspace skipped. Callback is NULL");
}
pthread_mutex_unlock(&usb->mLock);
}
Return<void> Usb::queryPortStatus() {
hidl_vec<PortStatus> currentPortStatus_1_2;
queryVersionHelper(this, &currentPortStatus_1_2);
return Void();
}
Return<void>
Usb::enableContaminantPresenceDetection(const hidl_string & /*portName*/,
bool enable) {
std::string disable = GetProperty(kDisableContaminantDetection, "");
if (disable != "true")
moistureDetectionEnabled = enable;
hidl_vec<PortStatus> currentPortStatus_1_2;
queryVersionHelper(this, &currentPortStatus_1_2);
return Void();
}
Return<void>
Usb::enableContaminantPresenceProtection(const hidl_string & /*portName*/,
bool /*enable*/) {
hidl_vec<PortStatus> currentPortStatus_1_2;
queryVersionHelper(this, &currentPortStatus_1_2);
return Void();
}
struct data {
int uevent_fd;
android::hardware::usb::V1_3::implementation::Usb *usb;
};
static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
char msg[UEVENT_MSG_LEN + 2];
char *cp;
int n;
n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0)
return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;
msg[n] = '\0';
msg[n + 1] = '\0';
cp = msg;
while (*cp) {
if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) {
ALOGI("partner added");
pthread_mutex_lock(&payload->usb->mPartnerLock);
payload->usb->mPartnerUp = true;
pthread_cond_signal(&payload->usb->mPartnerCV);
pthread_mutex_unlock(&payload->usb->mPartnerLock);
} else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) ||
!strncmp(cp, "CCIC=WATER", strlen("CCIC=WATER")) ||
!strncmp(cp, "CCIC=DRY", strlen("CCIC=DRY"))) {
hidl_vec<PortStatus> currentPortStatus_1_2;
queryVersionHelper(payload->usb, &currentPortStatus_1_2);
// Role switch is not in progress and port is in disconnected state
if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) {
for (unsigned long i = 0; i < currentPortStatus_1_2.size(); i++) {
DIR *dp = opendir(
std::string("/sys/class/typec/" +
std::string(currentPortStatus_1_2[i]
.status_1_1.status.portName.c_str()) +
"-partner")
.c_str());
if (dp == NULL) {
// PortRole role = {.role = static_cast<uint32_t>(PortMode::UFP)};
switchToDrp(currentPortStatus_1_2[i].status_1_1.status.portName);
} else {
closedir(dp);
}
}
pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
}
break;
}
/* advance to after the next \0 */
while (*cp++) {
}
}
}
void *work(void *param) {
int epoll_fd, uevent_fd;
struct epoll_event ev;
int nevents = 0;
struct data payload;
ALOGE("creating thread");
uevent_fd = uevent_open_socket(64 * 1024, true);
if (uevent_fd < 0) {
ALOGE("uevent_init: uevent_open_socket failed\n");
return NULL;
}
payload.uevent_fd = uevent_fd;
payload.usb = (android::hardware::usb::V1_3::implementation::Usb *)param;
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
ev.events = EPOLLIN;
ev.data.ptr = (void *)uevent_event;
epoll_fd = epoll_create(64);
if (epoll_fd == -1) {
ALOGE("epoll_create failed; errno=%d", errno);
goto error;
}
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
ALOGE("epoll_ctl failed; errno=%d", errno);
goto error;
}
while (!destroyThread) {
struct epoll_event events[64];
nevents = epoll_wait(epoll_fd, events, 64, -1);
if (nevents == -1) {
if (errno == EINTR)
continue;
ALOGE("usb epoll_wait failed; errno=%d", errno);
break;
}
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr)
(*(void (*)(int, struct data *payload))events[n].data.ptr)(
events[n].events, &payload);
}
}
ALOGI("exiting worker thread");
error:
close(uevent_fd);
if (epoll_fd >= 0)
close(epoll_fd);
return NULL;
}
void sighandler(int sig) {
if (sig == SIGUSR1) {
destroyThread = true;
ALOGI("destroy set");
return;
}
signal(SIGUSR1, sighandler);
}
Return<void> Usb::setCallback(const sp<V1_0::IUsbCallback> &callback) {
sp<V1_1::IUsbCallback> callback_V1_1 = V1_1::IUsbCallback::castFrom(callback);
sp<IUsbCallback> callback_V1_2 = IUsbCallback::castFrom(callback);
if (callback != NULL) {
if (callback_V1_2 != NULL)
ALOGI("Registering 1.2 callback");
else if (callback_V1_1 != NULL)
ALOGI("Registering 1.1 callback");
}
pthread_mutex_lock(&mLock);
/*
* When both the old callback and new callback values are NULL,
* there is no need to spin off the worker thread.
* When both the values are not NULL, we would already have a
* worker thread running, so updating the callback object would
* be suffice.
*/
if ((mCallback_1_0 == NULL && callback == NULL) ||
(mCallback_1_0 != NULL && callback != NULL)) {
/*
* Always store as V1_0 callback object. Type cast to V1_1
* when the callback is actually invoked.
*/
mCallback_1_0 = callback;
pthread_mutex_unlock(&mLock);
return Void();
}
mCallback_1_0 = callback;
ALOGI("registering callback");
// Kill the worker thread if the new callback is NULL.
if (mCallback_1_0 == NULL) {
pthread_mutex_unlock(&mLock);
if (!pthread_kill(mPoll, SIGUSR1)) {
pthread_join(mPoll, NULL);
ALOGI("pthread destroyed");
}
return Void();
}
destroyThread = false;
signal(SIGUSR1, sighandler);
/*
* Create a background thread if the old callback value is NULL
* and being updated with a new value.
*/
if (pthread_create(&mPoll, NULL, work, this)) {
ALOGE("pthread creation failed %d", errno);
mCallback_1_0 = NULL;
}
pthread_mutex_unlock(&mLock);
return Void();
}
} // namespace implementation
} // namespace V1_3
} // namespace usb
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,99 @@
/*
* 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 <android-base/file.h>
#include <android/hardware/usb/1.2/IUsbCallback.h>
#include <android/hardware/usb/1.2/types.h>
#include <android/hardware/usb/1.3/IUsb.h>
#include <hidl/Status.h>
#include <utils/Log.h>
#define UEVENT_MSG_LEN 2048
// The type-c stack waits for 4.5 - 5.5 secs before declaring a port non-pd.
// The -partner directory would not be created until this is done.
// Having a margin of ~3 secs for the directory and other related bookeeping
// structures created and uvent fired.
#define PORT_TYPE_TIMEOUT 8
namespace android {
namespace hardware {
namespace usb {
namespace V1_3 {
namespace implementation {
using ::android::sp;
using ::android::base::ReadFileToString;
using ::android::base::WriteStringToFile;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::usb::V1_0::PortDataRole;
using ::android::hardware::usb::V1_0::PortPowerRole;
using ::android::hardware::usb::V1_0::PortRole;
using ::android::hardware::usb::V1_0::PortRoleType;
using ::android::hardware::usb::V1_0::Status;
using ::android::hardware::usb::V1_1::PortMode_1_1;
using ::android::hardware::usb::V1_1::PortStatus_1_1;
using ::android::hardware::usb::V1_2::IUsbCallback;
using ::android::hardware::usb::V1_2::PortStatus;
using ::android::hardware::usb::V1_3::IUsb;
using ::android::hidl::base::V1_0::DebugInfo;
using ::android::hidl::base::V1_0::IBase;
enum class HALVersion { V1_0, V1_1, V1_2, V1_3 };
#define USB_DATA_PATH \
"/sys/devices/virtual/usb_notify/usb_control/usb_data_enabled"
struct Usb : public IUsb {
Usb();
Return<void> switchRole(const hidl_string &portName,
const PortRole &role) override;
Return<void> setCallback(const sp<V1_0::IUsbCallback> &callback) override;
Return<void> queryPortStatus() override;
Return<void> enableContaminantPresenceDetection(const hidl_string &portName,
bool enable);
Return<void> enableContaminantPresenceProtection(const hidl_string &portName,
bool enable);
Return<bool> enableUsbDataSignal(bool enable) override;
sp<V1_0::IUsbCallback> mCallback_1_0;
// Protects mCallback variable
pthread_mutex_t mLock;
// Protects roleSwitch operation
pthread_mutex_t mRoleSwitchLock;
// Threads waiting for the partner to come back wait here
pthread_cond_t mPartnerCV;
// lock protecting mPartnerCV
pthread_mutex_t mPartnerLock;
// Variable to signal partner coming back online after type switch
bool mPartnerUp;
private:
pthread_t mPoll;
};
} // namespace implementation
} // namespace V1_3
} // namespace usb
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,16 @@
service vendor.usb-hal-1-3 /vendor/bin/hw/android.hardware.usb@1.3-service.samsung
class hal
user system
group system shell mtp wakelock
capabilities WAKE_ALARM BLOCK_SUSPEND
on post-fs
chown root system /sys/class/typec/port0/power_role
chown root system /sys/class/typec/port0/data_role
chown root system /sys/class/typec/port0/port_type
chown root system /sys/devices/virtual/sec/ccic/water
chown root system /sys/devices/virtual/usb_notify/usb_control/usb_data_enabled
chmod 664 /sys/class/typec/port0/power_role
chmod 664 /sys/class/typec/port0/data_role
chmod 664 /sys/class/typec/port0/port_type
chmod 664 /sys/devices/virtual/usb_notify/usb_control/usb_data_enabled

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.usb</name>
<transport>hwbinder</transport>
<version>1.3</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* Copyright (C) 2022 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.usb@1.3-service.samsung"
#include "Usb.h"
#include <hidl/HidlTransportSupport.h>
using android::sp;
// libhwbinder:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::usb::V1_3::IUsb;
using android::hardware::usb::V1_3::implementation::Usb;
using android::OK;
using android::status_t;
int main() {
android::sp<IUsb> service = new Usb();
configureRpcThreadpool(1, true /*callerWillJoin*/);
status_t status = service->registerAsService();
if (status != OK) {
ALOGE("Cannot register USB HAL service");
return 1;
}
ALOGI("USB HAL Ready.");
joinRpcThreadpool();
// Under noraml cases, execution will not reach this line.
ALOGI("USB HAL failed to join thread pool.");
return 1;
}

View 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,
}

View file

@ -0,0 +1,343 @@
/*
* 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 <map>
#include <thread>
namespace aidl {
namespace android {
namespace hardware {
namespace vibrator {
static std::map<Effect, int> CP_TRIGGER_EFFECTS{{Effect::CLICK, 10},
{Effect::DOUBLE_CLICK, 14},
{Effect::HEAVY_CLICK, 23},
{Effect::TEXTURE_TICK, 50},
{Effect::TICK, 50}};
/*
* 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);
mHasTimedOutEffect = nodeExists(VIBRATOR_CP_TRIGGER_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;
if (mHasTimedOutEffect)
writeNode(VIBRATOR_CP_TRIGGER_PATH, 0); // Clear all effects
status = activate(timeoutMs);
if (callback != nullptr) {
std::thread([=] {
LOG(DEBUG) << "Starting on on another thread";
usleep(timeoutMs * 1000);
LOG(DEBUG) << "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;
uint32_t amplitude = strengthToAmplitude(strength, &status);
uint32_t ms = 1000;
if (!status.isOk())
return status;
activate(0);
setAmplitude(amplitude);
if (mHasTimedOutEffect &&
CP_TRIGGER_EFFECTS.find(effect) != CP_TRIGGER_EFFECTS.end()) {
writeNode(VIBRATOR_CP_TRIGGER_PATH, CP_TRIGGER_EFFECTS[effect]);
} else {
if (mHasTimedOutEffect)
writeNode(VIBRATOR_CP_TRIGGER_PATH, 0); // Clear previous effect
ms = effectToMs(effect, &status);
if (!status.isOk())
return status;
}
status = activate(ms);
if (callback != nullptr) {
std::thread([=] {
LOG(DEBUG) << "Starting perform on another thread";
usleep(ms * 1000);
LOG(DEBUG) << "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;
}
if (intensity == 0) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
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 10;
case Effect::DOUBLE_CLICK:
return 15;
case Effect::TICK:
case Effect::TEXTURE_TICK:
case Effect::THUD:
case Effect::POP:
return 5;
case Effect::HEAVY_CLICK:
return 10;
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 30000;
}
*status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
return 0;
}
} // namespace vibrator
} // namespace hardware
} // namespace android
} // namespace aidl

View file

@ -0,0 +1,95 @@
/*
* 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"
#define VIBRATOR_CP_TRIGGER_PATH \
"/sys/class/timed_output/vibrator/cp_trigger_index"
using ::aidl::android::hardware::vibrator::Braking;
using ::aidl::android::hardware::vibrator::CompositeEffect;
using ::aidl::android::hardware::vibrator::CompositePrimitive;
using ::aidl::android::hardware::vibrator::Effect;
using ::aidl::android::hardware::vibrator::EffectStrength;
using ::aidl::android::hardware::vibrator::IVibratorCallback;
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;
bool mHasTimedOutEffect;
};
} // namespace vibrator
} // namespace hardware
} // namespace android
} // namespace aidl

View file

@ -0,0 +1,10 @@
on init
chown system system /sys/class/timed_output/vibrator/cp_trigger_index
chown system system /sys/class/timed_output/vibrator/enable
chown system system /sys/class/timed_output/vibrator/intensity
service vendor.vibrator-default /vendor/bin/hw/android.hardware.vibrator-service.samsung
class hal
user system
group system
shutdown critical

View file

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.vibrator</name>
<fqname>IVibrator/default</fqname>
</hal>
</manifest>

View file

@ -0,0 +1,27 @@
/*
* Copyright (C) 2021 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "Vibrator.h"
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.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
}

View file

@ -0,0 +1,22 @@
// 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_library_static {
name: "libinit_universal7885",
recovery_available: true,
whole_static_libs: ["libbase"],
header_libs: ["libbase_headers"],
srcs: ["init_universal7885.cpp"],
include_dirs: ["system/core/init"]
}

View file

@ -0,0 +1,94 @@
/*
Copyright (c) 2021, The LineageOS Project
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <vector>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include "property_service.h"
#include "vendor_init.h"
using android::base::GetProperty;
using std::string;
std::vector<std::string> ro_props_default_source_order = {
"", "odm.", "product.", "system.", "system_ext.", "vendor.", "vendor_dlkm.",
};
void property_override(char const prop[], char const value[], bool add = true) {
prop_info *pi;
pi = (prop_info *)__system_property_find(prop);
if (pi)
__system_property_update(pi, value, strlen(value));
else if (add)
__system_property_add(prop, strlen(prop), value, strlen(value));
}
void set_ro_build_prop(const std::string &prop, const std::string &value,
bool product = true) {
string prop_name;
for (const auto &source : ro_props_default_source_order) {
if (product)
prop_name = "ro.product." + source + prop;
else
prop_name = "ro." + source + "build." + prop;
property_override(prop_name.c_str(), value.c_str());
}
}
bool hasEnding(std::string const &fullString, std::string const &ending) {
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare(fullString.length() - ending.length(),
ending.length(), ending));
} else {
return false;
}
}
void vendor_load_properties() {
string model;
model = GetProperty("ro.boot.product.model", "");
if (model.empty()) {
model = GetProperty("ro.boot.em.model", "");
}
if (hasEnding(model, "N") || hasEnding(model, "S") || hasEnding(model, "K") ||
model == "SM-A202F") {
property_override("ro.boot.product.hardware.sku", "NFC");
}
set_ro_build_prop("model", model);
set_ro_build_prop("product", model, false);
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 Eureka Team.
* https://github.com/eurekadevelopment
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
cc_library_shared {
name: "libcorrectcamera",
defaults: ["hidl_defaults"],
proprietary: true,
srcs: [
"CorrectCameraID.cpp",
],
shared_libs: [
"libhidlbase",
"libhardware",
"camera.device@3.2-impl",
"libcamera_metadata",
"android.hardware.camera.device@3.2",
"android.hardware.camera.provider@2.4",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
"liblog",
"libutils",
"libcutils",
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
],
}

View file

@ -0,0 +1,164 @@
/*
* 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 ANDROID_HARDWARE_CAM_DEVICE_V3_2_CAMERADEVICE_H
#define ANDROID_HARDWARE_CAM_DEVICE_V3_2_CAMERADEVICE_H
#include "CameraDeviceSession.h"
#include "CameraMetadata.h"
#include "CameraModule.h"
#include "utils/Mutex.h"
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V3_2 {
namespace implementation {
using ::android::Mutex;
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::camera::common::V1_0::CameraResourceCost;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::TorchMode;
using ::android::hardware::camera::common::V1_0::helper::CameraModule;
using ::android::hardware::camera::device::V3_2::ICameraDevice;
using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
using ::android::hardware::camera::device::V3_2::RequestTemplate;
/*
* The camera device HAL implementation is opened lazily (via the open call)
*/
struct CameraDevice : public virtual RefBase {
// Called by provider HAL. Provider HAL must ensure the uniqueness of
// CameraDevice object per cameraId, or there could be multiple CameraDevice
// trying to access the same physical camera.
// Also, provider will have to keep track of all CameraDevice objects in
// order to notify CameraDevice when the underlying camera is detached
CameraDevice(sp<CameraModule> module, const std::string &cameraId,
const SortedVector<std::pair<std::string, std::string>>
&cameraDeviceNames);
virtual ~CameraDevice();
// Retrieve the HIDL interface, split into its own class to avoid inheritance
// issues when dealing with minor version revs and simultaneous implementation
// and interface inheritance
virtual sp<ICameraDevice> getInterface() {
return new TrampolineDeviceInterface_3_2(this);
}
// Caller must use this method to check if CameraDevice ctor failed
bool isInitFailed() { return mInitFail; }
// Used by provider HAL to signal external camera disconnected
void setConnectionStatus(bool connected);
/* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice
* follow. */
// The following method can be called without opening the actual camera device
Return<void> getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb);
Return<void>
getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb);
Return<void>
getEurekaCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb);
Return<Status> setTorchMode(TorchMode mode);
// Open the device HAL and also return a default capture session
Return<void> open(const sp<ICameraDeviceCallback> &callback,
ICameraDevice::open_cb _hidl_cb);
Return<void> nuke(const sp<ICameraDeviceCallback> &callback,
ICameraDevice::open_cb _hidl_cb);
// Forward the dump call to the opened session, or do nothing
Return<void> dumpState(const ::android::hardware::hidl_handle &fd);
/* End of Methods from
* ::android::hardware::camera::device::V3_2::ICameraDevice */
protected:
// Overridden by child implementations for returning different versions of
// CameraDeviceSession
virtual sp<CameraDeviceSession>
createSession(camera3_device_t *, const camera_metadata_t *deviceInfo,
const sp<ICameraDeviceCallback> &);
const sp<CameraModule> mModule;
const std::string mCameraId;
// const after ctor
int mCameraIdInt;
int mDeviceVersion;
bool mInitFail = false;
// Set by provider (when external camera is connected/disconnected)
bool mDisconnected;
wp<CameraDeviceSession> mSession = nullptr;
const SortedVector<std::pair<std::string, std::string>> &mCameraDeviceNames;
// gating access to mSession and mDisconnected
mutable Mutex mLock;
// convert conventional HAL status to HIDL Status
static Status getHidlStatus(int);
Status initStatus() const;
private:
struct TrampolineDeviceInterface_3_2 : public ICameraDevice {
TrampolineDeviceInterface_3_2(sp<CameraDevice> parent) : mParent(parent) {}
virtual Return<void>
getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb) override {
return mParent->getResourceCost(_hidl_cb);
}
virtual Return<void> getCameraCharacteristics(
V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
return mParent->getCameraCharacteristics(_hidl_cb);
}
virtual Return<Status> setTorchMode(TorchMode mode) override {
return mParent->setTorchMode(mode);
}
virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback> &callback,
V3_2::ICameraDevice::open_cb _hidl_cb) override {
return mParent->open(callback, _hidl_cb);
}
virtual Return<void> dumpState(const hidl_handle &fd) override {
return mParent->dumpState(fd);
}
private:
sp<CameraDevice> mParent;
};
};
} // namespace implementation
} // namespace V3_2
} // namespace device
} // namespace camera
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_CAM_DEVICE_V3_2_CAMERADEVICE_H

View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2022 Eureka Team.
* https://github.com/eurekadevelopment
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "CamDevice_3_2.h"
#include <include/convert.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V3_2 {
namespace implementation {
using ::android::hardware::camera::common::V1_0::Status;
Return<void> CameraDevice::getCameraCharacteristics(
ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
Status status = initStatus();
CameraMetadata cameraCharacteristics;
if (status == Status::OK) {
// Module 2.1+ codepath.
struct camera_info info;
if (mCameraIdInt == 1)
mCameraIdInt = 2;
int ret = mModule->getCameraInfo(mCameraIdInt, &info);
if (ret == OK) {
convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
} else {
ALOGE("%s: get camera info failed!", __FUNCTION__);
status = Status::INTERNAL_ERROR;
}
}
_hidl_cb(status, cameraCharacteristics);
return Void();
}
Return<void> CameraDevice::getEurekaCharacteristics(
ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
return CameraDevice::getCameraCharacteristics(_hidl_cb);
}
Return<void> CameraDevice::open(const sp<ICameraDeviceCallback> &callback,
ICameraDevice::open_cb _hidl_cb) {
Status status = initStatus();
sp<CameraDeviceSession> session = nullptr;
if (callback == nullptr) {
ALOGE("%s: cannot open camera %s. callback is null!", __FUNCTION__,
mCameraId.c_str());
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
if (status != Status::OK) {
// Provider will never pass initFailed device to client, so
// this must be a disconnected camera
ALOGE("%s: cannot open camera %s. camera is disconnected!", __FUNCTION__,
mCameraId.c_str());
_hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
return Void();
} else {
mLock.lock();
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
session = mSession.promote();
if (session != nullptr && !session->isClosed()) {
ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
mLock.unlock();
_hidl_cb(Status::CAMERA_IN_USE, nullptr);
return Void();
}
/** Open HAL device */
status_t res;
camera3_device_t *device;
std::string mCameraID = mCameraId;
if (mCameraIdInt == 1)
mCameraIdInt = 2;
if (mCameraID == "1")
mCameraID = "2";
res = mModule->open(mCameraID.c_str(),
reinterpret_cast<hw_device_t **>(&device));
if (res != OK) {
ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraID.c_str());
mLock.unlock();
_hidl_cb(getHidlStatus(res), nullptr);
return Void();
}
/** Cross-check device version */
if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
ALOGE("%s: Could not open camera: "
"Camera device should be at least %x, reports %x instead",
__FUNCTION__, CAMERA_DEVICE_API_VERSION_3_2,
device->common.version);
device->common.close(&device->common);
mLock.unlock();
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
struct camera_info info;
res = mModule->getCameraInfo(mCameraIdInt, &info);
if (res != OK) {
ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
device->common.close(&device->common);
mLock.unlock();
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
session =
createSession(device, info.static_camera_characteristics, callback);
if (session == nullptr) {
ALOGE("%s: camera device session allocation failed", __FUNCTION__);
mLock.unlock();
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
if (session->isInitFailed()) {
ALOGE("%s: camera device session init failed", __FUNCTION__);
session = nullptr;
mLock.unlock();
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
mSession = session;
IF_ALOGV() {
session->getInterface()->interfaceChain(
[](::android::hardware::hidl_vec<::android::hardware::hidl_string>
interfaceChain) {
ALOGV("Session interface chain:");
for (const auto &iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
mLock.unlock();
}
_hidl_cb(status, session->getInterface());
return Void();
}
Return<void> CameraDevice::nuke(const sp<ICameraDeviceCallback> &callback,
ICameraDevice::open_cb _hidl_cb) {
return CameraDevice::open(callback, _hidl_cb);
}
} // namespace implementation
} // namespace V3_2
} // namespace device
} // namespace camera
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,12 @@
//
// Copyright (C) 2021 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
cc_library_shared {
name: "fakelogprint",
vendor: true,
shared_libs: ["liblog"],
srcs: ["fakelogprint.cpp"],
}

View file

@ -0,0 +1,5 @@
#include <log/log.h>
int __android_log_print(int prio, const char *tag, const char *fmt, ...) {
return 0;
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 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 <ALooper.h>
#define LOG_TAG "libshim_sensorndkbridge"
#include <android-base/logging.h>
using android::Mutex;
static Mutex gLock;
extern "C" ALooper *ALooper_forCamera() {
LOG(VERBOSE) << "ALooper_forCamera";
ALooper *sLooper = NULL;
Mutex::Autolock autoLock(gLock);
sLooper = new ALooper;
return sLooper;
}
extern "C" int ALooper_release_forCamera(ALooper *sLooper) {
if (sLooper != nullptr) {
Mutex::Autolock autoLock(gLock);
delete sLooper;
}
return 0;
}
extern "C" int ALooper_pollOnce_camera(ALooper *sLooper, int timeoutMillis,
int *outFd, int *outEvents,
void **outData) {
int res = sLooper->pollOnce(timeoutMillis, outFd, outEvents, outData);
LOG(VERBOSE) << "ALooper_pollOnce_camera => " << res;
return res;
}

Some files were not shown because too many files have changed in this diff Show more