diff --git a/play-services-api/src/main/java/com/google/android/gms/facs/cache/GetActivityControlsSettingsResult.java b/play-services-api/src/main/java/com/google/android/gms/facs/cache/GetActivityControlsSettingsResult.java index 6be6139af6..ae68810821 100644 --- a/play-services-api/src/main/java/com/google/android/gms/facs/cache/GetActivityControlsSettingsResult.java +++ b/play-services-api/src/main/java/com/google/android/gms/facs/cache/GetActivityControlsSettingsResult.java @@ -5,9 +5,29 @@ package com.google.android.gms.facs.cache; -import org.microg.safeparcel.AutoSafeParcelable; +import android.os.Parcel; -public class GetActivityControlsSettingsResult extends AutoSafeParcelable { +import androidx.annotation.NonNull; + +import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable; +import com.google.android.gms.common.internal.safeparcel.SafeParcelable; +import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter; + +@SafeParcelable.Class +public class GetActivityControlsSettingsResult extends AbstractSafeParcelable { + @Field(value = 1) + public byte[] bytes; + + @Constructor + public GetActivityControlsSettingsResult(@Param(1) byte[] data) { + this.bytes = data; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + CREATOR.writeToParcel(this, dest, flags); + } + + public static final SafeParcelableCreatorAndWriter CREATOR = findCreator(GetActivityControlsSettingsResult.class); - public static final Creator CREATOR = new AutoCreator<>(GetActivityControlsSettingsResult.class); } diff --git a/play-services-core-proto/src/main/proto/controlsettings.proto b/play-services-core-proto/src/main/proto/controlsettings.proto new file mode 100644 index 0000000000..b3d421552d --- /dev/null +++ b/play-services-core-proto/src/main/proto/controlsettings.proto @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +option java_outer_classname = "ControlsSettings"; + +option java_package = "org.microg.gms.udc"; +option java_multiple_files = true; + +message ActivityControlsSettings { + repeated ActivityControlItem items = 1; + optional GlobalSettings global = 2; +} + +message ActivityControlItem { + optional int32 id = 1; + optional int32 enabled = 2; + optional int32 allowed = 3; + optional int32 forced = 4; +} + +message GlobalSettings { + optional int32 enabled = 1; + optional int32 allowed = 2; +} \ No newline at end of file diff --git a/play-services-core/src/main/kotlin/org/microg/gms/udc/ActivityControlSettings.kt b/play-services-core/src/main/kotlin/org/microg/gms/udc/ActivityControlSettings.kt new file mode 100644 index 0000000000..662a823194 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/udc/ActivityControlSettings.kt @@ -0,0 +1,42 @@ +/** + * SPDX-FileCopyrightText: 2025 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.udc + +private enum class Controls(val id: Int) { + APP_USAGE_TIME(1), + SCREEN_TIME_LIMIT(2), + APP_INSTALL(3), + IN_APP_PURCHASE(4), + LOCATION_SHARING(5), + CALL_LOG(6), + CONTACT(9), + CALENDAR(10), + CAMERA(15), + MICROPHONE(17), + STORAGE(18), + NOTIFICATION(44), + ACCESSIBILITY_SERVICE(45), + DEVICE_ADMIN(46), + SYSTEM_WINDOW_OVERLAY(48), + SYSTEM_ALERT_WINDOW(61), + FLOATING_WINDOW(80), + PICTURE_IN_PICTURE(94), + SYSTEM_UI_VISIBILITY(95), + BACKGROUND_APP_RESTRICTION(101), + BATTERY_OPTIMIZATION(102) +} + +private val ALLOW_CONTROLS_PACKAGES = mapOf( + Pair("com.google.android.googlequicksearchbox", setOf(Controls.STORAGE, Controls.MICROPHONE, Controls.SYSTEM_WINDOW_OVERLAY)), +) + +fun getAllowControlsByPackage(packageName: String) : ByteArray? { + val controls = ALLOW_CONTROLS_PACKAGES[packageName] ?: return null + return ActivityControlsSettings.build { + items(controls.map { controls -> ActivityControlItem(controls.id, 1, 1, 1) }) + global(GlobalSettings(1, 1)) + }.encode() +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/udc/FacsCacheService.kt b/play-services-core/src/main/kotlin/org/microg/gms/udc/FacsCacheService.kt index 149fece0c5..989bd74a64 100644 --- a/play-services-core/src/main/kotlin/org/microg/gms/udc/FacsCacheService.kt +++ b/play-services-core/src/main/kotlin/org/microg/gms/udc/FacsCacheService.kt @@ -5,27 +5,34 @@ package org.microg.gms.udc +import android.content.Context import android.os.Parcel import android.util.Log import com.google.android.gms.common.api.Status import com.google.android.gms.common.internal.GetServiceRequest import com.google.android.gms.common.internal.IGmsCallbacks import com.google.android.gms.facs.cache.FacsCacheCallOptions +import com.google.android.gms.facs.cache.GetActivityControlsSettingsResult import com.google.android.gms.facs.cache.internal.IFacsCacheCallbacks import com.google.android.gms.facs.cache.internal.IFacsCacheService 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 = "GmsFacsCache" class FacsCacheService : BaseService(TAG, GmsService.FACS_CACHE) { override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest?, service: GmsService?) { - callback.onPostInitComplete(0, FacsCacheServiceImpl().asBinder(), null) + Log.d(TAG, "handleServiceRequest request=${request} ") + val packageName = PackageUtils.getAndCheckCallingPackage(this, request?.packageName) + ?: throw IllegalArgumentException("Missing package name") + callback.onPostInitComplete(0, FacsCacheServiceImpl(this, packageName).asBinder(), null) } } -class FacsCacheServiceImpl : IFacsCacheService.Stub() { +class FacsCacheServiceImpl(val context: Context, val packageName: String) : IFacsCacheService.Stub() { + override fun forceSettingsCacheRefresh(callbacks: IFacsCacheCallbacks, options: FacsCacheCallOptions) { Log.d(TAG, "forceSettingsCacheRefresh") callbacks.onForceSettingsCacheRefreshResult(Status.CANCELED, null) @@ -37,8 +44,10 @@ class FacsCacheServiceImpl : IFacsCacheService.Stub() { } override fun getActivityControlsSettings(callbacks: IFacsCacheCallbacks, options: FacsCacheCallOptions) { - Log.d(TAG, "getActivityControlsSettings") - callbacks.onGetActivityControlsSettingsResult(Status.CANCELED, null) + Log.d(TAG, "getActivityControlsSettings requestPackageName: $packageName, options: $options") + getAllowControlsByPackage(packageName)?.let { + callbacks.onGetActivityControlsSettingsResult(Status.SUCCESS, GetActivityControlsSettingsResult(it)) + } ?: callbacks.onGetActivityControlsSettingsResult(Status.CANCELED, null) } override fun readDeviceLevelSettings(callbacks: IFacsCacheCallbacks) {