Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit e73704f7 authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

ads-identifier: Add most of the server side logic

Except we don't persist, state is not shared accross apps and tracking is set to limited by default
parent e6a443ac
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -29,4 +29,8 @@ android {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }

    lintOptions {
        disable 'MissingTranslation'
    }
}
+113 −9
Original line number Diff line number Diff line
@@ -5,30 +5,134 @@
package org.microg.gms.ads.identifier

import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.core.os.bundleOf
import com.google.android.gms.ads.identifier.internal.IAdvertisingIdService
import org.microg.gms.common.PackageUtils
import java.util.UUID

const val TAG = "AdvertisingId"
const val EMPTY_AD_ID = "00000000-0000-0000-0000-000000000000"

class AdvertisingIdService : Service() {
    override fun onBind(intent: Intent): IBinder? {
        return AdvertisingIdServiceImpl().asBinder()
        return AdvertisingIdServiceImpl(this).asBinder()
    }
}

class MemoryAdvertisingIdConfiguration(context: Context) : AdvertisingIdConfiguration(context) {
    override val adTrackingLimitedPerApp: MutableMap<Int, Boolean> = hashMapOf()
    override var adTrackingLimitedGlobally: Boolean = true
    override var debugLogging: Boolean = false
    override var adId: String = EMPTY_AD_ID
    override var debugAdId: String = EMPTY_AD_ID

    init {
        resetAdvertisingId()
    }
}

abstract class AdvertisingIdConfiguration(private val context: Context) {
    abstract val adTrackingLimitedPerApp: MutableMap<Int, Boolean>
    abstract var adTrackingLimitedGlobally: Boolean
    abstract var debugLogging: Boolean
    abstract var adId: String
    abstract var debugAdId: String

    fun isAdTrackingLimitedForApp(uid: Int): Boolean {
        if (adTrackingLimitedGlobally) return true
        return adTrackingLimitedPerApp[uid] ?: false
    }

    fun resetAdvertisingId(): String {
        adId = UUID.randomUUID().toString()
        debugAdId = UUID.randomUUID().toString().dropLast(12) + "10ca1ad1abe1"
        return if (debugLogging) debugAdId else adId
    }

    fun getAdvertisingIdForApp(uid: Int): String {
        if (isAdTrackingLimitedForApp(uid)) return EMPTY_AD_ID
        try {
            val packageNames = context.packageManager.getPackagesForUid(uid) ?: return EMPTY_AD_ID
            for (packageName in packageNames) {
                val applicationInfo = context.packageManager.getApplicationInfo(packageName, 0)
                if (applicationInfo.targetSdkVersion > 33) {
                    if (context.packageManager.checkPermission("com.google.android.gms.permission.AD_ID", packageName) == PackageManager.PERMISSION_DENIED) {
                        throw SecurityException("Permission not granted")
                    }
                }
            }
        } catch (e: Exception) {
            Log.w(TAG, "Permission check failed", e)
            return EMPTY_AD_ID
        }
        val adId = if (debugLogging) debugAdId else adId
        return adId.ifEmpty { resetAdvertisingId() }
    }
}

class AdvertisingIdServiceImpl(private val context: Context) : IAdvertisingIdService.Stub() {
    private val configuration = MemoryAdvertisingIdConfiguration(context)

class AdvertisingIdServiceImpl : IAdvertisingIdService.Stub() {
    override fun getAdvertisingId(): String {
        return "00000000-0000-0000-0000-000000000000"
        return configuration.getAdvertisingIdForApp(Binder.getCallingUid())
    }

    override fun isAdTrackingLimited(ignored: Boolean): Boolean {
        return configuration.isAdTrackingLimitedForApp(Binder.getCallingUid())
    }

    override fun resetAdvertisingId(packageName: String): String {
        PackageUtils.checkPackageUid(context, packageName, getCallingUid())
        PackageUtils.assertExtendedAccess(context)
        return configuration.resetAdvertisingId()
    }

    override fun setAdTrackingLimitedGlobally(packageName: String, limited: Boolean) {
        PackageUtils.checkPackageUid(context, packageName, getCallingUid())
        PackageUtils.assertExtendedAccess(context)
        configuration.adTrackingLimitedGlobally = limited
    }

    override fun setDebugLoggingEnabled(packageName: String, enabled: Boolean): String {
        PackageUtils.checkPackageUid(context, packageName, getCallingUid())
        PackageUtils.assertExtendedAccess(context)
        configuration.debugLogging = enabled
        return advertisingId
    }

    override fun isDebugLoggingEnabled(): Boolean {
        return configuration.debugLogging
    }

