4 votes

Comment identifier ce qui permet d'accéder aux méthodes cachées

J'ai une application Flutter qui génère beaucoup d'avertissements d'API cachés :

Accessing hidden method Landroid/view/accessibility/AccessibilityNodeInfo;->getSourceNodeId()J (greylist,test-api, reflection, allowed)
Accessing hidden method Landroid/view/accessibility/AccessibilityRecord;->getSourceNodeId()J (greylist, reflection, allowed)
Accessing hidden field Landroid/view/accessibility/AccessibilityNodeInfo;->mChildNodeIds:Landroid/util/LongArray; (greylist, reflection, allowed)
Accessing hidden method Landroid/util/LongArray;->get(I)J (greylist, reflection, allowed)
...
Accessing hidden method Landroid/database/sqlite/SQLiteDatabase;-><clinit>()V (blacklist, linking, denied)
Accessing hidden field Landroid/database/sqlite/SQLiteDatabase;->DEBUG_CLOSE_IDLE_CONNECTIONS:Z (greylist-max-o, linking, denied)
Accessing hidden field Landroid/database/sqlite/SQLiteDatabase;->sActiveDatabases:Ljava/util/WeakHashMap; (greylist-max-o, linking, denied)
Accessing hidden field Landroid/database/sqlite/SQLiteDatabase;->CONFLICT_VALUES:[Ljava/lang/String; (greylist, linking, allowed)

Et ainsi de suite. Je n'ai pas écrit de code pour utiliser le système Android. SQLiteDatabase o AccessibilityNodeInfo mais cela ne fournit aucune information sur la partie du code qui appelle ces méthodes cachées. Cela pourrait être dans Flutter, ou dans l'un des nombreux plugins que je possède. À part mutiler mon code pour supprimer ces plugins, y a-t-il quelque chose que je puisse faire pour découvrir quel code appelle ces méthodes ? Par exemple, pour obtenir une trace de la pile.

Est-ce qu'Android dispose d'une option permettant de planter les accès aux champs cachés plutôt que de simplement les enregistrer, ou quelque chose de similaire ?

3voto

Timmmm Points 9909

Aha, grâce au lien de Mark Keen, j'ai pu créer un fichier personnalisé Application pour mon application Flutter qui enregistre le suivi de la pile pour les violations du mode strict. Créez un MainApplication.kt Kotlin comme ceci :

package com.yourdomain.flutter_app

import android.app.Application
import android.os.StrictMode
import android.os.StrictMode.OnVmViolationListener
import android.os.StrictMode.VmPolicy
import android.os.strictmode.Violation
import android.util.Log
import io.flutter.view.FlutterMain
import java.io.PrintWriter
import java.io.StringWriter
import java.util.concurrent.Executor

class CurrentThreadExecutor : Executor {
    override fun execute(r: Runnable) {
        r.run()
    }
}

class StacktraceLogger : OnVmViolationListener {
    override fun onVmViolation(v: Violation) {
        val sw = StringWriter()
        val pw = PrintWriter(sw)
        v.printStackTrace(pw)

        Log.e("STRICTMODE", sw.toString())
    }
}

class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        val policy = VmPolicy.Builder()
                .detectAll()
                .detectNonSdkApiUsage()
                .penaltyListener(CurrentThreadExecutor(), StacktraceLogger())
                .build()
        StrictMode.setVmPolicy(policy)

        FlutterMain.startInitialization(applicationContext)
    }
}

Et ensuite, pointez votre AndroidManifest.xml à ce sujet :

    <application
        android:name="com.yourdomain.flutter_app.MainApplication"

Ensuite, lorsque vous l'exécutez, vous devriez voir une trace de la pile. Dans ce cas, le AccessibilityNodeInfo semble être un problème de Flutter :

