diff --git a/init.hardware.rc b/init.hardware.rc index c7931579..7499cd60 100644 --- a/init.hardware.rc +++ b/init.hardware.rc @@ -346,6 +346,8 @@ on early-boot chown system system /sys/class/leds/vibrator/device/set_sequencer chown system system /sys/class/leds/vibrator/device/autocal_result chown system system /sys/class/leds/vibrator/device/ctrl_loop + chown system system /sys/class/leds/vibrator/device/ol_lra_period + chown system system /sys/class/leds/vibrator/device/autocal # Permission for LED driver chown system system /sys/class/leds/red/on_off_ms diff --git a/sepolicy/file.te b/sepolicy/file.te index 47862b43..88b12dad 100644 --- a/sepolicy/file.te +++ b/sepolicy/file.te @@ -40,6 +40,7 @@ type persist_file, file_type; type persist_data_file, file_type; type persist_display_file, file_type; type persist_sensors_file, file_type; +type persist_haptics_file, file_type; type netmgr_data_file, file_type, data_file_type; diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts index 516bc026..0e50e49f 100644 --- a/sepolicy/file_contexts +++ b/sepolicy/file_contexts @@ -305,6 +305,7 @@ /persist/data(/.*)? u:object_r:persist_data_file:s0 /persist/display(/.*)? u:object_r:persist_display_file:s0 /persist/sensors(/.*)? u:object_r:persist_sensors_file:s0 +/persist/haptics(/.*)? u:object_r:persist_haptics_file:s0 /metadata u:object_r:rootfs:s0 /metadata/.* u:object_r:vold_data_file:s0 diff --git a/sepolicy/hal_vibrator_default.te b/sepolicy/hal_vibrator_default.te index ba580b7e..5cc3a76d 100644 --- a/sepolicy/hal_vibrator_default.te +++ b/sepolicy/hal_vibrator_default.te @@ -2,3 +2,7 @@ r_dir_file(hal_vibrator_default, sysfs_leds) allow hal_vibrator_default sysfs_leds:file w_file_perms; allow hal_vibrator_default sysfs_msm_subsys:file rw_file_perms; allow hal_vibrator_default sysfs_msm_subsys:dir search; + +# read-only permission to obtain the calibration data +r_dir_file(hal_vibrator_default, persist_haptics_file) +allow hal_vibrator_default persist_file:dir search; diff --git a/vibrator/service.cpp b/vibrator/service.cpp index 9e24368b..f03dac24 100644 --- a/vibrator/service.cpp +++ b/vibrator/service.cpp @@ -31,14 +31,91 @@ using namespace android; // Refer to Documentation/ABI/testing/sysfs-class-led-driver-drv2624 // kernel documentation on the detail usages for ABIs below -static const char *ACTIVATE_PATH = "/sys/class/leds/vibrator/activate"; -static const char *DURATION_PATH = "/sys/class/leds/vibrator/duration"; -static const char *STATE_PATH = "/sys/class/leds/vibrator/state"; -static const char *RTP_INPUT_PATH = "/sys/class/leds/vibrator/device/rtp_input"; -static const char *MODE_PATH = "/sys/class/leds/vibrator/device/mode"; -static const char *SEQUENCER_PATH = "/sys/class/leds/vibrator/device/set_sequencer"; -static const char *SCALE_PATH = "/sys/class/leds/vibrator/device/scale"; -static const char *CTRL_LOOP_PATH = "/sys/class/leds/vibrator/device/ctrl_loop"; +static constexpr char ACTIVATE_PATH[] = "/sys/class/leds/vibrator/activate"; +static constexpr char DURATION_PATH[] = "/sys/class/leds/vibrator/duration"; +static constexpr char STATE_PATH[] = "/sys/class/leds/vibrator/state"; +static constexpr char RTP_INPUT_PATH[] = "/sys/class/leds/vibrator/device/rtp_input"; +static constexpr char MODE_PATH[] = "/sys/class/leds/vibrator/device/mode"; +static constexpr char SEQUENCER_PATH[] = "/sys/class/leds/vibrator/device/set_sequencer"; +static constexpr char SCALE_PATH[] = "/sys/class/leds/vibrator/device/scale"; +static constexpr char CTRL_LOOP_PATH[] = "/sys/class/leds/vibrator/device/ctrl_loop"; + +// File path to the calibration file +static constexpr char CALIBRATION_FILEPATH[] = "/persist/haptics/drv2624.cal"; + +// Kernel ABIs for updating the calibration data +static constexpr char AUTOCAL_CONFIG[] = "autocal"; +static constexpr char LRA_PERIOD_CONFIG[] = "lra_period"; +static constexpr char AUTOCAL_FILEPATH[] = "/sys/class/leds/vibrator/device/autocal"; +static constexpr char OL_LRA_PERIOD_FILEPATH[] = "/sys/class/leds/vibrator/device/ol_lra_period"; + +static std::string trim(const std::string& str, + const std::string& whitespace = " \t") { + const auto str_begin = str.find_first_not_of(whitespace); + if (str_begin == std::string::npos) { + return ""; + } + + const auto str_end = str.find_last_not_of(whitespace); + const auto str_range = str_end - str_begin + 1; + + return str.substr(str_begin, str_range); +} + +static bool loadCalibrationData() { + std::map config_data; + + std::ofstream autocal{AUTOCAL_FILEPATH}; + if (!autocal) { + int error = errno; + ALOGE("Failed to open %s (%d): %s", AUTOCAL_FILEPATH, error, + strerror(error)); + return false; + } + + std::ofstream ol_lra_period{OL_LRA_PERIOD_FILEPATH}; + if (!ol_lra_period) { + int error = errno; + ALOGE("Failed to open %s (%d): %s", OL_LRA_PERIOD_FILEPATH, error, + strerror(error)); + return false; + } + + std::ifstream cal_data{CALIBRATION_FILEPATH}; + if (!cal_data) { + int error = errno; + ALOGE("Failed to open %s (%d): %s", CALIBRATION_FILEPATH, error, + strerror(error)); + return false; + } + + std::string line; + + while (std::getline(cal_data, line)) { + if (line.empty() || line[0] == '#') { + continue; + } + std::istringstream is_line(line); + std::string key; + if (std::getline(is_line, key, ':')) { + std::string value; + + if (std::getline(is_line, value)) { + config_data[trim(key)] = trim(value); + } + } + } + + if(config_data.find(AUTOCAL_CONFIG) != config_data.end()) { + autocal << config_data[AUTOCAL_CONFIG] << std::endl; + } + + if(config_data.find(LRA_PERIOD_CONFIG) != config_data.end()) { + ol_lra_period << config_data[LRA_PERIOD_CONFIG] << std::endl; + } + + return true; +} status_t registerVibratorService() { // ostreams below are required @@ -101,6 +178,10 @@ status_t registerVibratorService() { ALOGW("Failed to open %s (%d): %s", CTRL_LOOP_PATH, error, strerror(error)); } + if (!loadCalibrationData()) { + ALOGW("Failed load calibration data"); + } + sp vibrator = new Vibrator(std::move(activate), std::move(duration), std::move(state), std::move(rtpinput), std::move(mode), std::move(sequencer), std::move(scale), std::move(ctrlloop));