NativeActivity的OnCreate过程及InputQueue相关分析

每一个应用程序都有一个ActivityThread,当这个应用的进程创建时,
会进入到ActivityThread的main函数运行

    public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        Security.addProvider(new AndroidKeyStoreProvider());

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        AsyncTask.init();

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
这里Looper.prepareMainLooper()创建了mainLooper,并且Looper.loop() 进入loop循环,之后所有系统回调事件(比如onCreate)都通过这个looper接受 并由sMainThreadHandler这个主UI线程handler进行处理 thread.getHandler()返回的是final H mH = new H(); 当mH接受到LAUNCH_ACTIVITY事件之后, 调用handleLaunchActivity() > performLaunchActivity > onCreate     framework/base/core/java/android/app/NativeActivity.java: 可以看到在onCreate()函数里做了很多动作,包括: takeSurface、takeInputQueue(表示用户自己来处理input事件, android不会调用java层的dispatch等函数), 设置NativeContentView,加载jni library, loadNativeCode返回的mNativeHandle对应着native层的ANativeActivity* activity, 在后继调用中会被传给native层,可以看到funcname对应着ANativeActivity_onCreate, ANativeActivity_onCreate会被自动调用  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        String libname = "main";
        String funcname = "ANativeActivity_onCreate";
        ActivityInfo ai;

        mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

        getWindow().takeSurface(this);
        getWindow().takeInputQueue(this);
        getWindow().setFormat(PixelFormat.RGB_565);
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
                | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

        mNativeContentView = new NativeContentView(this);
        mNativeContentView.mActivity = this;
        setContentView(mNativeContentView);
        mNativeContentView.requestFocus();
        mNativeContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);

        try {
            ai = getPackageManager().getActivityInfo(
                    getIntent().getComponent(), PackageManager.GET_META_DATA);
            if (ai.metaData != null) {
                String ln = ai.metaData.getString(META_DATA_LIB_NAME);
                if (ln != null) libname = ln;
                ln = ai.metaData.getString(META_DATA_FUNC_NAME);
                if (ln != null) funcname = ln;
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException("Error getting activity info", e);
        }

        String path = null;

        File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
                System.mapLibraryName(libname));
        if (libraryFile.exists()) {
            path = libraryFile.getPath();
        }

        if (path == null) {
            throw new IllegalArgumentException("Unable to find native library: " + libname);
        }

        byte[] nativeSavedState = savedInstanceState != null
                ? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;

        mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
                getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
                getAbsolutePath(getExternalFilesDir(null)),
                Build.VERSION.SDK_INT, getAssets(), nativeSavedState);

        if (mNativeHandle == 0) {
            throw new IllegalArgumentException("Unable to load native library: " + path);
        }
        super.onCreate(savedInstanceState);
    }

loadNativeCode调用jni层的loadNativeCode_native
它通过java层的messageQueue取得对应的native层的messageQueue,并赋值给code->messageQueue
创建pipe,将读端赋值给code->mainWorkRead,写端赋值给code->mainWorkWrite
并将读端添加到主线程looper中进行监听,对应的回调函数是mainWorkCallback
这里创建的pipe主要用于将native层函数调用传递到java层
例如由native层发起android_NativeActivity_showSoftInput,它就向
code->mainWorkWrite写入CMD_SHOW_SOFT_INPUT,唤醒looper并进入mainWorkCallback回调

        case CMD_SHOW_SOFT_INPUT: {
            code->env->CallVoidMethod(code->clazz,
                    gNativeActivityClassInfo.showIme, work.arg1);
            code->messageQueue->raiseAndClearException(code->env, "showIme");
        } break;
