Skip to content

Commit 86551be

Browse files
committed
android: add accessibility stuff
adds option for customizing transparency mode, amplification, tone, etc.
1 parent 802c2e0 commit 86551be

9 files changed

Lines changed: 1430 additions & 129 deletions

File tree

android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@
9090

9191
<category android:name="android.intent.category.LAUNCHER" />
9292
</intent-filter>
93-
<intent-filter android:autoVerify="true">
93+
<!-- <intent-filter android:autoVerify="true">
9494
<action android:name="android.intent.action.VIEW" />
9595
<category android:name="android.intent.category.DEFAULT" />
9696
<category android:name="android.intent.category.BROWSABLE" />
9797
<data android:scheme="librepods"
9898
android:host="add-magic-keys" />
99-
</intent-filter>
99+
</intent-filter> -->
100100
</activity>
101101

102102
<activity

android/app/src/main/cpp/l2c_fcr_hook.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <string>
2525
#include <sys/system_properties.h>
2626
#include "l2c_fcr_hook.h"
27+
#include <cerrno>
28+
#include <cstdlib>
2729

2830
#define LOG_TAG "AirPodsHook"
2931
#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
126128
static void (*original_l2c_csm_config)(tL2C_CCB* p_ccb, uint8_t event, void* p_data) = nullptr;
127129
static void (*original_l2cu_send_peer_info_req)(tL2C_LCB* p_lcb, uint16_t info_type) = nullptr;
128130

131+
// Add original pointer for BTA_DmSetLocalDiRecord
132+
static tBTA_STATUS (*original_BTA_DmSetLocalDiRecord)(tSDP_DI_RECORD* p_device_info, uint32_t* p_handle) = nullptr;
133+
129134
uint8_t fake_l2c_fcr_chk_chan_modes(void* p_ccb) {
130135
LOGI("l2c_fcr_chk_chan_modes hooked, returning true.");
131136
return 1;
@@ -156,6 +161,53 @@ void fake_l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
156161
return;
157162
}
158163

164+
// New loader for SDP hook offset (persist.librepods.sdp_offset)
165+
uintptr_t loadSdpOffset() {
166+
const char* property_name = "persist.librepods.sdp_offset";
167+
char value[PROP_VALUE_MAX] = {0};
168+
169+
int len = __system_property_get(property_name, value);
170+
if (len > 0) {
171+
LOGI("Read sdp offset from property: %s", value);
172+
uintptr_t offset;
173+
char* endptr = nullptr;
174+
175+
const char* parse_start = value;
176+
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
177+
parse_start = value + 2;
178+
}
179+
180+
errno = 0;
181+
offset = strtoul(parse_start, &endptr, 16);
182+
183+
if (errno == 0 && endptr != parse_start && *endptr == '\0' && offset > 0) {
184+
LOGI("Parsed sdp offset: 0x%x", offset);
185+
return offset;
186+
}
187+
188+
LOGE("Failed to parse sdp offset from property value: %s", value);
189+
}
190+
191+
LOGI("No sdp offset property present - skipping SDP hook");
192+
return 0;
193+
}
194+
195+
// Fake BTA_DmSetLocalDiRecord: set vendor/vendor_id_source then call original
196+
tBTA_STATUS fake_BTA_DmSetLocalDiRecord(tSDP_DI_RECORD* p_device_info, uint32_t* p_handle) {
197+
LOGI("BTA_DmSetLocalDiRecord hooked - forcing vendor fields");
198+
if (p_device_info) {
199+
p_device_info->vendor = 0x004C;
200+
p_device_info->vendor_id_source = 0x0001;
201+
}
202+
LOGI("Set vendor=0x%04x, vendor_id_source=0x%04x", p_device_info->vendor, p_device_info->vendor_id_source);
203+
if (original_BTA_DmSetLocalDiRecord) {
204+
return original_BTA_DmSetLocalDiRecord(p_device_info, p_handle);
205+
}
206+
207+
LOGE("Original BTA_DmSetLocalDiRecord not available");
208+
return BTA_FAILURE;
209+
}
210+
159211
uintptr_t loadHookOffset([[maybe_unused]] const char* package_name) {
160212
const char* property_name = "persist.librepods.hook_offset";
161213
char value[PROP_VALUE_MAX] = {0};
@@ -320,6 +372,7 @@ bool findAndHookFunction(const char *library_name) {
320372
uintptr_t l2cu_process_our_cfg_req_offset = loadL2cuProcessCfgReqOffset();
321373
uintptr_t l2c_csm_config_offset = loadL2cCsmConfigOffset();
322374
uintptr_t l2cu_send_peer_info_req_offset = loadL2cuSendPeerInfoReqOffset();
375+
uintptr_t sdp_offset = loadSdpOffset();
323376

324377
bool success = false;
325378

@@ -392,6 +445,21 @@ bool findAndHookFunction(const char *library_name) {
392445
LOGI("Skipping l2cu_send_peer_info_req hook as offset is not available");
393446
}
394447

448+
if (sdp_offset > 0) {
449+
void* target = reinterpret_cast<void*>(base_addr + sdp_offset);
450+
LOGI("Hooking BTA_DmSetLocalDiRecord at offset: 0x%x, base: %p, target: %p",
451+
sdp_offset, (void*)base_addr, target);
452+
453+
int result = hook_func(target, (void*)fake_BTA_DmSetLocalDiRecord, (void**)&original_BTA_DmSetLocalDiRecord);
454+
if (result != 0) {
455+
LOGE("Failed to hook BTA_DmSetLocalDiRecord, error: %d", result);
456+
} else {
457+
LOGI("Successfully hooked BTA_DmSetLocalDiRecord (SDP)");
458+
}
459+
} else {
460+
LOGI("Skipping BTA_DmSetLocalDiRecord hook as sdp offset is not available");
461+
}
462+
395463
return success;
396464
}
397465

android/app/src/main/cpp/l2c_fcr_hook.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,25 @@ uintptr_t loadL2cuProcessCfgReqOffset();
2626
uintptr_t loadL2cCsmConfigOffset();
2727
uintptr_t loadL2cuSendPeerInfoReqOffset();
2828
bool findAndHookFunction(const char *library_path);
29+
30+
#define SDP_MAX_ATTR_LEN 400
31+
32+
typedef struct t_sdp_di_record {
33+
uint16_t vendor;
34+
uint16_t vendor_id_source;
35+
uint16_t product;
36+
uint16_t version;
37+
bool primary_record;
38+
char client_executable_url[SDP_MAX_ATTR_LEN];
39+
char service_description[SDP_MAX_ATTR_LEN];
40+
char documentation_url[SDP_MAX_ATTR_LEN];
41+
} tSDP_DI_RECORD;
42+
43+
typedef enum : uint8_t {
44+
BTA_SUCCESS = 0, /* Successful operation. */
45+
BTA_FAILURE = 1, /* Generic failure. */
46+
BTA_PENDING = 2, /* API cannot be completed right now */
47+
BTA_BUSY = 3,
48+
BTA_NO_RESOURCES = 4,
49+
BTA_WRONG_MODE = 5,
50+
} tBTA_STATUS;

0 commit comments

Comments
 (0)