AIDL では、メソッドのオーバーロードが出来ません。
つまり、以下のような AIDL はコンパイルできません。
interface BadAIDL {
void doSomething();
void doSomething(int flags);
}
これで何が困るかといえば、呼び出される側のアプリをアップデートして IPC のインタフェースを変更出来ないということです。呼び出し側のアプリの改修を待たなければ、IPC はメソッドの実装がないものとして扱われAbstractMethodError
を吐いてクラッシュします。
ところが、このインタフェースの実装を工夫することで、擬似的ながらインタフェースのオーバーロードが可能になります。
オーバーロードができているように見せるハック
あるバージョンでは、以下のように AIDL が定義されているとします。
interface BadAIDL {
void doSomething();
}
この AIDL に従って実装を以下のように記述します。
public class SomeIPCHandler extends SomeAIDL.Stub {
public void doSomething() {
}
}
ここで、次のアップデートで AIDL を変更してみます。
interface BadAIDL {
void doSomething(int flags);
}
すると、実装も以下のように変更が必要になります。
public class SomeIPCHandler extends SomeAIDL.Stub {
public void doSomething(int flags) {
}
}
ところが、IPC の呼び出し側は以前のバージョンのままの場合、このままでは存在しないメソッドを呼び出すことになります(古いバージョンの呼び出しは古いインタフェースで判断されるので、実装がないエラーとなる)。
そこで、以下のようにオーバーロードを試みます。
public class SomeIPCHandler extends SomeAIDL.Stub {
public void doSomething() {
}
public void doSomething(int flags) {
}
}
Java ではオーバーロードそのものですので、IPC でもしっかり古い方のdoSomething()
が呼び出されます。
AIDL 上にはdoSomething()
の定義は消滅していますが、問題なく呼び出されているはずです。
これで、AIDL のバージョニングによる互換性問題が解決出来ました。