进而调用java层的showIme() 设置好code struct其他字段后,code->createActivityFunc调用jni层的ANativeActivity_onCreate code对应于ANativeActivity结构体,load结束后保存在java层的mNativeHandle变量中 frameworks/base/core/jni/android_app_NativeActivity.cpp > loadNativeCode_native
static jint
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
        jobject messageQueue, jstring internalDataDir, jstring obbDir,
        jstring externalDataDir, int sdkVersion,
        jobject jAssetMgr, jbyteArray savedState)
{
    LOG_TRACE("loadNativeCode_native");

    const char* pathStr = env->GetStringUTFChars(path, NULL);
    NativeCode* code = NULL;

    void* handle = dlopen(pathStr, RTLD_LAZY);

    env->ReleaseStringUTFChars(path, pathStr);

    if (handle != NULL) {
        const char* funcStr = env->GetStringUTFChars(funcName, NULL);
        code = new NativeCode(handle, (ANativeActivity_createFunc*)
                dlsym(handle, funcStr));
        env->ReleaseStringUTFChars(funcName, funcStr);

        if (code->createActivityFunc == NULL) {
            ALOGW("ANativeActivity_onCreate not found");
            delete code;
            return 0;
        }

        code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
        if (code->messageQueue == NULL) {
            ALOGW("Unable to retrieve native MessageQueue");
            delete code;
            return 0;
        }

        int msgpipe[2];
        if (pipe(msgpipe)) {
            ALOGW("could not create pipe: %s", strerror(errno));
            delete code;
            return 0;
        }
        code->mainWorkRead = msgpipe[0];
        code->mainWorkWrite = msgpipe[1];
        int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
        SLOGW_IF(result != 0, "Could not make main work read pipe "
                "non-blocking: %s", strerror(errno));
        result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
        SLOGW_IF(result != 0, "Could not make main work write pipe "
                "non-blocking: %s", strerror(errno));
        code->messageQueue->getLooper()->addFd(
                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);

        code->ANativeActivity::callbacks = &code->callbacks;
        if (env->GetJavaVM(&code->vm) < 0) {
            ALOGW("NativeActivity GetJavaVM failed");
            delete code;
            return 0;
        }
        code->env = env;
        code->clazz = env->NewGlobalRef(clazz);

        const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
        code->internalDataPathObj = dirStr;
        code->internalDataPath = code->internalDataPathObj.string();
        env->ReleaseStringUTFChars(internalDataDir, dirStr);

        if (externalDataDir != NULL) {
            dirStr = env->GetStringUTFChars(externalDataDir, NULL);
            code->externalDataPathObj = dirStr;
            env->ReleaseStringUTFChars(externalDataDir, dirStr);
        }
        code->externalDataPath = code->externalDataPathObj.string();

        code->sdkVersion = sdkVersion;

        code->assetManager = assetManagerForJavaObject(env, jAssetMgr);

        if (obbDir != NULL) {
            dirStr = env->GetStringUTFChars(obbDir, NULL);
            code->obbPathObj = dirStr;
            env->ReleaseStringUTFChars(obbDir, dirStr);
        }
        code->obbPath = code->obbPathObj.string();

        jbyte* rawSavedState = NULL;
        jsize rawSavedSize = 0;
        if (savedState != NULL) {
            rawSavedState = env->GetByteArrayElements(savedState, NULL);
            rawSavedSize = env->GetArrayLength(savedState);
        }

        code->createActivityFunc(code, rawSavedState, rawSavedSize);

        if (rawSavedState != NULL) {
            env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
        }
    }

    return (jint)code;
}

在NDK中android-ndk-r9d/sources/android/native_app_glue/android_native_app_glue.c
ANativeActivity_onCreate的实现为:

