1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "berberis/native_activity/native_activity_wrapper.h"
18
19 #include <stddef.h>
20 #include <string.h>
21
22 #include "android/input.h"
23 #include "android/native_activity.h"
24 #include "android/native_window_jni.h"
25 #include "android/rect.h"
26 #include "berberis/guest_abi/function_wrappers.h"
27 #include "berberis/guest_abi/guest_arguments.h"
28 #include "berberis/guest_abi/guest_call.h"
29 #include "berberis/jni/jni_trampolines.h"
30 #include "berberis/native_activity/native_activity.h"
31
32 namespace berberis {
33
34 namespace {
35
ToGuestNativeActivity(ANativeActivity * activity)36 Guest_ANativeActivity* ToGuestNativeActivity(ANativeActivity* activity) {
37 return reinterpret_cast<Guest_ANativeActivity*>(activity->instance);
38 }
39
GetGuestCallbacks(Guest_ANativeActivity * activity)40 Guest_ANativeActivityCallbacks* GetGuestCallbacks(Guest_ANativeActivity* activity) {
41 return ToHostAddr<Guest_ANativeActivityCallbacks>(activity->callbacks);
42 }
43
AllocGuestNativeActivity()44 Guest_ANativeActivity* AllocGuestNativeActivity() {
45 Guest_ANativeActivity* guest_activity = new Guest_ANativeActivity;
46 Guest_ANativeActivityCallbacks* guest_callbacks = new Guest_ANativeActivityCallbacks;
47 memset(guest_callbacks, 0, sizeof(*guest_callbacks));
48 guest_activity->callbacks = ToGuestAddr(guest_callbacks);
49 return guest_activity;
50 }
51
FreeGuestNativeActivity(Guest_ANativeActivity * guest_activity)52 void FreeGuestNativeActivity(Guest_ANativeActivity* guest_activity) {
53 delete GetGuestCallbacks(guest_activity);
54 delete guest_activity;
55 }
56
Wrap_OnStart(ANativeActivity * activity)57 void Wrap_OnStart(ANativeActivity* activity) {
58 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
59 GuestAddr func = GetGuestCallbacks(guest_activity)->onStart;
60 if (func == 0) {
61 return;
62 }
63 GuestCall call;
64 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
65 call.RunVoid(func);
66 }
67
Wrap_OnResume(ANativeActivity * activity)68 void Wrap_OnResume(ANativeActivity* activity) {
69 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
70 GuestAddr func = GetGuestCallbacks(guest_activity)->onResume;
71 if (func == 0) {
72 return;
73 }
74 GuestCall call;
75 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
76 call.RunVoid(func);
77 }
78
Wrap_OnSaveInstanceState(ANativeActivity * activity,size_t * outSize)79 void* Wrap_OnSaveInstanceState(ANativeActivity* activity, size_t* outSize) {
80 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
81 GuestAddr func = GetGuestCallbacks(guest_activity)->onSaveInstanceState;
82 if (func == 0) {
83 return nullptr;
84 }
85 GuestCall call;
86 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
87 call.AddArgGuestAddr(ToGuestAddr(outSize));
88 return ToHostAddr<void>(call.RunResGuestAddr(func));
89 }
90
Wrap_OnPause(ANativeActivity * activity)91 void Wrap_OnPause(ANativeActivity* activity) {
92 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
93 GuestAddr func = GetGuestCallbacks(guest_activity)->onPause;
94 if (func == 0) {
95 return;
96 }
97 GuestCall call;
98 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
99 call.RunVoid(func);
100 }
101
Wrap_OnStop(ANativeActivity * activity)102 void Wrap_OnStop(ANativeActivity* activity) {
103 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
104 GuestAddr func = GetGuestCallbacks(guest_activity)->onStop;
105 if (func == 0) {
106 return;
107 }
108 GuestCall call;
109 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
110 call.RunVoid(func);
111 }
112
Wrap_OnDestroy(ANativeActivity * activity)113 void Wrap_OnDestroy(ANativeActivity* activity) {
114 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
115 GuestAddr func = GetGuestCallbacks(guest_activity)->onDestroy;
116 if (func != 0) {
117 GuestCall call;
118 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
119 call.RunVoid(func);
120 }
121 activity->instance = nullptr;
122 FreeGuestNativeActivity(guest_activity);
123 }
124
Wrap_OnWindowFocusChanged(ANativeActivity * activity,int hasFocus)125 void Wrap_OnWindowFocusChanged(ANativeActivity* activity, int hasFocus) {
126 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
127 GuestAddr func = GetGuestCallbacks(guest_activity)->onWindowFocusChanged;
128 if (func == 0) {
129 return;
130 }
131 GuestCall call;
132 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
133 call.AddArgInt32(hasFocus);
134 call.RunVoid(func);
135 }
136
Wrap_OnNativeWindowCreated(ANativeActivity * activity,ANativeWindow * window)137 void Wrap_OnNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
138 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
139 GuestAddr func = GetGuestCallbacks(guest_activity)->onNativeWindowCreated;
140 if (func == 0) {
141 return;
142 }
143 GuestCall call;
144 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
145 call.AddArgGuestAddr(ToGuestAddr(window));
146 call.RunVoid(func);
147 }
148
Wrap_OnNativeWindowResized(ANativeActivity * activity,ANativeWindow * window)149 void Wrap_OnNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
150 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
151 GuestAddr func = GetGuestCallbacks(guest_activity)->onNativeWindowResized;
152 if (func == 0) {
153 return;
154 }
155 GuestCall call;
156 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
157 call.AddArgGuestAddr(ToGuestAddr(window));
158 call.RunVoid(func);
159 }
160
Wrap_OnNativeWindowRedrawNeeded(ANativeActivity * activity,ANativeWindow * window)161 void Wrap_OnNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
162 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
163 GuestAddr func = GetGuestCallbacks(guest_activity)->onNativeWindowRedrawNeeded;
164 if (func == 0) {
165 return;
166 }
167 GuestCall call;
168 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
169 call.AddArgGuestAddr(ToGuestAddr(window));
170 call.RunVoid(func);
171 }
172
Wrap_OnNativeWindowDestroyed(ANativeActivity * activity,ANativeWindow * window)173 void Wrap_OnNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
174 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
175 GuestAddr func = GetGuestCallbacks(guest_activity)->onNativeWindowDestroyed;
176 if (func == 0) {
177 return;
178 }
179 GuestCall call;
180 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
181 call.AddArgGuestAddr(ToGuestAddr(window));
182 call.RunVoid(func);
183 }
184
Wrap_OnInputQueueCreated(ANativeActivity * activity,AInputQueue * queue)185 void Wrap_OnInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
186 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
187 GuestAddr func = GetGuestCallbacks(guest_activity)->onInputQueueCreated;
188 if (func == 0) {
189 return;
190 }
191 GuestCall call;
192 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
193 call.AddArgGuestAddr(ToGuestAddr(queue));
194 call.RunVoid(func);
195 }
196
Wrap_OnInputQueueDestroyed(ANativeActivity * activity,AInputQueue * queue)197 void Wrap_OnInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
198 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
199 GuestAddr func = GetGuestCallbacks(guest_activity)->onInputQueueDestroyed;
200 if (func == 0) {
201 return;
202 }
203 GuestCall call;
204 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
205 call.AddArgGuestAddr(ToGuestAddr(queue));
206 call.RunVoid(func);
207 }
208
Wrap_OnContentRectChanged(ANativeActivity * activity,const ARect * rect)209 void Wrap_OnContentRectChanged(ANativeActivity* activity, const ARect* rect) {
210 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
211 GuestAddr func = GetGuestCallbacks(guest_activity)->onContentRectChanged;
212 if (func == 0) {
213 return;
214 }
215 GuestCall call;
216 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
217 call.AddArgGuestAddr(ToGuestAddr(const_cast<ARect*>(rect)));
218 call.RunVoid(func);
219 }
220
Wrap_OnConfigurationChanged(ANativeActivity * activity)221 void Wrap_OnConfigurationChanged(ANativeActivity* activity) {
222 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
223 GuestAddr func = GetGuestCallbacks(guest_activity)->onConfigurationChanged;
224 if (func == 0) {
225 return;
226 }
227 GuestCall call;
228 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
229 call.RunVoid(func);
230 }
231
Wrap_OnLowMemory(ANativeActivity * activity)232 void Wrap_OnLowMemory(ANativeActivity* activity) {
233 Guest_ANativeActivity* guest_activity = ToGuestNativeActivity(activity);
234 GuestAddr func = GetGuestCallbacks(guest_activity)->onLowMemory;
235 if (func == 0) {
236 return;
237 }
238 GuestCall call;
239 call.AddArgGuestAddr(ToGuestAddr(guest_activity));
240 call.RunVoid(func);
241 }
242
WrapNativeActivityCallbacks(ANativeActivity * activity)243 void WrapNativeActivityCallbacks(ANativeActivity* activity) {
244 ANativeActivityCallbacks* callbacks = activity->callbacks;
245 callbacks->onStart = Wrap_OnStart;
246 callbacks->onResume = Wrap_OnResume;
247 callbacks->onSaveInstanceState = Wrap_OnSaveInstanceState;
248 callbacks->onPause = Wrap_OnPause;
249 callbacks->onStop = Wrap_OnStop;
250 callbacks->onDestroy = Wrap_OnDestroy;
251 callbacks->onWindowFocusChanged = Wrap_OnWindowFocusChanged;
252 callbacks->onNativeWindowCreated = Wrap_OnNativeWindowCreated;
253 callbacks->onNativeWindowResized = Wrap_OnNativeWindowResized;
254 callbacks->onNativeWindowRedrawNeeded = Wrap_OnNativeWindowRedrawNeeded;
255 callbacks->onNativeWindowDestroyed = Wrap_OnNativeWindowDestroyed;
256 callbacks->onInputQueueCreated = Wrap_OnInputQueueCreated;
257 callbacks->onInputQueueDestroyed = Wrap_OnInputQueueDestroyed;
258 callbacks->onContentRectChanged = Wrap_OnContentRectChanged;
259 callbacks->onConfigurationChanged = Wrap_OnConfigurationChanged;
260 callbacks->onLowMemory = Wrap_OnLowMemory;
261 }
262
263 // Call Native Activity creation function. If it has a different architecture,
264 // we pass a copy of ANativeActivity to the function. The real Native Activity
265 // callbacks are filled with wrappers that call real functions.
CreateGuestNativeActivity(GuestAddr on_create,ANativeActivity * activity,void * saved,size_t saved_size)266 void CreateGuestNativeActivity(GuestAddr on_create,
267 ANativeActivity* activity,
268 void* saved,
269 size_t saved_size) {
270 // Create a copy of ANativeActivity that will be passed to the guest function.
271 Guest_ANativeActivity* guest_activity = AllocGuestNativeActivity();
272 // This field is reserved for arbitrary application usage. Since we don't
273 // pass pointer to real ANativeActivity to the application, we can use this
274 // field for our purposes.
275 activity->instance = guest_activity;
276 guest_activity->host_native_activity = activity;
277 guest_activity->vm = ToGuestJavaVM(activity->vm);
278 guest_activity->env = ToGuestJNIEnv(activity->env);
279 guest_activity->externalDataPath = ToGuestAddr(const_cast<char*>(activity->externalDataPath));
280 guest_activity->internalDataPath = ToGuestAddr(const_cast<char*>(activity->internalDataPath));
281 guest_activity->sdkVersion = activity->sdkVersion;
282 guest_activity->activity = activity->clazz;
283 guest_activity->assetManager = ToGuestAddr(activity->assetManager);
284 guest_activity->obbPath = ToGuestAddr(activity->obbPath);
285 GuestCall guest_call;
286 guest_call.AddArgGuestAddr(ToGuestAddr(guest_activity));
287 guest_call.AddArgGuestAddr(ToGuestAddr(saved));
288 guest_call.AddArgGuestSize(saved_size);
289 guest_call.RunVoid(on_create);
290
291 // Real callbacks are filled with wrappers.
292 WrapNativeActivityCallbacks(activity);
293 }
294
295 // void ANativeActivity_createFunc(
296 // ANativeActivity* activity, void* savedState, size_t savedStateSize);
RunGuestNativeActivityOnCreate(GuestAddr pc,GuestArgumentBuffer * buf)297 void RunGuestNativeActivityOnCreate(GuestAddr pc, GuestArgumentBuffer* buf) {
298 auto&& [activity, saved_state, saved_state_size] =
299 GuestArgumentsReferences<ANativeActivity_createFunc>(buf);
300 CreateGuestNativeActivity(pc, activity, saved_state, saved_state_size);
301 }
302
303 } // namespace
304
WrapGuestNativeActivityOnCreate(GuestAddr pc)305 HostCode WrapGuestNativeActivityOnCreate(GuestAddr pc) {
306 return WrapGuestFunctionImpl(pc,
307 kGuestFunctionWrapperSignature<ANativeActivity_createFunc>,
308 RunGuestNativeActivityOnCreate,
309 "ANativeActivity_onCreate");
310 }
311
312 } // namespace berberis
313