4
4
#include < dlfcn.h>
5
5
#include < cstring>
6
6
#include < android/log_macros.h>
7
+ #include < bits/timespec.h>
8
+ #include " helpers.h"
7
9
8
10
extern void *libaudioclient_handle;
9
11
extern void *libpermission_handle;
10
12
extern void *libandroid_runtime_handle;
13
+ extern void *libutils_handle;
11
14
extern bool initLib (JNIEnv *env);
12
15
16
+ typedef void *(*ZN7android7RefBaseC2Ev_t)(void * thisptr);
17
+ static ZN7android7RefBaseC2Ev_t ZN7android7RefBaseC2Ev = nullptr ;
18
+ typedef void *(*ZN7android7RefBaseD2Ev_t)(void * thisptr);
19
+ static ZN7android7RefBaseD2Ev_t ZN7android7RefBaseD2Ev = nullptr ;
20
+ #include " aosp_stubs.h"
13
21
typedef void *(*ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject_t)(_JNIEnv*, _jobject*);
14
22
static ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject_t ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject = nullptr ;
15
23
typedef int32_t (*ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE_t)(void * thisptr, void * parcel);
@@ -18,92 +26,152 @@ typedef void*(*ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE_t
18
26
static ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE_t ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE = nullptr ;
19
27
typedef void *(*ZN7android10AudioTrackC1Ev_t)(void * thisptr);
20
28
static ZN7android10AudioTrackC1Ev_t ZN7android10AudioTrackC1Ev = nullptr ;
29
+ typedef void (*ZNK7android7RefBase9incStrongEPKv_t)(void * thisptr, void * id);
30
+ static ZNK7android7RefBase9incStrongEPKv_t ZNK7android7RefBase9incStrongEPKv = nullptr ;
31
+ typedef void (*ZNK7android7RefBase9decStrongEPKv_t)(void * thisptr, void * id);
32
+ static ZNK7android7RefBase9decStrongEPKv_t ZNK7android7RefBase9decStrongEPKv = nullptr ;
33
+ typedef void *(*ZNK7android7RefBase10createWeakEPKv_t)(void * thisptr, void * id);
34
+ static ZNK7android7RefBase10createWeakEPKv_t ZNK7android7RefBase10createWeakEPKv = nullptr ;
35
+ typedef void (*ZN7android7RefBase12weakref_type7decWeakEPKv_t)(void * thisptr, void * id);
36
+ static ZN7android7RefBase12weakref_type7decWeakEPKv_t ZN7android7RefBase12weakref_type7decWeakEPKv = nullptr ;
37
+ typedef int32_t (*ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi_t)
38
+ (void * thisptr, int32_t streamType, uint32_t sampleRate, uint32_t format, uint32_t channelMask, size_t frameCount /* = 0 */ , uint32_t flags /* = 0 */ , fake_wp callback /* = nullptr */ , int32_t notificationFrames /* = 0 */ , fake_sp sharedMemory /* = nullptr */ , bool threadCanCallJava /* = false */ , int32_t audioSessionId /* = 0 */ , transfer_type transferType /* = TRANSFER_DEFAULT */ , void * offloadInfo /* = nullptr */ , void * attributionSource, void * attributes /* = nullptr */ , bool doNotReconnect /* = false */ , float maxRequiredSpeed /* = 1.0f */ , int selectedDeviceId /* = 0 */ );
39
+ static ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi_t ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi = nullptr ;
21
40
22
- // last observed AOSP size (arm64) was 1312
23
- #define AUDIO_TRACK_SIZE 5000
24
- // last observed AOSP size (arm64) was 152
25
- #define ATTRIBUTION_SOURCE_SIZE 500
26
- #define FAKE_PTR_SIZE 32
41
+ /* class MyCallback : virtual android::AudioTrack::IAudioTrackCallback {
42
+ public:
43
+ MyCallback() : RefBase() {};
44
+ void onUnderrun() override {
45
+ ALOGI("MyCallback::onMoreData called");
46
+ }
47
+ void onMarker(uint32_t markerPosition) override {
48
+ ALOGI("MyCallback::onMarker called");
49
+ }
50
+ void onNewPos(uint32_t newPos) override {
51
+ ALOGI("MyCallback::onNewPos called");
52
+ }
53
+ void onNewIAudioTrack() override {
54
+ ALOGI("MyCallback::onNewIAudioTrack called");
55
+ }
56
+ void onStreamEnd() override {
57
+ ALOGI("MyCallback::onStreamEnd called");
58
+ }
59
+ };*/
27
60
28
- // make sure to call RefBase::incStrong on thePtr before giving fake_sp away, and call
29
- // decStrong when you don't need it anymore :)
30
- struct fake_sp {
31
- void * thePtr;
32
- };
33
- // make sure to call RefBase::createWeak(thePtr, <arbitrary unique id>) and save returned pointer
34
- // to refs, then call RefBase::weakref_type::decWeak(refs) when you don't need it anymore
35
- struct fake_wp {
36
- void * thePtr;
37
- void * refs;
61
+ struct track_holder {
62
+ void * track;
63
+ void * callback;
64
+ void * ats;
38
65
};
39
66
67
+ extern " C" JNIEXPORT jboolean JNICALL
68
+ Java_org_akanework_gramophone_logic_utils_NativeTrack_initDlsym (JNIEnv* env, jobject) {
69
+ if (!initLib (env))
70
+ return false ;
71
+ if (android_get_device_api_level () >= 31 ) {
72
+ DLSYM_OR_RETURN (libandroid_runtime, ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject, false )
73
+ DLSYM_OR_RETURN (libpermission, ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE, false )
74
+ DLSYM_OR_RETURN (libaudioclient, ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE, false )
75
+ } else {
76
+ DLSYM_OR_RETURN (libaudioclient, ZN7android10AudioTrackC1Ev, false )
77
+ }
78
+ DLSYM_OR_RETURN (libutils, ZN7android7RefBaseC2Ev, false )
79
+ DLSYM_OR_RETURN (libutils, ZN7android7RefBaseD2Ev, false )
80
+ DLSYM_OR_RETURN (libutils, ZNK7android7RefBase9incStrongEPKv, false )
81
+ DLSYM_OR_RETURN (libutils, ZNK7android7RefBase9decStrongEPKv, false )
82
+ DLSYM_OR_RETURN (libutils, ZNK7android7RefBase10createWeakEPKv, false )
83
+ DLSYM_OR_RETURN (libutils, ZN7android7RefBase12weakref_type7decWeakEPKv, false )
84
+ // TODO support all 5 gazillion variants of set()
85
+ if (ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi == nullptr ) {
86
+ ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi =
87
+ (ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi_t)
88
+ dlsym (libaudioclient_handle, " _ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi" );
89
+ if (ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi == nullptr ) {
90
+ ALOGE (" dlsym returned nullptr for _ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi: %s" ,
91
+ dlerror ());
92
+ return false ;
93
+ }
94
+ }
95
+ return true ;
96
+ }
97
+
40
98
extern " C" JNIEXPORT jlong JNICALL
41
99
Java_org_akanework_gramophone_logic_utils_NativeTrack_create (
42
100
JNIEnv *env, jobject, jobject parcel) {
43
- if (!initLib (env))
44
- return NULL ;
45
101
auto theTrack = ::operator new (AUDIO_TRACK_SIZE);
46
- memset (theTrack, 0 , AUDIO_TRACK_SIZE);
102
+ memset (theTrack, 0xdeadbeef , AUDIO_TRACK_SIZE);
103
+ auto holder = new track_holder ();
47
104
if (parcel != nullptr ) { // implies SDK >= 31
48
- auto ats = ::operator new (ATTRIBUTION_SOURCE_SIZE);
49
- memset (ats, 0 , ATTRIBUTION_SOURCE_SIZE);
50
- if (!ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject) {
51
- ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject =
52
- (ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject_t)
53
- dlsym (libandroid_runtime_handle," _ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject" );
54
- if (ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject == nullptr ) {
55
- ALOGE (" dlsym returned nullptr for _ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject: %s" ,
56
- dlerror ());
57
- return NULL ;
58
- }
59
- }
105
+ // I'm too cool to call AttributionSourceState ctor before using it.
60
106
auto myParcel = ZN7android19parcelForJavaObjectEP7_JNIEnvP8_jobject (env, parcel);
61
107
if (myParcel == nullptr ) {
62
108
ALOGE (" myParcel is NULL" );
109
+ ::operator delete (theTrack);
63
110
return NULL ;
64
111
}
65
- if (!ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE) {
66
- ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE =
67
- (ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE_t)
68
- dlsym (libpermission_handle," _ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE" );
69
- if (ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE == nullptr ) {
70
- ALOGE (" dlsym returned nullptr for _ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE: %s" ,
71
- dlerror ());
72
- return NULL ;
73
- }
74
- }
75
- // I'm too cool to call AttributionSourceState ctor before using it.
112
+ auto ats = ::operator new (ATTRIBUTION_SOURCE_SIZE);
113
+ memset (ats, 0 , ATTRIBUTION_SOURCE_SIZE);
76
114
ZN7android7content22AttributionSourceState14readFromParcelEPKNS_6ParcelE (ats, myParcel);
77
- if (!ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE) {
78
- ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE =
79
- (ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE_t)
80
- dlsym (libaudioclient_handle," _ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE" );
81
- if (ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE == nullptr ) {
82
- ALOGE (" dlsym returned nullptr for _ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE: %s" ,
83
- dlerror ());
84
- return NULL ;
85
- }
86
- }
87
115
ZN7android10AudioTrackC1ERKNS_7content22AttributionSourceStateE (theTrack, ats);
88
- ::operator delete (ats); // copied by AudioTrack ctor
116
+ // ZN7android7RefBaseC2Ev(theTrack); // TODO
117
+ holder->ats = ats;
89
118
} else {
90
- if (!ZN7android10AudioTrackC1Ev) {
91
- ZN7android10AudioTrackC1Ev = (ZN7android10AudioTrackC1Ev_t)
92
- dlsym (libaudioclient_handle," _ZN7android10AudioTrackC1Ev" );
93
- if (ZN7android10AudioTrackC1Ev == nullptr ) {
94
- ALOGE (" dlsym returned nullptr for _ZN7android10AudioTrackC1Ev: %s" ,
95
- dlerror ());
96
- return NULL ;
97
- }
98
- }
99
119
ZN7android10AudioTrackC1Ev (theTrack);
100
120
}
101
- return (intptr_t )theTrack;
121
+ ALOGE (" 0" );
122
+ auto callback = nullptr ;// new MyCallback();
123
+ // ZN7android7RefBaseC2Ev(callback); // TODO
124
+ ALOGE (" 1" );
125
+ ZNK7android7RefBase9incStrongEPKv (theTrack, holder);
126
+ ALOGE (" 2" );
127
+ // ZNK7android7RefBase9incStrongEPKv(callback, holder);
128
+ ALOGE (" 3" );
129
+ holder->track = theTrack;
130
+ holder->callback = callback;
131
+ return (intptr_t )holder;
102
132
}
103
133
104
134
extern " C" JNIEXPORT jint JNICALL
105
135
Java_org_akanework_gramophone_logic_utils_NativeTrack_doSet (
106
- JNIEnv *env, jobject, jlong ptr) {
107
- // TODO support all 5 gazillion variants of set()
136
+ JNIEnv *, jobject, jlong ptr) {
137
+ return 0 ;
138
+ auto holder = (track_holder*) ptr;
139
+ auto refs = ZNK7android7RefBase10createWeakEPKv (holder->callback , holder);
140
+ auto ret = ZN7android10AudioTrack3setE19audio_stream_type_tj14audio_format_t20audio_channel_mask_tm20audio_output_flags_tRKNS_2wpINS0_19IAudioTrackCallbackEEEiRKNS_2spINS_7IMemoryEEEb15audio_session_tNS0_13transfer_typeEPK20audio_offload_info_tRKNS_7content22AttributionSourceStateEPK18audio_attributes_tbfi (
141
+ holder->track ,
142
+ /* streamType = */ 3 /* AUDIO_STREAM_MUSIC */ ,
143
+ /* sampleRate = */ 13370 ,
144
+ /* format = */ 1 ,
145
+ /* channelMask = */ 1 ,
146
+ /* frameCount = */ 0 /* default */ ,
147
+ /* flags = */ 0 /* AUDIO_OUTPUT_FLAG_NONE */ ,
148
+ /* callback = */ { .thePtr = holder->callback , .refs = refs },
149
+ /* notificationFrames = */ 0 /* default */ ,
150
+ /* sharedBuffer = */ { .thePtr = nullptr },
151
+ /* threadCanCallJava = */ true ,
152
+ /* sessionId = */ 0 /* default */ ,
153
+ /* transferType = */ TRANSFER_SYNC,
154
+ /* offloadInfo = */ nullptr ,
155
+ /* attributionSource = */ holder->ats ,
156
+ /* pAttributes = */ nullptr ,
157
+ /* doNotReconnect = */ true , // for emulating DIRECT track developer UX
158
+ /* maxRequiredSpeed = */ 1 .0f ,
159
+ /* selectedDeviceId = */ 0 /* default */
160
+ );
161
+ // wp copy constructor increased weak with it's own id, so we're done here
162
+ ZN7android7RefBase12weakref_type7decWeakEPKv (refs /* yes, refs */ , holder);
163
+ // we own attributionSource, so get rid of it
164
+ ::operator delete (holder->ats );
165
+ holder->ats = nullptr ;
166
+ return ret;
167
+ }
108
168
169
+ extern " C" JNIEXPORT void JNICALL
170
+ Java_org_akanework_gramophone_logic_utils_NativeTrack_dtor (
171
+ JNIEnv *, jobject, jlong ptr) {
172
+ auto holder = (track_holder*) ptr;
173
+ // RefBase will call the dtor
174
+ ZNK7android7RefBase9decStrongEPKv (holder->track , holder);
175
+ ZNK7android7RefBase9decStrongEPKv (holder->callback , holder);
176
+ delete holder;
109
177
}
0 commit comments