void ANativeActivity_onCreate(ANativeActivity* activity,
        void* savedState, size_t savedStateSize) {
    LOGV("Creating: %p\n", activity);
    activity->callbacks->onDestroy = onDestroy;
    activity->callbacks->onStart = onStart;
    activity->callbacks->onResume = onResume;
    activity->callbacks->onSaveInstanceState = onSaveInstanceState;
    activity->callbacks->onPause = onPause;
    activity->callbacks->onStop = onStop;
    activity->callbacks->onConfigurationChanged = onConfigurationChanged;
    activity->callbacks->onLowMemory = onLowMemory;
    activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
    activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
    activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
    activity->callbacks->onInputQueueCreated = onInputQueueCreated;
    activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;

    activity->instance = android_app_create(activity, savedState, savedStateSize);
}
可以看到设置了一些callbacks,包括常见的onResume、onPause等, onInputQueueCreated也是在这里设置的,后面会看到 最后调用android_app_create,
static struct android_app* android_app_create(ANativeActivity* activity,
        void* savedState, size_t savedStateSize) {
    struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
    memset(android_app, 0, sizeof(struct android_app));
    android_app->activity = activity;

    pthread_mutex_init(&android_app->mutex, NULL);
    pthread_cond_init(&android_app->cond, NULL);

    if (savedState != NULL) {
        android_app->savedState = malloc(savedStateSize);
        android_app->savedStateSize = savedStateSize;
        memcpy(android_app->savedState, savedState, savedStateSize);
    }

    int msgpipe[2];
    if (pipe(msgpipe)) {
        LOGE("could not create pipe: %s", strerror(errno));
        return NULL;
    }
    android_app->msgread = msgpipe[0];
    android_app->msgwrite = msgpipe[1];

    pthread_attr_t attr; 
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&android_app->thread, &attr, android_app_entry, android_app);

    // Wait for thread to start.
    pthread_mutex_lock(&android_app->mutex);
    while (!android_app->running) {
        pthread_cond_wait(&android_app->cond, &android_app->mutex);
    }
    pthread_mutex_unlock(&android_app->mutex);

    return android_app;
}
这个函数会malloc一个struct android_app的自定义结构体保存一些必要的变量, pipe(msgpipe)创建一个pipe管道,接着pthread_create创建子线程, 子线程的入口是android_app_entry,等待子线程起来后就可以返回了, 返回的android_app结构体保存在ANativeActivity的instance,它是一个 void*指针,可以保存任何用户自定义数据,这里是android_app结构体 回到android_app_entry这个子线程入口:
static void* android_app_entry(void* param) {
    struct android_app* android_app = (struct android_app*)param;

    android_app->config = AConfiguration_new();
    AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);

    print_cur_config(android_app);

    android_app->cmdPollSource.id = LOOPER_ID_MAIN;
    android_app->cmdPollSource.app = android_app;
    android_app->cmdPollSource.process = process_cmd;
    android_app->inputPollSource.id = LOOPER_ID_INPUT;
    android_app->inputPollSource.app = android_app;
    android_app->inputPollSource.process = process_input;

    ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
    ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
            &android_app->cmdPollSource);
    android_app->looper = looper;

    pthread_mutex_lock(&android_app->mutex);
    android_app->running = 1;
    pthread_cond_broadcast(&android_app->cond);
    pthread_mutex_unlock(&android_app->mutex);

    android_main(android_app);

    android_app_destroy(android_app);
    return NULL;
}
这里创建一个native层的looper ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 关于looper更详细的介绍可以参考《Android应用程序消息处理机制(Looper、Handler)分析》(下载) 然后将前面pipe创建的msgread读端FD,挂到这个looper去监听, int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) fd对应android_app->msgread,ident对应LOOPER_ID_MAIN,events对应ALOOPER_EVENT_INPUT(监听输入事件), callback为NULL,data指向&android_app->cmdPollSource 一旦pipe的写端msgwrite写入了数据,监听msgread的looper就会被唤醒(pollOnce结束block状态), 对于传入callback为NULL的情况,pollOnce直接返回ident,根据这个值就知道是什么类型的事件了, 比如LOOPER_ID_MAIN、LOOPER_ID_INPUT等等,参考前一篇《retroarch:启动入口、android输入驱动》 中process_events调用android_run_events时的ALooper_pollOnce 这里我们传进去的是LOOPER_ID_MAIN,表明是android系统相关的事件 注意,这里创建的pipe及looper是在一个新线程中运行的,而不是前面的主UI线程 后面提到的LOOPER_ID_MAIN、LOOPER_ID_INPUT都是在这个新线程中处理的 下面来看看跟Looper相关的部分: ALooper_xxx函数基本上都是将调用传递给looper frameworks/base/native/android/looper.cpp
ALooper* ALooper_forThread() {
    return Looper::getForThread().get();
}

ALooper* ALooper_prepare(int opts) {
    return Looper::prepare(opts).get();
}

int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    sp looper = Looper::getForThread();
    if (looper == NULL) {
        ALOGE("ALooper_pollOnce: No looper for this thread!");
        return ALOOPER_POLL_ERROR;
    }

    IPCThreadState::self()->flushCommands();
    return looper->pollOnce(timeoutMillis, outFd, outEvents, outData);
}

int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    sp looper = Looper::getForThread();
    if (looper == NULL) {
        ALOGE("ALooper_pollAll: No looper for this thread!");
        return ALOOPER_POLL_ERROR;
    }

    IPCThreadState::self()->flushCommands();
    return looper->pollAll(timeoutMillis, outFd, outEvents, outData);
}

void ALooper_wake(ALooper* looper) {
    static_cast<Looper*>(looper)->wake();
}

int ALooper_addFd(ALooper* looper, int fd, int ident, int events,
        ALooper_callbackFunc callback, void* data) {
    return static_cast<Looper*>(looper)->addFd(fd, ident, events, callback, data);
}

int ALooper_removeFd(ALooper* looper, int fd) {
    return static_cast<Looper*>(looper)->removeFd(fd);
}
关于looper可以参考android源代码目录下的system/core/libutils/Looper.cpp实现
sp Looper::prepare(int opts) {
    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
    sp looper = Looper::getForThread();
    if (looper == NULL) {
        looper = new Looper(allowNonCallbacks);
        Looper::setForThread(looper);
    }
    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
        ALOGW("Looper already prepared for this thread with a different value for the "
                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
    }
    return looper;
}

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    int wakeFds[2];
    int result = pipe(wakeFds);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
            errno);

    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
            errno);

    mIdling = false;

    // Allocate the epoll instance and register the wake pipe.
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
            errno);
}

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            int ident = response.request.ident;
            if (ident >= 0) {
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
                ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
                        "fd=%d, events=0x%x, data=%p",
                        this, ident, fd, events, data);
