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