Не односторонние декларации в Android.AIDL гарантирует, что метод будет вызван в отдельном потоке?


Я разрабатываю фреймворк для клиент-серверного приложения для телефонов на Android. Я довольно Новичок как в Java, так и в Android (но не новичок в программировании вообще или в потоковом программировании в частности).

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

IServer.aidl:

package com.my.application;

interface IServer {

    /**
     * Register client callback object
     */
    void registerCallback( in IClient callbackObject );

    /**
     * Do something and report back
     */
    void doSomething( in String what );
  .
  .
  .
}

IClient.aidl:

package com.my.application;

oneway interface IClient {

    /**
     * Receive an answer
     */
    void reportBack( in String answer );
  .
  .
  .
}
Теперь вот где это становится интересным. Я могу предвидеть случаи использования, когда клиент вызывает IServer.doSomething(), который в свою очередь вызывает IClient.reportBack(), и на основе того, что сообщается обратно, IClient.reportBack() должен сделать еще один вызов IClient.doSomething(). Проблема здесь в том, что IServer.doSomething() в целом не будет реентерабельным. Это нормально, если IClient.reportBack() всегда вызывается в новом потоке. В таком случае, я могу убедиться, что реализация из IServer.doSomething() всегда synchronized соответственно, так что вызов из Нового потока блокируется до тех пор, пока не вернется первый вызов.

Если все работает так, как я думаю, то, объявив интерфейс IClient как oneway, я гарантирую, что это так. По крайней мере, я не могу придумать никакого способа, чтобы вызов из IServer.doSomething() в IClient.reportBack() мог немедленно вернуться (что oneway должен гарантировать), но IClient.reportBack все еще мог повторно вызвать IServer.doSomething рекурсивно в том же потоке. Либо новый поток в IServer должен быть запущенным, или же старый поток IServer может быть повторно использован для внутреннего вызова IServer.doSomething (), но только после того, как внешний вызов IServer.doSomething() вернулся.

Итак, мой вопрос: все ли работает так, как я думаю? Документация по Android почти не упоминает интерфейсы oneway.
1 6

1 ответ:

Ключевое слово oneway означает, что если этот вызов приводит к IPC (то есть вызывающий и вызываемый находятся в разных процессах), то вызывающий процесс не будет ждать, пока вызываемый процесс обработает IPC. Если это не приводит к IPC (то есть они оба находятся в одном процессе), вызов будет синхронным. Это досадная деталь, которая значительно упрощает реализацию binder IPC. Если они находятся в одном процессе, то вызов является обычным вызовом метода java.