#endif
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }

        if (result != 0) {
#if DEBUG_POLL_AND_WAKE
            ALOGD("%p ~ pollOnce - returning result %d", this, result);
#endif
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = 0;
            if (outData != NULL) *outData = NULL;
            return result;
        }

        result = pollInner(timeoutMillis);
    }
}

int Looper::pollInner(int timeoutMillis) {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
#endif

    // Adjust the timeout based on when the next message is due.
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
                this, mNextMessageUptime - now, timeoutMillis);
#endif
    }

    // Poll.
    int result = ALOOPER_POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;

    // We are about to idle.
    mIdling = true;

    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    // No longer idling.
    mIdling = false;

    // Acquire lock.
    mLock.lock();

    // Check for poll error.
    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }
        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
        result = ALOOPER_POLL_ERROR;
        goto Done;
    }

    // Check for poll timeout.
    if (eventCount == 0) {
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - timeout", this);
#endif
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }

    // Handle all events.
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
#endif

    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
Done: ;

    // Invoke pending message callbacks.
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            // Remove the envelope from the list.
            // We keep a strong reference to the handler until the call to handleMessage
            // finishes.  Then we drop it so that the handler can be deleted *before*
            // we reacquire our lock.
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
                        this, handler.get(), message.what);
#endif
                handler->handleMessage(message);
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }

    // Release lock.
    mLock.unlock();

    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
                    this, response.request.callback.get(), fd, events, data);
#endif
            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd);
            }
            // Clear the callback reference in the response structure promptly because we
            // will not clear the response vector itself until the next poll.
            response.request.callback.clear();
            result = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}

int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    if (timeoutMillis <= 0) {
        int result;
        do {
            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
        } while (result == ALOOPER_POLL_CALLBACK);
        return result;
    } else {
        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
                + milliseconds_to_nanoseconds(timeoutMillis);

        for (;;) {
            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
            if (result != ALOOPER_POLL_CALLBACK) {
                return result;
            }

            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
            if (timeoutMillis == 0) {
                return ALOOPER_POLL_TIMEOUT;
            }
        }
    }
}

void Looper::wake() {
    ssize_t nWrite;
    do {
        nWrite = write(mWakeWritePipeFd, "W", 1);
    } while (nWrite == -1 && errno == EINTR);

    if (nWrite != 1) {
        if (errno != EAGAIN) {
            ALOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}

void Looper::awoken() {
    char buffer[16];
    ssize_t nRead;
    do {
        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}

int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
    return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}

int Looper::addFd(int fd, int ident, int events, const sp& callback, void* data) {
    if (!callback.get()) {
        if (! mAllowNonCallbacks) {
            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
            return -1;
        }

        if (ident < 0) {
            ALOGE("Invalid attempt to set NULL callback with ident < 0.");
            return -1;
        }
    } else {
        ident = ALOOPER_POLL_CALLBACK;
    }

    int epollEvents = 0;
    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;

    { // acquire lock
        AutoMutex _l(mLock);

        Request request;
        request.fd = fd;
        request.ident = ident;
        request.callback = callback;
        request.data = data;

        struct epoll_event eventItem;
        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
        eventItem.events = epollEvents;
        eventItem.data.fd = fd;

        ssize_t requestIndex = mRequests.indexOfKey(fd);
        if (requestIndex < 0) {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.add(fd, request);
        } else {
            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
            if (epollResult < 0) {
                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
                return -1;
            }
            mRequests.replaceValueAt(requestIndex, request);
        }
    } // release lock
    return 1;
}

void Looper::sendMessageAtTime(nsecs_t uptime, const sp& handler,
        const Message& message) {
    size_t i = 0;
    { // acquire lock
        AutoMutex _l(mLock);

        size_t messageCount = mMessageEnvelopes.size();
        while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
            i += 1;
        }

        MessageEnvelope messageEnvelope(uptime, handler, message);
        mMessageEnvelopes.insertAt(messageEnvelope, i, 1);

        // Optimization: If the Looper is currently sending a message, then we can skip
        // the call to wake() because the next thing the Looper will do after processing
        // messages is to decide when the next wakeup time should be.  In fact, it does
        // not even matter whether this code is running on the Looper thread.
        if (mSendingMessage) {
            return;
        }
    } // release lock

    // Wake the poll loop only when we enqueue a new message at the head.
    if (i == 0) {
        wake();
    }
}
最后android_main(android_app)进入主循环,android_main由app实现 可以看看NDK提供的sample native-activity实现:
void android_main(struct android_app* state) {
    struct engine engine;

    // Make sure glue isn't stripped.
    app_dummy();

    memset(&engine, 0, sizeof(engine));
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    state->onInputEvent = engine_handle_input;
    engine.app = state;

    // Prepare to monitor accelerometer
    engine.sensorManager = ASensorManager_getInstance();
    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
            ASENSOR_TYPE_ACCELEROMETER);
    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
            state->looper, LOOPER_ID_USER, NULL, NULL);

    if (state->savedState != NULL) {
        // We are starting with a previous saved state; restore from it.
        engine.state = *(struct saved_state*)state->savedState;
    }

    // loop waiting for stuff to do.

    while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;

        // If not animating, we will block forever waiting for events.
        // If animating, we loop until all events are read, then continue
        // to draw the next frame of animation.
        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
                (void**)&source)) >= 0) {

            // Process this event.
            if (source != NULL) {
                source->process(state, source);
            }

            // If a sensor has data, process it now.
            if (ident == LOOPER_ID_USER) {
                if (engine.accelerometerSensor != NULL) {
                    ASensorEvent event;
                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
                            &event, 1) > 0) {
                        LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
                    }
                }
            }

            // Check if we are exiting.
            if (state->destroyRequested != 0) {
                engine_term_display(&engine);
                return;
            }
        }

        if (engine.animating) {
            // Done with events; draw next animation frame.
            engine.state.angle += .01f;
            if (engine.state.angle > 1) {
                engine.state.angle = 0;
            }

            // Drawing is throttled to the screen update rate, so there
            // is no need to do timing here.
            engine_draw_frame(&engine);
        }
    }
}

