android_native_app_glue.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * © 2010 The Android Open Source Project
  3. *
  4. * Лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия");
  5. *этот файл можно использовать только в соответствии с лицензией.
  6. *Копию лицензии можно получить на веб-сайте
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение
  11. * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ",
  12. * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых.
  13. * См. лицензию для получения информации об определенных разрешениях по использованию языка и
  14. * ограничениях в рамках лицензии.
  15. *
  16. */
  17. #ifndef _ANDROID_NATIVE_APP_GLUE_H
  18. #define _ANDROID_NATIVE_APP_GLUE_H
  19. #include <poll.h>
  20. #include <pthread.h>
  21. #include <sched.h>
  22. #include <android/configuration.h>
  23. #include <android/looper.h>
  24. #include <android/native_activity.h>
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28. /**
  29. * Интерфейс NativeActivity, предоставленный <android/native_activity.h>,
  30. * основан на наборе предоставленных приложением обратных вызовов, которые вызываются
  31. *основным потоком действия при возникновении определенных событий.
  32. *
  33. * Это означает, что ни один из данных обратных вызовов _не_ _должен_ блокироваться, иначе
  34. * существует риск принудительного закрытия приложения системой. Эта модель программирования
  35. * прямая, простая, но имеет ограничения.
  36. *
  37. * Статическая библиотека threaded_native_app используется для обеспечения другой
  38. * модели выполнения, в которой приложение может реализовать свой собственный цикл главного события
  39. * в другом потоке вместо этого. Это работает так:
  40. *
  41. * 1/ Приложение должно предоставить функцию с именем android_main(), которая
  42. * будет вызываться при создании действия в новом потоке,
  43. * отличающемся от основного потока действия.
  44. *
  45. * 2/ android_main() получает указатель на допустимую структуру android_app,
  46. * которая содержит ссылки на другие важные объекты, например экземпляр объекта
  47. * ANativeActivity, где выполняется приложение.
  48. *
  49. * 3/ Объект android_app содержит экземпляр ALooper, который уже
  50. * ожидает две важных вещи:
  51. *
  52. * - событий жизненного цикла действия (например, "pause", "resume"). См. объявления APP_CMD_XXX
  53. * ниже.
  54. *
  55. * - входных событий, поступающих из очереди AInputQueue, присоединенной к действию.
  56. *
  57. * Каждое из этих событий соответствует идентификатору ALooper, возвращенному
  58. * ALooper_pollOnce со значениями LOOPER_ID_MAIN и LOOPER_ID_INPUT,
  59. *, соответственно.
  60. *
  61. * Ваше приложение может использовать тот же ALooper для прослушивания дополнительных
  62. * дескрипторов файла. Они могут быть основаны либо на обратных вызовах, либо поступают с идентификаторами возврата,
  63. * начинающимися с LOOPER_ID_USER.
  64. *
  65. * 4/ При получении события LOOPER_ID_MAIN или LOOPER_ID_INPUT
  66. * возвращенные данные будут указывать на структуру android_poll_source. Для нее
  67. * можно вызвать функцию process() и заполнить android_app->onAppCmd
  68. * и android_app->onInputEvent, для того чтобы они вызывались для вашей собственной обработки
  69. * события.
  70. *
  71. * Вместо этого можно вызвать функции нижнего уровня для чтения и обработки
  72. * данных непосредственно... посмотрите на реализации process_cmd() и process_input()
  73. * в приклеивании, чтобы выяснить, как это делается.
  74. *
  75. * См. пример "native-activity" в NDK с
  76. * полной демонстрацией использования. Также посмотрите JavaDoc в NativeActivity.
  77. */
  78. struct android_app;
  79. /**
  80. * Данные, связанные с ALooper fd, которые будут возвращаться как outData
  81. * при готовности данных в этом источнике.
  82. */
  83. struct android_poll_source {
  84. // Идентификатор данного источника. Может быть LOOPER_ID_MAIN или
  85. // LOOPER_ID_INPUT.
  86. int32_t id;
  87. // android_app, с которым связан данный идентификатор.
  88. struct android_app* app;
  89. // Функция, вызываемая для стандартной обработки данных из
  90. // этого источника.
  91. void (*process)(struct android_app* app, struct android_poll_source* source);
  92. };
  93. /**
  94. * Это интерфейс стандартного кода приклеивания поточного
  95. * приложения. В этой модели код приложения выполняется
  96. * в своем собственном потоке, отдельном от основного потока процесса.
  97. * Не требуется связь данного потока с ВМ Java
  98. *, хотя это необходимо для выполнения вызовов JNI любых
  99. * объектов Java.
  100. */
  101. struct android_app {
  102. // Приложение может поместить указатель на свой собственный объект состояния
  103. // здесь, если нужно.
  104. void* userData;
  105. // Введите здесь код функции для обработки основных команд приложения (APP_CMD_*)
  106. void (*onAppCmd)(struct android_app* app, int32_t cmd);
  107. // Введите здесь код функции для обработки входных событий. Сейчас
  108. // событие уже было предварительно отправлено и будет завершено при
  109. // возврате. Верните 1, если событие обработано, 0 — для любой диспетчеризации
  110. // по умолчанию.
  111. int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
  112. // Экземпляр объекта ANativeActivity, в котором выполняется это приложение.
  113. ANativeActivity* activity;
  114. // Текущая конфигурация, в которой выполняется это приложение.
  115. AConfiguration* config;
  116. // Это последнее сохраненное состояние экземпляра, предоставленное во время создания.
  117. // Значение равно NULL, если состояния не было. Можно использовать это по мере необходимости;
  118. // память останется доступной до вызова android_app_exec_cmd() для
  119. // APP_CMD_RESUME, после чего она будет освобождена, а savedState получит значение NULL.
  120. // Эти переменные необходимо изменять только при обработке APP_CMD_SAVE_STATE,
  121. // когда их значения будут инициализироваться в NULL и можно будет выполнить malloc для
  122. // состояния и поместить здесь информацию. В этом случае память будет
  123. // освобождена позднее.
  124. void* savedState;
  125. size_t savedStateSize;
  126. // ALooper, связанный с потоком приложения.
  127. ALooper* looper;
  128. // Если значение не равно NULL, то это входная очередь, из которой приложение будет
  129. // получать входные события пользователя.
  130. AInputQueue* inputQueue;
  131. // Если значение не равно NULL, то это поверхность окна, в котором приложение может рисовать.
  132. ANativeWindow* window;
  133. // Текущий прямоугольник содержимого окна. Это область, в которой
  134. // должно помещаться содержимое окна, чтобы его видел пользователь.
  135. ARect contentRect;
  136. // Текущее состояние действия приложения. Может быть APP_CMD_START,
  137. // APP_CMD_RESUME, APP_CMD_PAUSE или APP_CMD_STOP; см. ниже.
  138. int activityState;
  139. // Значение не равно нулю, когда NativeActivity приложения
  140. // разрушается и ожидает завершения потока приложения.
  141. int destroyRequested;
  142. // -------------------------------------------------
  143. // Ниже показан "частная" реализация кода прилипания.
  144. pthread_mutex_t mutex;
  145. pthread_cond_t cond;
  146. int msgread;
  147. int msgwrite;
  148. pthread_t thread;
  149. struct android_poll_source cmdPollSource;
  150. struct android_poll_source inputPollSource;
  151. int running;
  152. int stateSaved;
  153. int destroyed;
  154. int redrawNeeded;
  155. AInputQueue* pendingInputQueue;
  156. ANativeWindow* pendingWindow;
  157. ARect pendingContentRect;
  158. };
  159. enum {
  160. /**
  161. * Идентификатор данных Looper команд, поступающих из основного потока приложения, который
  162. * возвращается как идентификатор от ALooper_pollOnce(). Данные для этого идентификатора
  163. * являются указателем на структуру android_poll_source.
  164. * Их можно извлечь и обработать с помощью android_app_read_cmd()
  165. * и android_app_exec_cmd().
  166. */
  167. LOOPER_ID_MAIN = 1,
  168. /**
  169. * Идентификатор данных Looper событий, поступающий из AInputQueue окна
  170. * приложения, который возвращается как идентификатор из
  171. * ALooper_pollOnce(). Данные этого идентификатора являются указателем на структуру
  172. * android_poll_source. Их можно прочитать через объект inputQueue
  173. * приложения android_app.
  174. */
  175. LOOPER_ID_INPUT = 2,
  176. /**
  177. * Запуск определяемых пользователем идентификаторов ALooper.
  178. */
  179. LOOPER_ID_USER = 3,
  180. };
  181. enum {
  182. /**
  183. * Команда из основного потока: AInputQueue изменена. После обработки
  184. * этой команды android_app->inputQueue будет обновлена в новую очередь
  185. * (или NULL).
  186. */
  187. APP_CMD_INPUT_CHANGED,
  188. /**
  189. * Команда из основного потока: новое окно ANativeWindow готово к использованию. После
  190. * получения этой команды окно android_app-> будет содержать новую поверхность
  191. *окна.
  192. */
  193. APP_CMD_INIT_WINDOW,
  194. /**
  195. * Команда из основного потока: существующее окно ANativeWindow необходимо
  196. * прекратить. После получения этой команды окно android_app->по-прежнему
  197. * содержит существующее окно; после вызова android_app_exec_cmd
  198. * оно получит значение NULL.
  199. */
  200. APP_CMD_TERM_WINDOW,
  201. /**
  202. * Команда из основного потока: текущее окно ANativeWindow изменило размер.
  203. * Перерисуйте согласно новом размеру.
  204. */
  205. APP_CMD_WINDOW_RESIZED,
  206. /**
  207. * Команда из основного потока: системе необходимо, чтобы текущее окно ANativeWindow
  208. * было перерисовано. Необходимо перерисовать окно перед ее передачей в
  209. * android_app_exec_cmd(), чтобы избежать переходных сбоев рисования.
  210. */
  211. APP_CMD_WINDOW_REDRAW_NEEDED,
  212. /**
  213. * Команда из основного потока: область содержимого окна изменена
  214. * таким образом, что из функционального ввода окно показывается или скрывается. Можно
  215. * найти новый прямоугольник содержимого в android_app::contentRect.
  216. */
  217. APP_CMD_CONTENT_RECT_CHANGED,
  218. /**
  219. * Команда из основного потока: окно действия приложения получило
  220. * фокус ввода.
  221. */
  222. APP_CMD_GAINED_FOCUS,
  223. /**
  224. * Команда из основного потока: окно действия приложения потеряло
  225. * фокус ввода.
  226. */
  227. APP_CMD_LOST_FOCUS,
  228. /**
  229. * Команда из основного потока: изменена текущая конфигурация устройства.
  230. */
  231. APP_CMD_CONFIG_CHANGED,
  232. /**
  233. * Команда из основного потока: системе не хватает памяти.
  234. * Попробуйте уменьшить использование памяти.
  235. */
  236. APP_CMD_LOW_MEMORY,
  237. /**
  238. * Команда из основного потока: действие приложения было запущено.
  239. */
  240. APP_CMD_START,
  241. /**
  242. * Команда из основного потока: действие приложения было возобновлено.
  243. */
  244. APP_CMD_RESUME,
  245. /**
  246. * Команда из основного потока: приложение должно создать новое сохраненное состояние
  247. * для себя, чтобы восстанавливаться из него позднее в случае необходимости. Если вы сохранили состояние,
  248. * выделите его с использованием malloc и поместите в android_app.savedState с
  249. * размером android_app.savedStateSize. Память будет освобождена
  250. * позднее.
  251. */
  252. APP_CMD_SAVE_STATE,
  253. /**
  254. * Команда из основного потока: пауза в действии приложения.
  255. */
  256. APP_CMD_PAUSE,
  257. /**
  258. * Команда из основного потока: действие приложения было остановлено.
  259. */
  260. APP_CMD_STOP,
  261. /**
  262. * Команда из основного потока: действие приложения уничтожается,
  263. * и ожидает очистки потока приложения и выхода перед обработкой.
  264. */
  265. APP_CMD_DESTROY,
  266. };
  267. /**
  268. * Вызовите, когда ALooper_pollAll() возвращает LOOPER_ID_MAIN, при чтении следующего сообщения команды
  269. *приложения.
  270. */
  271. int8_t android_app_read_cmd(struct android_app* android_app);
  272. /**
  273. * Вызовите с помощью команды, возвращенной android_app_read_cmd() для выполнения
  274. * начальной предварительной обработки данной команды. Можно выполнить собственные
  275. * действия для команды после вызова этой функции.
  276. */
  277. void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
  278. /**
  279. * Вызовите с помощью команды, возвращенной android_app_read_cmd(), для
  280. * окончательной предварительной обработки данной команды. Необходимо завершить собственные
  281. * действия с командой до вызова этой функции.
  282. */
  283. void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
  284. /**
  285. * Это функция, которую должен реализовать код приложения, представляет собой
  286. * главный вход в приложение.
  287. */
  288. extern void android_main(struct android_app* app);
  289. #ifdef __cplusplus
  290. }
  291. #endif
  292. #endif /* _ANDROID_NATIVE_APP_GLUE_H */