Открыть главное меню

Application

Версия от 19:59, 16 февраля 2010; G-XaD (обсуждение | вклад) (упс, ошибочка)

Application - приложение для системы AFW. Приложение это именно то, что взаимодействует с пользователем (драйвера, в отличие от приложений, обычно не взаимодействуют с пользователем, они работают с железом и приложениями или операционной системой).

Приложение для AFW разрабатывалось таким, чтобы работать из ROM'а, поэтому может вообще не иметь глобальных переменных, все данные должны храниться в структуре приложения, в которой первой должна быть структура APPLICATION_T. Указатель на экземпляр текущего приложения передаётся в каждом обработчике событий, из которых по сути и состоит приложение. В приложениях из эльфов немного иначе, как минимум таблица ивентов регистрации должна быть в RAM'е, т.к. база ивентов выделяется динамически. В прошивке коды ивентов назначаются автоматически в процессе компиляции.


Таблица ивентов регистрации

Массив кодов ивентов на которые стартует приложение, регистрируется функция старта. Для эльфов это обычно один единственный ивент код которого записывается в глобальной структуре ldrElf.

Регистрация

Приложение должно быть зарегестрировано в системе AFW, делается это функцией APP_Register. Её параметры:

APP_Register( reg_tbl, // указатель на первый элемент таблицы ивентов регистрации	reg_count, // количество элементов в этой таблице	state_handling_table, // таблица, описывающая все состояния приложения	APP_STATE_MAX, // количество элементов в этой таблице	(void *) AppStart ); // функция старта приложения

Регистрируется приложение один раз и удалить регистрацию потом будет невозможно, а эльф обычно должен выгружаться из памяти, поэтому нужно исключить совпадение ивентов для выгружаемого эльфа, для этого используется функция ldrRequestEventBase, которая каждый раз возвращает уникальный свободный код ивента который можно использовать как "свои" ивенты. Даже более, следующие 63 кода тоже свободны и никогда не встретятся. При регистрации система запоминает не ивенты, а адресс таблицы, а т.к. память эльфа может быть освобождена данные могут быть изменениы и это может быть источником глюков, от этого никуда не деться.

Старт

Функция старта приложения имеет вид:

UINT32 AppStart( EVENT_STACK_T * ev_st, REG_ID_T reg_id, void * reg_hdl );

Параметры:

  • ev_st - указатель на стэк событий.
  • reg_id - идентификатор регистрации приложения. Когда приложение регистрируется оно получает уникальный идентификатор регистрации, по которому его можно найти. По reg_id можно определить что приложение с таким идентификатором уже запущено (см. AFW_InquireRoutingStackByRegId).
  • reg_hdr - структура с данными, которые получены при регистрации приложениями.

В начале можно проверить, вдруг это приложение уже папущено:

if( AFW_InquireRoutingStackByRegId( reg_id ) == RESULT_OK ) {	return RESULT_FAIL;	}

Дальше нужно выделить память под структуру и провести инициализацию AFW приложения функцией APP_InitAppData. Параметры:

Дальше идут несколько уровней приоритета приложения. Очевидно, фоновое приложение имеет высший приоритет и раньше поймает событие в обработчике.
  • =AFW_APP_CENTRICITY_PRIMARY для фоновых, =AFW_APP_CENTRICITY_SECONDARY для приложений с UIS.
  • =AFW_PREPROCESSING для фоновых, =AFW_FOCUS для приложений с UIS.
  • приоритет в стэке приложений. =AFW_POSITION_TOP.

Функция должна указатель на структуру приложения, NULL в случае ошибки. Если функция вернула не NULL, то приложение можно запустить, после чего приложение будет обрабатывать ивенты. Делается это функцией APP_Start. Параметры:

  • указатель на стэк событий.
  • указатель на структуру приложения.
  • индеск первого стэйта, в котором стартует приложение.
  • адресс функции, закрывающей приложение, освобождающей данные.
  • указатель на глобальную константу, содержащую имя приложения.
  • указатель на таблицу, описывающую имена стэйтов. Можно указать NULL.

Функция должна вернуть RESULT_OK если все сделано без ошибок. Приложение запущено, возвращаем RESULT_OK, как подтверждение, что приложение успешно запущено.

Выход

Функция выхода(закрытия) из приложения имеет вид:

UINT32 AppExit( EVENT_STACK_T * ev_st, APPLICATION_T * app );

В этой функции должны быть удалены диалоги, освобождена память и прочие ресурсы, выделенные динамически в процессе работы приложения. Вызвана стандартная функция выхода из приложения.


Таблица состояний (англ. states)

В один момент времени приложение в целом может находиться в одном из состояний, за исключением зарезервированного ANY под индексом 0. От стэйта зависит поведение приложения. Когда на стандартный обработчик событий приложением (задается первым параметром в APP_InitAppData при старте приложения) поступает ивент он ищет код этого ивента в таблице обработчиков ивентов, которая записана под ANY стэйтом, если там не находит, то ищет в таблице под текущим стэйтом и вызывает обработчик события. Если обработчик ивента вернул чтото отличное от RESULT_OK вызывается функция выхода из приложения. Одно состояние должно иметь:

  • идентификатор. Задается через enum в заголовочном файле, при этом ANY_STATE под индексом 0.
  • функция входа в стэйт, можно NULL, если такая не нужна.
  • функция выхода из стэйта, можно NULL, если такая не нужна.
  • указатель на таблицу обработчиков ивентов.

Пример:

static const STATE_HANDLERS_ENTRY_T state_handling_table[] =	{ APP_STATE_ANY, NULL, NULL, any_state_handlers	},	{ APP_STATE_INIT, NULL, NULL, init_state_handlers	},	{ APP_STATE_MAIN, MainStateEnter, MainStateExit, main_state_handlers	}//,
};

Функция входа в стэйт

Должна иметь вид:

UINT32 StateEnter( EVENT_STACK_T * ev_st, APPLICATION_T * app, ENTER_STATE_TYPE_T type );

type при этом может принимать значения:

  • ENTER_STATE_ENTER - обычный вход в стэйт, либо при старте приложения, либо при смене стэйта.
  • ENTER_STATE_RESUME - приложение уже находится в этом стэйте, если приложение потеряло фокус, из-за того, что было запущено другое, которое использует UIS, и закрылось. Тоесть потеряло фокус и снова получило.

Функция выхода из стэйта

Должна иметь вид:

UINT32 StateExit( EVENT_STACK_T * ev_st, APPLICATION_T * app, EXIT_STATE_TYPE_T type );

type при этом может принимать значения:

  • EXIT_STATE_EXIT - обычный выход из стэйта.
  • EXIT_STATE_SUSPEND - когда приложение должно "приостановить" свою активность т.к. оно не имеет фокус.

Таблица обработчиков ивентов

Представляет из себя массив элементов типа:

typedef struct
{	EVENT_CODE_T	code; // код ивента	EVENT_HANDLER_T	*hfunc; // функция, которая обрабатывает ивент с этим кодом
} EVENT_HANDLER_ENTRY_T;