static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
    struct engine* engine = (struct engine*)app->userData;
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        engine->animating = 1;
        engine->state.x = AMotionEvent_getX(event, 0);
        engine->state.y = AMotionEvent_getY(event, 0);
        return 1;
    }
    return 0;
}
android_native_app_glue.c中,onInputQueueCreated被系统回调时,
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
    LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
    android_app_set_input((struct android_app*)activity->instance, queue);
}
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
    pthread_mutex_lock(&android_app->mutex);
    android_app->pendingInputQueue = inputQueue;
    android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
    while (android_app->inputQueue != android_app->pendingInputQueue) {
        pthread_cond_wait(&android_app->cond, &android_app->mutex);
    }
    pthread_mutex_unlock(&android_app->mutex);
}
这里发送了一个APP_CMD_INPUT_CHANGED命令,
static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
    if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
        LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
    }
}
实际上就是向前面创建的pipe的写端msgwrite写入cmd,让挂在looper上等待的读端被唤醒, app在android_main循环中应该会不断调用looper的pollOnce/pollAll,这时就会返回LOOPER_ID_MAIN, 这时可以调用android_app->cmdPollSource中的process_cmd进行处理 process_cmd的实现如下:
static void process_cmd(struct android_app* app, struct android_poll_source* source) {
    int8_t cmd = android_app_read_cmd(app);
    android_app_pre_exec_cmd(app, cmd);
    if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
    android_app_post_exec_cmd(app, cmd);
}

