diff --git a/play-services-api/src/main/aidl/com/google/android/gms/phenotype/internal/IPhenotypeService.aidl b/play-services-api/src/main/aidl/com/google/android/gms/phenotype/internal/IPhenotypeService.aidl new file mode 100644 index 00000000..3b306d53 --- /dev/null +++ b/play-services-api/src/main/aidl/com/google/android/gms/phenotype/internal/IPhenotypeService.aidl @@ -0,0 +1,35 @@ +package com.google.android.gms.phenotype.internal; + +import com.google.android.gms.common.api.internal.IStatusCallback; +import com.google.android.gms.phenotype.internal.IPhenotypeCallbacks; +import com.google.android.gms.phenotype.Flag; +import com.google.android.gms.phenotype.RegistrationInfo; + +interface IPhenotypeService { + oneway void register(IPhenotypeCallbacks callbacks, String packageName, int version, in String[] p3, in byte[] p4) = 0; // returns via callbacks.onRegistered() + oneway void weakRegister(IPhenotypeCallbacks callbacks, String packageName, int version, in String[] p3, in int[] p4, in byte[] p5) = 1; // returns via callbacks.onWeakRegistered() + oneway void unregister(IPhenotypeCallbacks callbacks, String packageName) = 2; // returns via callbacks.onUnregistered() + oneway void getConfigurationSnapshot(IPhenotypeCallbacks callbacks, String packageName, String user) = 3; // returns via callbacks.onConfiguration() + oneway void commitToConfiguration(IPhenotypeCallbacks callbacks, String snapshotToken) = 4; // returns via callbacks.onCommitedToConfiguration() + oneway void getExperimentTokens(IPhenotypeCallbacks callbacks, String packageName, String logSourceName) = 5; // returns via callbacks.onExperimentTokens() + oneway void getDogfoodsToken(IPhenotypeCallbacks callbacks) = 6; // returns via callbacks.onDogfoodsToken() + oneway void setDogfoodsToken(IPhenotypeCallbacks callbacks, in byte[] p1) = 7; // returns via callbacks.onDogfoodsTokenSet() + oneway void getFlag(IPhenotypeCallbacks callbacks, String packageName, String name, int type) = 8; // returns via callbacks.onFlag() + oneway void getCommitedConfiguration(IPhenotypeCallbacks callbacks, String packageName) = 9; // returns via callbacks.onCommittedConfiguration() + oneway void getConfigurationSnapshot2(IPhenotypeCallbacks callbacks, String packageName, String user, String p3) = 10; // returns via callbacks.onConfiguration() + oneway void syncAfterOperation(IPhenotypeCallbacks callbacks, String packageName, long version) = 11; // returns via callbacks.onSyncFinished() + oneway void registerSync(IPhenotypeCallbacks callbacks, String packageName, int version, in String[] p3, in byte[] p4, String p5, String p6) = 12; // returns via callbacks.onConfiguration() + oneway void setFlagOverrides(IPhenotypeCallbacks callbacks, String packageName, String user, String flagName, int flagType, int flagDataType, String flagValue) = 13; // returns via callbacks.onFlagOverridesSet() + oneway void deleteFlagOverrides(IPhenotypeCallbacks callbacks, String packageName, String user, String flagName) = 14; // returns via callbacks.onFlagOverrides() + oneway void listFlagOverrides(IPhenotypeCallbacks callbacks, String packageName, String user, String flagName) = 15; // returns via callbacks.onFlagOverrides() + + oneway void clearFlagOverrides(IPhenotypeCallbacks callbacks, String packageName, String user) = 17; // returns via callbacks.onFlagOverridesSet() + oneway void bulkRegister(IPhenotypeCallbacks callbacks, in RegistrationInfo[] infos) = 18; // returns via callbacks.onRegister() + oneway void setAppSpecificProperties(IPhenotypeCallbacks callbacks, String packageName, in byte[] p2) = 19; // returns via callbacks.onAppSpecificPropertiesSet() + + oneway void getServingVersion(IPhenotypeCallbacks callbacks) = 21; // returns via callbacks.onServingVersion() + oneway void getExperimentTokensForLogging(IPhenotypeCallbacks callbacks, String packageName, String logSourceName, String p3, String clientPackageName) = 22; // returns via callbacks.onExperimentTokens() + oneway void syncAllAfterOperation(IPhenotypeCallbacks callbacks, long p1) = 23; // returns via callbacks.onSyncFinished() + oneway void setRuntimeProperties(IStatusCallback callbacks, String p1, in byte[] p2) = 24; +// oneway void setExternalExperiments(IStatusCallback callbacks, String p1, in List p2) = 25; +} diff --git a/play-services-api/src/main/java/com/google/android/gms/phenotype/RegistrationInfo.java b/play-services-api/src/main/java/com/google/android/gms/phenotype/RegistrationInfo.java new file mode 100644 index 00000000..7b9f6cd1 --- /dev/null +++ b/play-services-api/src/main/java/com/google/android/gms/phenotype/RegistrationInfo.java @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2021 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.phenotype; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class RegistrationInfo extends AutoSafeParcelable { + @Field(1) + public String packageName; + @Field(2) + public int version; + @Field(3) + public String[] field3; + @Field(4) + public byte[] field4; + @Field(5) + public boolean weak; + @Field(6) + public int[] field6; + @Field(7) + public String clientPackageName; + + public static final Creator CREATOR = new AutoCreator<>(RegistrationInfo.class); +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt b/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt new file mode 100644 index 00000000..fff8154e --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/phenotype/PhenotypeService.kt @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2020 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.phenotype + +import android.os.Parcel +import android.util.Log +import com.google.android.gms.common.api.Status +import com.google.android.gms.common.api.internal.IStatusCallback +import com.google.android.gms.common.internal.GetServiceRequest +import com.google.android.gms.common.internal.IGmsCallbacks +import com.google.android.gms.phenotype.* +import com.google.android.gms.phenotype.internal.IPhenotypeCallbacks +import com.google.android.gms.phenotype.internal.IPhenotypeService +import org.microg.gms.BaseService +import org.microg.gms.common.GmsService +import org.microg.gms.common.PackageUtils +import org.microg.gms.utils.warnOnTransactionIssues + +private const val TAG = "PhenotypeService" + +class PhenotypeService : BaseService(TAG, GmsService.PHENOTYPE) { + override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest?, service: GmsService?) { + val packageName = PackageUtils.getAndCheckCallingPackage(this, request?.packageName) + callback.onPostInitComplete(0, PhenotypeServiceImpl(packageName).asBinder(), null) + } +} + +class PhenotypeServiceImpl(val packageName: String?) : IPhenotypeService.Stub() { + override fun register(callbacks: IPhenotypeCallbacks, packageName: String?, version: Int, p3: Array?, p4: ByteArray?) { + Log.d(TAG, "register($packageName, $version, $p3, $p4)") + callbacks.onRegistered(Status.SUCCESS) + } + + override fun weakRegister(callbacks: IPhenotypeCallbacks, packageName: String?, version: Int, p3: Array?, p4: IntArray?, p5: ByteArray?) { + Log.d(TAG, "weakRegister($packageName, $version, $p3, $p4, $p5)") + callbacks.onWeakRegistered(Status.SUCCESS) + } + + override fun unregister(callbacks: IPhenotypeCallbacks, packageName: String?) { + Log.d(TAG, "unregister($packageName)") + callbacks.onUnregistered(Status.SUCCESS) + } + + override fun getConfigurationSnapshot(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?) { + getConfigurationSnapshot2(callbacks, packageName, user, null) + } + + override fun commitToConfiguration(callbacks: IPhenotypeCallbacks, snapshotToken: String?) { + Log.d(TAG, "commitToConfiguration($snapshotToken)") + callbacks.onCommitedToConfiguration(Status.SUCCESS) + } + + override fun getExperimentTokens(callbacks: IPhenotypeCallbacks, packageName: String?, logSourceName: String?) { + getExperimentTokensForLogging(callbacks, packageName, logSourceName, null, this.packageName) + } + + override fun getDogfoodsToken(callbacks: IPhenotypeCallbacks) { + Log.d(TAG, "getDogfoodsToken()") + callbacks.onDogfoodsToken(Status.SUCCESS, DogfoodsToken()) + } + + override fun setDogfoodsToken(callbacks: IPhenotypeCallbacks, p1: ByteArray?) { + Log.d(TAG, "setDogfoodsToken($p1)") + callbacks.onDogfoodsTokenSet(Status.SUCCESS) + } + + override fun getFlag(callbacks: IPhenotypeCallbacks, packageName: String?, name: String?, type: Int) { + Log.d(TAG, "setDogfoodsToken($packageName, $name, $type)") + callbacks.onFlag(Status.SUCCESS, null) + } + + override fun getCommitedConfiguration(callbacks: IPhenotypeCallbacks, packageName: String?) { + Log.d(TAG, "getCommitedConfiguration($packageName)") + callbacks.onCommittedConfiguration(Status.SUCCESS, Configurations().apply { + field4 = emptyArray() + }) + } + + override fun getConfigurationSnapshot2(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?, p3: String?) { + Log.d(TAG, "getConfigurationSnapshot2($packageName, $user, $p3)") + callbacks.onConfiguration(Status.SUCCESS, Configurations().apply { + field4 = emptyArray() + }) + } + + override fun syncAfterOperation(callbacks: IPhenotypeCallbacks, packageName: String?, version: Long) { + Log.d(TAG, "syncAfterOperation($packageName, $version)") + callbacks.onSyncFinished(Status.SUCCESS, version) + } + + override fun registerSync(callbacks: IPhenotypeCallbacks, packageName: String?, version: Int, p3: Array?, p4: ByteArray?, p5: String?, p6: String?) { + Log.d(TAG, "registerSync($packageName, $version, $p3, $p4, $p5, $p6)") + callbacks.onConfiguration(Status.SUCCESS, Configurations().apply { + field4 = emptyArray() + }) + } + + override fun setFlagOverrides(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?, flagName: String?, flagType: Int, flagDataType: Int, flagValue: String?) { + Log.d(TAG, "setFlagOverrides($packageName, $user, $flagName, $flagDataType, $flagType, $flagDataType, $flagValue)") + callbacks.onFlagOverridesSet(Status.SUCCESS) + } + + override fun deleteFlagOverrides(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?, flagName: String?) { + Log.d(TAG, "deleteFlagOverrides($packageName, $user, $flagName)") + callbacks.onFlagOverrides(Status.SUCCESS, FlagOverrides()) + } + + override fun listFlagOverrides(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?, flagName: String?) { + Log.d(TAG, "listFlagOverrides($packageName, $user, $flagName)") + callbacks.onFlagOverrides(Status.SUCCESS, FlagOverrides()) + } + + override fun clearFlagOverrides(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?) { + Log.d(TAG, "clearFlagOverrides($packageName, $user)") + callbacks.onFlagOverridesSet(Status.SUCCESS) + } + + override fun bulkRegister(callbacks: IPhenotypeCallbacks, infos: Array?) { + Log.d(TAG, "bulkRegister($infos)") + callbacks.onRegistered(Status.SUCCESS) + } + + override fun setAppSpecificProperties(callbacks: IPhenotypeCallbacks, packageName: String?, p2: ByteArray?) { + Log.d(TAG, "setAppSpecificProperties($packageName, $p2)") + callbacks.onAppSpecificPropertiesSet(Status.SUCCESS) + } + + override fun getServingVersion(callbacks: IPhenotypeCallbacks) { + Log.d(TAG, "getServingVersion()") + callbacks.onServingVersion(Status.SUCCESS, 1) + } + + override fun getExperimentTokensForLogging(callbacks: IPhenotypeCallbacks, packageName: String?, user: String?, p3: String?, clientPackageName: String?) { + Log.d(TAG, "getExperimentTokens($packageName, $user, $p3, $clientPackageName)") + callbacks.onExperimentTokens(Status.SUCCESS, ExperimentTokens().apply { + field2 = "" + }) + } + + override fun syncAllAfterOperation(callbacks: IPhenotypeCallbacks?, p1: Long) { + Log.d(TAG, "Not yet implemented: syncAllAfterOperation") + } + + override fun setRuntimeProperties(callbacks: IStatusCallback?, p1: String?, p2: ByteArray?) { + Log.d(TAG, "Not yet implemented: setRuntimeProperties") + } + + override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean = + warnOnTransactionIssues(code, reply, flags, TAG) { super.onTransact(code, data, reply, flags) } +} diff --git a/play-services-phenotype/src/main/java/com/google/android/gms/phenotype/ExperimentTokens.java b/play-services-phenotype/src/main/java/com/google/android/gms/phenotype/ExperimentTokens.java new file mode 100644 index 00000000..22c637e2 --- /dev/null +++ b/play-services-phenotype/src/main/java/com/google/android/gms/phenotype/ExperimentTokens.java @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2020 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.phenotype; + +import androidx.annotation.NonNull; +import org.microg.safeparcel.AutoSafeParcelable; + +public class ExperimentTokens extends AutoSafeParcelable { + @Field(2) + public String field2; + @Field(3) + public byte[] direct; + @Field(4) + public byte[][] gaia; + @Field(5) + public byte[][] pseudo; + @Field(6) + public byte[][] always; + @Field(7) + public byte[][] other; + @Field(8) + public int[] weak; + @Field(9) + public byte[][] directs; + @Field(10) + public int[] genericDimensions; + @Field(11) + public byte[][] external; + + public static final Creator CREATOR = findCreator(ExperimentTokens.class); +}