훅 메커니즘 학습(3) - weishu 블로그 학습 노트(AMS & PMS 훅)
1: 훅 AMS
1.1 이론적 기초인ActivityManagerNative는ActivityManagerService라는 원격 대상의Binder 프록시 대상이다.AMS와 접촉해야 할 때마다 이 프록시 대상이 드라이브를 통해 IPC 호출을 완성해야 한다.예를 들어 Activity를 시작할 때 Activity ManagerNative를 통해getDefault() .startActivity()가 Activity 시작 요청을 Activity Manager Service에 전달
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // ...  
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        // ----------------look here!!!!!!!!!!!!!!!!!!!
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
    }
    return null;
}
  ActivityManagerNative.getDefault (): gDefault이 호출되었습니다.get()
static public IActivityManager getDefault()
 {
     return gDefault.get();
 }
  gDefault: gDefault는 하나의 예입니다.저장된 개체는 Iactivity Manager 단일 예입니다.실제로 ActivityManagerProxy가 반환됩니다.Ibinder b는 누드 Binder 객체로, 원격의 Binder 객체가 Binder 드라이브를 통해 전환된 후 App 프로세스로 되돌아오는 객체입니다.
private static final Singleton gDefault = new Singleton() {
      protected IActivityManager create() {
           IBinder b = ServiceManager.getService("activity");
     // IBinder b  Binder , Binder Binder App  。
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
          }
            IActivityManager am = asInterface(b);
            // ActivityManagerProxy
           if (false) {
               Log.v("ActivityManager", "default service = " + am);
           }
            return am;
       }
    };
}
    1.2 훅 AMS에서 우리가 사용하는 AMS는 실제로Activity Manager Proxy이다. 훅을 떨어뜨리려면 훅이 gDefault에 단일 대상을 저장하면 된다.gDefault를 통해 얻을 수 있는 단일 예를 훅 대상으로 합니다. 싱글튼의 mInstance 필드를 훅 대상으로 설정해야 합니다.
Class> activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
//   gDefault  ,  
Field gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
gDefaultField.setAccessible(true);
Object gDefault = gDefaultField.get(null);
// 4.x gDefault  android.util.Singleton ;  
Class> singleton = Class.forName("android.util.Singleton");
Field mInstanceField = singleton.getDeclaredField("mInstance");
mInstanceField.setAccessible(true);
// ActivityManagerNative  gDefault  IActivityManager 
Object rawIActivityManager = mInstanceField.get(gDefault);
//  ,  ,  
Class> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
        new Class>[] { iActivityManagerInterface }, new IActivityManagerHandler(rawIActivityManager));
mInstanceField.set(gDefault, proxy);
  2. 훅 PMS
ContextImpl.getPackage Manager() PMS는 ContextImpl을 통해 가져옵니다.getPackage Manager에서 가져옵니다. mPackage Manager는 정적 필드가 아닙니다.그래서 이게 좋은 훅이 아니라 포장 대상인 Application Package Manager로 돌아가는 거예요.
public PackageManager getPackageManager() {
    if (mPackageManager != null) {
        return mPackageManager;
    }
    IPackageManager pm = ActivityThread.getPackageManager();
    if (pm != null) {
        // Doesn't matter if we make more than one instance.
        return (mPackageManager = new ApplicationPackageManager(this, pm));
    }
    return null;
}
  ActivityThread.getPackage Manager () 는 서비스 매니저를 사용하여 IPackager Manager sPackage Manager를 가져옵니다.Activity Thead의 정적 필드입니다. 이 정적 필드를 훅에서 떨어뜨려서 훅이 PMS를 떨어뜨리는 목적을 달성합니다.Context 클래스의 getPackage Manager 방법을 통해 얻을 수 있는ApplicationPackage Manager 대상의 mPM 필드도 Hook이 필요합니다.
public static IPackageManager getPackageManager() {
    if (sPackageManager != null) {
        return sPackageManager;
    }
    IBinder b = ServiceManager.getService("package");
    sPackageManager = IPackageManager.Stub.asInterface(b);
    return sPackageManager;
}
  훅 코드
//  ActivityThread 
Class> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
//  ActivityThread  sPackageManager
Field sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager");
sPackageManagerField.setAccessible(true);
Object sPackageManager = sPackageManagerField.get(currentActivityThread);
//  ,  
Class> iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager");
Object proxy = Proxy.newProxyInstance(iPackageManagerInterface.getClassLoader(),
        new Class>[] { iPackageManagerInterface },
        new HookHandler(sPackageManager));
// 1.  ActivityThread  sPackageManager  
sPackageManagerField.set(currentActivityThread, proxy);
// 2.   ApplicationPackageManager  mPM 
PackageManager pm = context.getPackageManager();
Field mPmField = pm.getClass().getDeclaredField("mPM");
mPmField.setAccessible(true);
mPmField.set(pm, proxy);
                이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.