int8_t android_app_read_cmd(struct android_app* android_app) {
    int8_t cmd;
    if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
        switch (cmd) {
            case APP_CMD_SAVE_STATE:
                free_saved_state(android_app);
                break;
        }
        return cmd;
    } else {
        LOGE("No data on command pipe!");
    }
    return -1;
}
它会先调用android_app_pre_exec_cmd预处理一下,然后调用onAppCmd这个app实现的回调, 最后调用android_app_post_exec_cmd
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
    switch (cmd) {
        case APP_CMD_INPUT_CHANGED:
            LOGV("APP_CMD_INPUT_CHANGED\n");
            pthread_mutex_lock(&android_app->mutex);
            if (android_app->inputQueue != NULL) {
                AInputQueue_detachLooper(android_app->inputQueue);
            }
            android_app->inputQueue = android_app->pendingInputQueue;
            if (android_app->inputQueue != NULL) {
                LOGV("Attaching input queue to looper");
                AInputQueue_attachLooper(android_app->inputQueue,
                        android_app->looper, LOOPER_ID_INPUT, NULL,
                        &android_app->inputPollSource);
            }
            pthread_cond_broadcast(&android_app->cond);
            pthread_mutex_unlock(&android_app->mutex);
            break;
    ....
这里只看我们关心的APP_CMD_INPUT_CHANGED,主要执行了AInputQueue_attachLooper, frameworks/base/native/android/input.cpp:
void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
        int ident, ALooper_callbackFunc callback, void* data) {
    InputQueue* iq = static_cast<InputQueue*>(queue);
    Looper* l = static_cast<Looper*>(looper);
    iq->attachLooper(l, ident, callback, data);
}
frameworks/base/core/jni/android_view_InputQueue.cpp
void InputQueue::attachLooper(Looper* looper, int ident,
        ALooper_callbackFunc callback, void* data) {
    Mutex::Autolock _l(mLock);
    for (size_t i = 0; i < mAppLoopers.size(); i++) {
        if (looper == mAppLoopers[i]) {
            return;
        }
    }
    mAppLoopers.push(looper);
    looper->addFd(mDispatchReadFd, ident, ALOOPER_EVENT_INPUT, callback, data);
}
最终会调用looper的addFd,将mDispatchReadFd这个读端fd挂到looper上监听, 从mAppLoopers.push(looper)可以看到mDispatchReadFd可以有多个looper来监听, 至此,input queue的事件也被监听了,android系统底层向input queue的写端写入数据, 就能唤醒读端,而开发者通过pollOnce返回的ident为LOOPER_ID_INPUT 当LOOPER_ID_INPUT返回时,可以调用android_app->inputPollSource中的process_input进行处理 它会先调用AInputQueue_preDispatchEvent处理,接着调用app的onInputEvent, 最后调用AInputQueue_finishEvent结束处理
static void process_input(struct android_app* app, struct android_poll_source* source) {
    AInputEvent* event = NULL;
    while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
        LOGV("New input event: type=%d\n", AInputEvent_getType(event));
        if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
            continue;
        }
        int32_t handled = 0;
        if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
        AInputQueue_finishEvent(app->inputQueue, event, handled);
    }
}

frameworks/base/native/android/input.cpp:

int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent) {
    InputQueue* iq = static_cast<InputQueue*>(queue);
    InputEvent* event;
    int32_t res = iq->getEvent(&event);
    *outEvent = event;
    return res;
}

int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event) {
    InputQueue* iq = static_cast<InputQueue*>(queue);
    InputEvent* e = static_cast<InputEvent*>(event);
    return iq->preDispatchEvent(e) ? 1 : 0;
}

void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled) {
    InputQueue* iq = static_cast<InputQueue*>(queue);
    InputEvent* e = static_cast<InputEvent*>(event);
    iq->finishEvent(e, handled != 0);
}

frameworks/base/core/jni/android_view_InputQueue.cpp

status_t InputQueue::getEvent(InputEvent** outEvent) {
    Mutex::Autolock _l(mLock);
    *outEvent = NULL;
    if (!mPendingEvents.isEmpty()) {
        *outEvent = mPendingEvents[0];
        mPendingEvents.removeAt(0);
    }

    if (mPendingEvents.isEmpty()) {
        char byteread[16];
        ssize_t nRead;
        do {
            nRead = TEMP_FAILURE_RETRY(read(mDispatchReadFd, &byteread, sizeof(byteread)));
            if (nRead < 0 && errno != EAGAIN) {
                ALOGW("Failed to read from native dispatch pipe: %s", strerror(errno));
            }
        } while (nRead > 0);
    }

    return *outEvent != NULL ? OK : WOULD_BLOCK;
}

bool InputQueue::preDispatchEvent(InputEvent* e) {
    if (e->getType() == AINPUT_EVENT_TYPE_KEY) {
        KeyEvent* keyEvent = static_cast<KeyEvent*>(e);
        if (keyEvent->getFlags() & AKEY_EVENT_FLAG_PREDISPATCH) {
            finishEvent(e, false);
            return true;
        }
    }
    return false;
}

void InputQueue::finishEvent(InputEvent* event, bool handled) {
    Mutex::Autolock _l(mLock);
    mFinishedEvents.push(key_value_pair_t<InputEvent*, bool>(event, handled));
    if (mFinishedEvents.size() == 1) {
        mDispatchLooper->sendMessage(this, Message(MSG_FINISH_INPUT));
    }
}

再回到前面,android_native_app_glue.c中的onInputQueueCreated何时被回调的?

Java层在ViewRootImpl.java中调用setView时,会判断mInputQueueCallback是否为null,
对于NativeActivity,它在onCreate时调用了getWindow().takeInputQueue(this);
因此不为null,于是new InputQueue()创建一个InputQueue,
并且调用mInputQueueCallback.onInputQueueCreated

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ....
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
            getHostVisibility(), mDisplay.getDisplayId(),
            mAttachInfo.mContentInsets, mInputChannel);
    ....
    if (mInputChannel != null) {
        if (mInputQueueCallback != null) {
            mInputQueue = new InputQueue();
            mInputQueueCallback.onInputQueueCreated(mInputQueue);
        }
        mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                Looper.myLooper());
    }
    ....
}