    override fun isAdTrackingLimitedGlobally(): Boolean {
        PackageUtils.assertExtendedAccess(context)
        return configuration.adTrackingLimitedGlobally
    }

    override fun setAdTrackingLimitedForApp(uid: Int, limited: Boolean) {
        PackageUtils.assertExtendedAccess(context)
        configuration.adTrackingLimitedPerApp[uid] = limited
    }

    override fun isAdTrackingLimited(defaultHint: Boolean): Boolean {
        return true
    override fun resetAdTrackingLimitedForApp(uid: Int) {
        PackageUtils.assertExtendedAccess(context)
        configuration.adTrackingLimitedPerApp.remove(uid)
    }

    override fun generateAdvertisingId(packageName: String): String {
        return advertisingId // Ad tracking limited
    override fun getAllAppsLimitedAdTrackingConfiguration(): Bundle {
        PackageUtils.assertExtendedAccess(context)
        return bundleOf(*configuration.adTrackingLimitedPerApp.map { it.key.toString() to it.value }.toTypedArray())
    }

    override fun setAdTrackingLimited(packageName: String, limited: Boolean) {
        // Ignored, sorry :)
    override fun getAdvertisingIdForApp(uid: Int): String {
        PackageUtils.assertExtendedAccess(context)
        return configuration.getAdvertisingIdForApp(uid)
    }
}
+11 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ SPDX-FileCopyrightText: 2023 microG Project Team
  ~ SPDX-License-Identifier: Apache-2.0
  -->

<resources>
    <string name="perm_ad_id_label">Advertising ID Permission</string>
    <string name="perm_ad_id_description">Allows a publisher app to access a valid advertising ID directly or indirectly.</string>
    <string name="perm_ad_id_notification_label">Advertising ID notification</string>
    <string name="perm_ad_id_notification_description">Allows an app to receive a notification when the advertising ID or limit ad tracking preference of the user is updated.</string>
</resources>
 No newline at end of file
+12 −3
Original line number Diff line number Diff line
package com.google.android.gms.ads.identifier.internal;

import android.os.Bundle;

interface IAdvertisingIdService {
    String getAdvertisingId() = 0;
    boolean isAdTrackingLimited(boolean defaultHint) = 1;
    String generateAdvertisingId(String packageName) = 2;
    void setAdTrackingLimited(String packageName, boolean limited) = 3;
    boolean isAdTrackingLimited(boolean ignored) = 1;
    String resetAdvertisingId(String packageName) = 2;
    void setAdTrackingLimitedGlobally(String packageName, boolean limited) = 3;
    String setDebugLoggingEnabled(String packageName, boolean enabled) = 4;
    boolean isDebugLoggingEnabled() = 5;
    boolean isAdTrackingLimitedGlobally() = 6;
    void setAdTrackingLimitedForApp(int uid, boolean limited) = 7;
    void resetAdTrackingLimitedForApp(int uid) = 8;
    Bundle getAllAppsLimitedAdTrackingConfiguration() = 9; // Map packageName -> Boolean
    String getAdvertisingIdForApp(int uid) = 10;
}
+39 −4
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2013-2019 microG Project Team
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,6 +58,17 @@
        android:label="@string/permission_service_writely_label"
        android:protectionLevel="dangerous" />

    <permission
        android:name="com.google.android.gms.permission.AD_ID"
        android:label="@string/perm_ad_id_label"
        android:description="@string/perm_ad_id_description"
        android:protectionLevel="normal" />
    <permission
        android:name="com.google.android.gms.permission.AD_ID_NOTIFICATION"
        android:label="@string/perm_ad_id_notification_label"
        android:description="@string/perm_ad_id_notification_description"
        android:protectionLevel="normal" />

    <permission
        android:name="org.microg.gms.STATUS_BROADCAST"
        android:label="@string/perm_status_broadcast_label"
@@ -161,8 +171,7 @@
            </intent-filter>
        </service>

        <service
            android:name="org.microg.gms.wearable.location.WearableLocationService">
        <service android:name="org.microg.gms.wearable.location.WearableLocationService">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
                <data
@@ -576,6 +585,32 @@
            </intent-filter>
        </service>

        <!-- Help -->

        <service
            android:name="org.microg.gms.googlehelp.GoogleHelpService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.googlehelp.service.GoogleHelpService.START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

        <activity
            android:name="org.microg.gms.googlehelp.ui.GoogleHelpRedirectActivity"
            android:process=":ui"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.googlehelp.HELP" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
        </activity>

        <!-- Other -->

        <service