2021-02-20 12:43:11.986 3291-3291/uk.co.timhutt.flutter_app E/STRICTMODE: android.os.strictmode.NonSdkApiUsedViolation: Landroid/view/accessibility/AccessibilityNodeInfo;->getSourceNodeId()J
        at android.os.StrictMode.lambda$static$1(StrictMode.java:416)
        at android.os.-$$Lambda$StrictMode$lu9ekkHJ2HMz0jd3F8K8MnhenxQ.accept(Unknown Source:2)
        at java.lang.Class.getDeclaredMethodInternal(Native Method)
        at java.lang.Class.getPublicMethodRecursive(Class.java:2079)
        at java.lang.Class.getMethod(Class.java:2066)
        at java.lang.Class.getMethod(Class.java:1693)
        at io.flutter.view.AccessibilityViewEmbedder$ReflectionAccessors.<init>(AccessibilityViewEmbedder.java:446)
        at io.flutter.view.AccessibilityViewEmbedder$ReflectionAccessors.<init>(AccessibilityViewEmbedder.java:429)
        at io.flutter.view.AccessibilityViewEmbedder.<init>(AccessibilityViewEmbedder.java:70)
        at io.flutter.view.AccessibilityBridge.<init>(AccessibilityBridge.java:346)
        at io.flutter.embedding.android.FlutterView.attachToFlutterEngine(FlutterView.java:919)
        at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onCreateView(FlutterActivityAndFragmentDelegate.java:294)
        at io.flutter.embedding.android.FlutterActivity.createFlutterView(FlutterActivity.java:520)
        at io.flutter.embedding.android.FlutterActivity.onCreate(FlutterActivity.java:414)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7660)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Mise à jour : les méthodes SQLite

Bizarrement, il n'a toujours pas imprimé de traces de pile pour les erreurs SQLite, mais j'ai remarqué que les premières erreurs concernaient la "réflexion" alors que les autres concernaient la "liaison". Je fais la liaison avec une bibliothèque Rust qui utilise une copie groupée de SQLite - en utilisant cette dépendance :

rusqlite = { version = "0.24.2", features = ["bundled"] }

Et ensuite le charger dans Dart :

final DynamicLibrary mapRenderNative = Platform.isAndroid
    ? DynamicLibrary.open("libmap_render.so")
    : DynamicLibrary.process();

Quand j'ai commenté cette ligne et que j'ai exécuté wgradle clean (nécessaire semble-t-il), les erreurs ont disparu ! Wtf ? Il semble qu'Android intercepte dlopen() et vérifie si vous établissez un lien avec l'un des symboles interdits.

Mais la chose vraiment bizarre est que mon libmap_render.so n'a pas lien avec SQLite (parce qu'il est lié statiquement à lui) :

>llvm-readelf -d target\aarch64-linux-android\debug\libmap_render.so
Dynamic section at offset 0x52768 contains 23 entries:
  Tag                Type           Name/Value
  0x0000000000000001 (NEEDED)       Shared library: [libdl.so]
  0x0000000000000001 (NEEDED)       Shared library: [libc.so]
  0x000000000000001e (FLAGS)        BIND_NOW
  0x000000006ffffffb (FLAGS_1)      NOW
  0x0000000000000007 (RELA)         0x988
  0x0000000000000008 (RELASZ)       9768 (bytes)
  0x0000000000000009 (RELAENT)      24 (bytes)
  0x000000006ffffff9 (RELACOUNT)    405
  0x0000000000000017 (JMPREL)       0x2fb0
  0x0000000000000002 (PLTRELSZ)     888 (bytes)
  0x0000000000000003 (PLTGOT)       0x54940
  0x0000000000000014 (PLTREL)       RELA
  0x0000000000000006 (SYMTAB)       0x308
  0x000000000000000b (SYMENT)       24 (bytes)
  0x0000000000000005 (STRTAB)       0x79c
  0x000000000000000a (STRSZ)        491 (bytes)
  0x000000006ffffef5 (GNU_HASH)     0x778
  0x000000000000001a (FINI_ARRAY)   0x54758
  0x000000000000001c (FINI_ARRAYSZ) 16 (bytes)
  0x000000006ffffff0 (VERSYM)       0x6e0
  0x000000006ffffffe (VERNEED)      0x734
  0x000000006fffffff (VERNEEDNUM)   2
  0x0000000000000000 (NULL)         0x0

Je n'ai pas non plus trouvé de symboles SQLite dans la table des symboles, des relocalisations, etc. Je n'ai donc littéralement aucune idée de ce que fait Android. Est-ce qu'il scanne littéralement le binaire ?

Je vais ouvrir une nouvelle question pour cela, je pense.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X