new InputQueue()创建如下:
frameworks/base/core/java/android/view/InputQueue.java

    public InputQueue() {
        mPtr = nativeInit(new WeakReference<InputQueue>(this), Looper.myQueue());
        mCloseGuard.open("dispose");
    }

frameworks/base/core/jni/android_view_InputQueue.cpp

static jint nativeInit(JNIEnv* env, jobject clazz, jobject queueWeak, jobject jMsgQueue) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, jMsgQueue);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    sp<InputQueue> queue = InputQueue::createQueue(queueWeak, messageQueue->getLooper());
    if (!queue.get()) {
        jniThrowRuntimeException(env, "InputQueue failed to initialize");
        return 0;
    }
    queue->incStrong(&gInputQueueClassInfo);
    return reinterpret_cast<jint>(queue.get());
}

InputQueue* InputQueue::createQueue(jobject inputQueueObj, const sp<Looper>& looper) {
    int pipeFds[2];
    if (pipe(pipeFds)) {
        ALOGW("Could not create native input dispatching pipe: %s", strerror(errno));
        return NULL;
    }
    fcntl(pipeFds[0], F_SETFL, O_NONBLOCK);
    fcntl(pipeFds[1], F_SETFL, O_NONBLOCK);
    return new InputQueue(inputQueueObj, looper, pipeFds[0], pipeFds[1]);
}

InputQueue::InputQueue(jobject inputQueueObj, const sp<Looper>& looper,
        int dispatchReadFd, int dispatchWriteFd) :
        mDispatchReadFd(dispatchReadFd), mDispatchWriteFd(dispatchWriteFd),
        mDispatchLooper(looper), mHandler(new WeakMessageHandler(this)) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    mInputQueueWeakGlobal = env->NewGlobalRef(inputQueueObj);
}
可以看到native层的InputQueue创建了一个pipe,读端是mDispatchReadFd 前面看到的InputQueue::attachLooper,就是将looper与这个读端绑定的 java层的onInputQueueCreated回调函数会调用native层: frameworks/base/core/java/android/view/InputQueue.java
    public void onInputQueueCreated(InputQueue queue) {
        if (!mDestroyed) {
            mCurInputQueue = queue;
            onInputQueueCreatedNative(mNativeHandle, queue.getNativePtr());
        }
    }
frameworks/base/core/jni/android_app_NativeActivity.cpp:
static void
onInputQueueCreated_native(JNIEnv* env, jobject clazz, jint handle, jint queuePtr)
{
    LOG_TRACE("onInputChannelCreated_native");
    if (handle != 0) {
        NativeCode* code = (NativeCode*)handle;
        if (code->callbacks.onInputQueueCreated != NULL) {
            AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
            code->callbacks.onInputQueueCreated(code, queue);
        }
    }
}
InputQueue中的另一个重要函数sendInputEvent, ViewRootImpl在收到InputEvent进行分发的流程中,会将InputEvent通过这个 函数插入到InputQueue中去,这样native层就接受到InputEvent了 可惜sendInputEvent是hide不可见的 可以看看native层是如何注入input event事件的(见nativeSendKeyEvent) frameworks/base/core/java/android/view/InputQueue.java
    /** @hide */
    public void sendInputEvent(InputEvent e, Object token, boolean predispatch,
            FinishedInputEventCallback callback) {
        ActiveInputEvent event = obtainActiveInputEvent(token, callback);
        int id;
        if (e instanceof KeyEvent) {
            id = nativeSendKeyEvent(mPtr, (KeyEvent) e, predispatch);
        } else {
            id = nativeSendMotionEvent(mPtr, (MotionEvent) e);
        }
        mActiveEventArray.put(id, event);
    }

    private void finishInputEvent(int id, boolean handled) {
        int index = mActiveEventArray.indexOfKey(id);
        if (index >= 0) {
            ActiveInputEvent e = mActiveEventArray.valueAt(index);
            mActiveEventArray.removeAt(index);
            e.mCallback.onFinishedInputEvent(e.mToken, handled);
            recycleActiveInputEvent(e);
        }
    }
frameworks/base/core/jni/android_view_InputQueue.cpp
static jint nativeSendKeyEvent(JNIEnv* env, jobject clazz, jint ptr, jobject eventObj,
        jboolean predispatch) {
    InputQueue* queue = reinterpret_cast<InputQueue*>(ptr);
    KeyEvent* event = queue->createKeyEvent();
    status_t status = android_view_KeyEvent_toNative(env, eventObj, event);
    if (status) {
        queue->recycleInputEvent(event);
        jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
        return -1;
    }

    if (predispatch) {
        event->setFlags(event->getFlags() | AKEY_EVENT_FLAG_PREDISPATCH);
    }

    queue->enqueueEvent(event);
    return reinterpret_cast(event);
}

