mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-02-03 00:29:16 +00:00
android: multidevice capabilites and accessiblity features (and "liquid glass") (#202)
many thanks to @rithvikvibhu for help with the hearing aids feature adds: hearing aid two-device connection new UI transparency mode customization commits: * android: add accessibility stuff adds option for customizing transparency mode, amplification, tone, etc. * docs: update transparency mode format * android: don't 'start' service every time MainActivity is launched * android: add basic multidevice capabilities use at your own risk, may or may not work * android: clean up a bit of AI gen'd code * android: clean up main service and remove minimum API on head gestures * android: clean up a lot of stuff * android: implement the accessiblity settings page * android: add EQ settings for phone and media * android: add toggle for DID hook * docs: add 'has ownership' control cmd * android: fix balance NaN error when amplification L/R is both zero * android: bring back some accessiblity settings and add listeners for all config * android: add header to ATTManager * android: use device name sent by the connected device in island * android: fix track color in tone volume * android: remove unused composable * android: update eq sliders style * android: fix text color in selectors * android: add delay before starting head tracking again * android: add a few options ik not the right branch/pr but, eh, i am not merging this hook until i test further, and if i don't merge, conflicts, a lot of 'em * android: a small ui fix * docs: a few more control cmds * android: add microphone setting also, un-hardcoded strings, and updated text sizes * android: improve dropdowns ai generated * android: move attmanager to service to avoid trying to connect multiple times * android: add ui for hearing stuff mostly copied from the transparency settings, which are now updated to match ios <26 ui * android: add media assist options in hearing aid ui only * android: add hearing aid adjustments * android: liquidglass sliders * android: improve liquid glass sliders * android: little more liquid glass * android: fix hearing aid parsing * android: remove customdeviceactivity from manifest * android: remove unused strings * android: small ui tweaks * android: a very big commit refactoring ui, mostly * android: move padding to StyledScaffold's content because haze needs it * android: revert accidental capitalization on toggle label * android: update usages for toggle * android: liquidglass, maybe? the switch and icon button took quite a while. i forgot the order of modifiers matters! * remove bleonly mode, use CAPod instead * remove bleonly mode, use CAPod instead * android: fix switch styling * android: remove fade from transition * android: add A16's new bluetooth identifier for log collection just why... * android: fix crash in head gestures screen * android: show head gestures status in the navigation button * android: don't crash if att not available * android: use lazycolumn in airpods settings for better performance and navigation transitions * android: fix text color in troubshooting button and pressandhold settings * android: bring back original confirmation dialog too lazy to fix/implement properly the glassy one * android: prevent hearing aid turning off itself * android: hide media assist, not implemented * docs: update README with new features * docs: add demo video * docs: add new screenshots for android * docs: update demo video position * docs: app3 compatibility * docs: new control cmds '25 (again) * docs: change section title in control cmd doc Updated section title from 'Control Commands' to 'Identifiers and details'. * android: ui tweaks * android: update styled slider thumb * android: add accessiblity service for camera control * android: add camera control, finally i got too lazy to find out how to listen to app openings earlier, wasn't too hard * android: add option to change camera app id * android: not use relative paths for executing commands i hope it's the same across all skins * android: fix transparency and noise cancellation flags huh... was it always like this? * android: revert to using relative paths for su compatibility issues with magisk * android: bump version * android: don't crash if self MAC is not available * android: remove unused LOCAL_ADDRESS permission * android: add opensource licenses should've done this a long time ago! * android: move navigation button to activity level * android: update animation time on switch tap * android: implement setting hearing test results * android: update title in hearing test screen * docs: add screenshot for hearing test * android: fix haze for dialog when enabling hearing aid * android: parse device info * android: add support for various models still need to update images or find a way to fetch from apple's cdn * android: fix a2dp connection * android: remove stray eq config in accessibility settings * android: improve connection handling * android: add a (very important) support dialog to not be invasive, this only shows up once, and never again. * docs: add note for DID hook on android
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
#include <string>
|
||||
#include <sys/system_properties.h>
|
||||
#include "l2c_fcr_hook.h"
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
|
||||
#define LOG_TAG "AirPodsHook"
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
@@ -126,6 +128,9 @@ static void (*original_l2cu_process_our_cfg_req)(tL2C_CCB* p_ccb, tL2CAP_CFG_INF
|
||||
static void (*original_l2c_csm_config)(tL2C_CCB* p_ccb, uint8_t event, void* p_data) = nullptr;
|
||||
static void (*original_l2cu_send_peer_info_req)(tL2C_LCB* p_lcb, uint16_t info_type) = nullptr;
|
||||
|
||||
// Add original pointer for BTA_DmSetLocalDiRecord
|
||||
static tBTA_STATUS (*original_BTA_DmSetLocalDiRecord)(tSDP_DI_RECORD* p_device_info, uint32_t* p_handle) = nullptr;
|
||||
|
||||
uint8_t fake_l2c_fcr_chk_chan_modes(void* p_ccb) {
|
||||
LOGI("l2c_fcr_chk_chan_modes hooked, returning true.");
|
||||
return 1;
|
||||
@@ -156,6 +161,53 @@ void fake_l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
// New loader for SDP hook offset (persist.librepods.sdp_offset)
|
||||
uintptr_t loadSdpOffset() {
|
||||
const char* property_name = "persist.librepods.sdp_offset";
|
||||
char value[PROP_VALUE_MAX] = {0};
|
||||
|
||||
int len = __system_property_get(property_name, value);
|
||||
if (len > 0) {
|
||||
LOGI("Read sdp offset from property: %s", value);
|
||||
uintptr_t offset;
|
||||
char* endptr = nullptr;
|
||||
|
||||
const char* parse_start = value;
|
||||
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
|
||||
parse_start = value + 2;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
offset = strtoul(parse_start, &endptr, 16);
|
||||
|
||||
if (errno == 0 && endptr != parse_start && *endptr == '\0' && offset > 0) {
|
||||
LOGI("Parsed sdp offset: 0x%x", offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
LOGE("Failed to parse sdp offset from property value: %s", value);
|
||||
}
|
||||
|
||||
LOGI("No sdp offset property present - skipping SDP hook");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fake BTA_DmSetLocalDiRecord: set vendor/vendor_id_source then call original
|
||||
tBTA_STATUS fake_BTA_DmSetLocalDiRecord(tSDP_DI_RECORD* p_device_info, uint32_t* p_handle) {
|
||||
LOGI("BTA_DmSetLocalDiRecord hooked - forcing vendor fields");
|
||||
if (p_device_info) {
|
||||
p_device_info->vendor = 0x004C;
|
||||
p_device_info->vendor_id_source = 0x0001;
|
||||
}
|
||||
LOGI("Set vendor=0x%04x, vendor_id_source=0x%04x", p_device_info->vendor, p_device_info->vendor_id_source);
|
||||
if (original_BTA_DmSetLocalDiRecord) {
|
||||
return original_BTA_DmSetLocalDiRecord(p_device_info, p_handle);
|
||||
}
|
||||
|
||||
LOGE("Original BTA_DmSetLocalDiRecord not available");
|
||||
return BTA_FAILURE;
|
||||
}
|
||||
|
||||
uintptr_t loadHookOffset([[maybe_unused]] const char* package_name) {
|
||||
const char* property_name = "persist.librepods.hook_offset";
|
||||
char value[PROP_VALUE_MAX] = {0};
|
||||
@@ -320,6 +372,7 @@ bool findAndHookFunction(const char *library_name) {
|
||||
uintptr_t l2cu_process_our_cfg_req_offset = loadL2cuProcessCfgReqOffset();
|
||||
uintptr_t l2c_csm_config_offset = loadL2cCsmConfigOffset();
|
||||
uintptr_t l2cu_send_peer_info_req_offset = loadL2cuSendPeerInfoReqOffset();
|
||||
uintptr_t sdp_offset = loadSdpOffset();
|
||||
|
||||
bool success = false;
|
||||
|
||||
@@ -392,6 +445,21 @@ bool findAndHookFunction(const char *library_name) {
|
||||
LOGI("Skipping l2cu_send_peer_info_req hook as offset is not available");
|
||||
}
|
||||
|
||||
if (sdp_offset > 0) {
|
||||
void* target = reinterpret_cast<void*>(base_addr + sdp_offset);
|
||||
LOGI("Hooking BTA_DmSetLocalDiRecord at offset: 0x%x, base: %p, target: %p",
|
||||
sdp_offset, (void*)base_addr, target);
|
||||
|
||||
int result = hook_func(target, (void*)fake_BTA_DmSetLocalDiRecord, (void**)&original_BTA_DmSetLocalDiRecord);
|
||||
if (result != 0) {
|
||||
LOGE("Failed to hook BTA_DmSetLocalDiRecord, error: %d", result);
|
||||
} else {
|
||||
LOGI("Successfully hooked BTA_DmSetLocalDiRecord (SDP)");
|
||||
}
|
||||
} else {
|
||||
LOGI("Skipping BTA_DmSetLocalDiRecord hook as sdp offset is not available");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,3 +26,25 @@ uintptr_t loadL2cuProcessCfgReqOffset();
|
||||
uintptr_t loadL2cCsmConfigOffset();
|
||||
uintptr_t loadL2cuSendPeerInfoReqOffset();
|
||||
bool findAndHookFunction(const char *library_path);
|
||||
|
||||
#define SDP_MAX_ATTR_LEN 400
|
||||
|
||||
typedef struct t_sdp_di_record {
|
||||
uint16_t vendor;
|
||||
uint16_t vendor_id_source;
|
||||
uint16_t product;
|
||||
uint16_t version;
|
||||
bool primary_record;
|
||||
char client_executable_url[SDP_MAX_ATTR_LEN];
|
||||
char service_description[SDP_MAX_ATTR_LEN];
|
||||
char documentation_url[SDP_MAX_ATTR_LEN];
|
||||
} tSDP_DI_RECORD;
|
||||
|
||||
typedef enum : uint8_t {
|
||||
BTA_SUCCESS = 0, /* Successful operation. */
|
||||
BTA_FAILURE = 1, /* Generic failure. */
|
||||
BTA_PENDING = 2, /* API cannot be completed right now */
|
||||
BTA_BUSY = 3,
|
||||
BTA_NO_RESOURCES = 4,
|
||||
BTA_WRONG_MODE = 5,
|
||||
} tBTA_STATUS;
|
||||
Reference in New Issue
Block a user