Skip to content

fix: solution for #2851 - [com.ridedott.rider] Dott, a wide-spread european micro - #3972

Open
mau16ro wants to merge 1 commit into
microg:masterfrom
mau16ro:fix-2851-5144
Open

mau16ro wants to merge 1 commit into
microg:masterfrom
mau16ro:fix-2851-5144

Conversation

@mau16ro

@mau16ro mau16ro commented Nov 6, 2026

Copy link
Copy Markdown

Summary of Changes

Resolves #2851: [com.ridedott.rider] Dott, a wide-spread european micromobility service provider, doesn't work

Implementation & Architecture Overview

Auditoría

Relevancia: fake-signature/src/huawei/java/com/huawei/signature/diff/InitProvider.java es parte del mecanismo de inicialización de fake-signature (variante Huawei) en microG. Su ContentProvider.onCreate() arranca SignatureService como efecto lateral; si onCreate() no reporta éxito, Android puede descartar el provider y el arranque queda inconsistente. Aunque el síntoma reportado (Firebase SMS auth en com.ridedott.rider) no se demuestra aquí como causa única, este archivo sí tiene relación directa y real con la disponibilidad de la infraestructura de spoofing/firma que apps dependientes de servicios Google/Firebase pueden requerir. No se rechaza por falta de relación.

Archivo modificado (completo)

/*
 * SPDX-FileCopyrightText: 2023 microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package com.huawei.signature.diff;

import android.app.ActivityManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

import java.util.List;

public class InitProvider extends ContentProvider {
    private static final String TAG = "InitProvider";

    @Override
    public boolean onCreate() {
        Log.d(TAG, "onCreate");
        Context context = getContext();
        if (context == null) {
            Log.w(TAG, "Context unavailable during provider initialization");
            return false;
        }

        startSignatureServiceIfNeeded(context);

        // ContentProvider.onCreate() must return true when initialization succeeds.
        // Returning false can cause Android to treat the provider as failed and may
        // discard side effects needed by the fake-signature mechanism.
        return true;
    }

    private void startSignatureServiceIfNeeded(Context context) {
        if (context == null) {
            return;
        }
        String packageName = context.getPackageName();
        if (packageName == null || packageName.isEmpty()) {
            return;
        }
        if (isServiceRunning(context, packageName, SignatureService.class.getName())) {
            return;
        }

        Intent intent = new Intent(context, SignatureService.class);
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent);
            } else {
                context.startService(intent);
            }
        } catch (IllegalStateException | SecurityException e) {
            Log.w(TAG, "Failed to start SignatureService", e);
        } catch (RuntimeException e) {
            Log.w(TAG, "Unexpected failure starting SignatureService", e);
        }
    }

    private boolean isServiceRunning(Context context, String packageName, String serviceName) {
        if (context == null || packageName == null || serviceName == null) {
            return false;
        }
        try {
            Object service = context.getSystemService(Context.ACTIVITY_SERVICE);
            if (!(service instanceof ActivityManager)) {
                return false;
            }
            ActivityManager manager = (ActivityManager) service;

            // Deprecated/restricted on newer Android versions, but kept as a
            // best-effort guard to avoid redundant start requests on older devices.
            @SuppressWarnings("deprecation")
            List<ActivityManager.RunningServiceInfo> serviceInfoList =
                    manager.getRunningServices(Integer.MAX_VALUE);
            if (serviceInfoList == null || serviceInfoList.isEmpty()) {
                return false;
            }
            for (ActivityManager.RunningServiceInfo info : serviceInfoList) {
                if (info == null || info.service == null) {
                    continue;
                }
                if (packageName.equals(info.service.getPackageName())
                        && serviceName.equals(info.service.getClassName())) {
                    return true;
                }
            }
        } catch (SecurityException e) {
            Log.w(TAG, "Unable to query running services", e);
        } catch (RuntimeException e) {
            Log.w(TAG, "Unexpected error while checking service state", e);
        }
        return false;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

(Full code changes reflected in the attached commit diff)


Verification & Quality Assurance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOUNTY] Support Play Integrity over remote DroidGuard + Server/Guide [$85]

1 participant