static jint nativeSendMotionEvent(JNIEnv* env, jobject clazz, jint ptr, jobject eventObj) {
    sp queue = reinterpret_cast<InputQueue*>(ptr);
    MotionEvent* originalEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
    if (!originalEvent) {
        jniThrowRuntimeException(env, "Could not obtain MotionEvent pointer.");
        return -1;
    }
    MotionEvent* event = queue->createMotionEvent();
    event->copyFrom(originalEvent, true /* keepHistory */);
    queue->enqueueEvent(event);
    return reinterpret_cast(event);
}
最后附上两个结构体的定义 ANativeActivity的定义如下:
typedef struct ANativeActivity {
    /**
     * Pointer to the callback function table of the native application.
     * You can set the functions here to your own callbacks.  The callbacks
     * pointer itself here should not be changed; it is allocated and managed
     * for you by the framework.
     */
    struct ANativeActivityCallbacks* callbacks;

    /**
     * The global handle on the process's Java VM.
     */
    JavaVM* vm;

    /**
     * JNI context for the main thread of the app.  Note that this field
     * can ONLY be used from the main thread of the process; that is, the
     * thread that calls into the ANativeActivityCallbacks.
     */
    JNIEnv* env;

    /**
     * The NativeActivity object handle.
     *
     * IMPORTANT NOTE: This member is mis-named. It should really be named
     * 'activity' instead of 'clazz', since it's a reference to the
     * NativeActivity instance created by the system for you.
     *
     * We unfortunately cannot change this without breaking NDK
     * source-compatibility.
     */
    jobject clazz;

    /**
     * Path to this application's internal data directory.
     */
    const char* internalDataPath;

    /**
     * Path to this application's external (removable/mountable) data directory.
     */
    const char* externalDataPath;

    /**
     * The platform's SDK version code.
     */
    int32_t sdkVersion;

    /**
     * This is the native instance of the application.  It is not used by
     * the framework, but can be set by the application to its own instance
     * state.
     */
    void* instance;

    /**
     * Pointer to the Asset Manager instance for the application.  The application
     * uses this to access binary assets bundled inside its own .apk file.
     */
    AAssetManager* assetManager;
} ANativeActivity;
struct android_app的定义如下:
struct android_app {
    // The application can place a pointer to its own state object
    // here if it likes.
    void* userData;

    // Fill this in with the function to process main app commands (APP_CMD_*)
    void (*onAppCmd)(struct android_app* app, int32_t cmd);

    // Fill this in with the function to process input events.  At this point
    // the event has already been pre-dispatched, and it will be finished upon
    // return.  Return 1 if you have handled the event, 0 for any default
    // dispatching.
    int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);

    // The ANativeActivity object instance that this app is running in.
    ANativeActivity* activity;

    // The current configuration the app is running in.
    AConfiguration* config;

    // This is the last instance's saved state, as provided at creation time.
    // It is NULL if there was no state.  You can use this as you need; the
    // memory will remain around until you call android_app_exec_cmd() for
    // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
    // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
    // at which point they will be initialized to NULL and you can malloc your
    // state and place the information here.  In that case the memory will be
    // freed for you later.
    void* savedState;
    size_t savedStateSize;

    // The ALooper associated with the app's thread.
    ALooper* looper;

    // When non-NULL, this is the input queue from which the app will
    // receive user input events.
    AInputQueue* inputQueue;

    // When non-NULL, this is the window surface that the app can draw in.
    ANativeWindow* window;

    // Current content rectangle of the window; this is the area where the
    // window's content should be placed to be seen by the user.
    ARect contentRect;

    // Current state of the app's activity.  May be either APP_CMD_START,
    // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
    int activityState;

    // This is non-zero when the application's NativeActivity is being
    // destroyed and waiting for the app thread to complete.
    int destroyRequested;

    // -------------------------------------------------
    // Below are "private" implementation of the glue code.

    pthread_mutex_t mutex;
    pthread_cond_t cond;

    int msgread;
    int msgwrite;

    pthread_t thread;

    struct android_poll_source cmdPollSource;
    struct android_poll_source inputPollSource;

    int running;
    int stateSaved;
    int destroyed;
    int redrawNeeded;
    AInputQueue* pendingInputQueue;
    ANativeWindow* pendingWindow;
    ARect pendingContentRect;
};