ActivityThread 中一些常用的知识点记录

源码 2024-9-15 13:00:20 187 0 来自 中国
ActivityThread:
它管理 应用步调进程 中主线程的实验,调理和实验Activity,广播,
以及ActivityManager 哀求的其他操纵。
简朴的说,可以通过这个类,获取到当前应用的一些信息
TIPS:
(1).可以使用以下的开源代码网站检察源码
http://aosp.opersys.com/xref/android-12.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
(2).也可以通过AndroidStudio 下载SDK Source code  检察
1 代码目次分析

它在源码的目次是在framework下: /frameworks/base/core/java/android/app/
包名为 android.app;
但它有 @hide 标记,则在app无法直接访问,但是可以通过反射获取(如Hook 技能中常用)
package android.app;/** * This manages the execution of the main thread in an * application process, scheduling and executing activities, * broadcasts, and other operations on it as the activity * manager requests. * * {@hide} */public final class ActivityThread extends ClientTransactionHandler        implements ActivityThreadInternal {2. 获取当前应用 currentApplication()

Application application = ActivityThread.currentApplication();即可以获取到当前代码运行到的地方,它所属的 应用.
application.mLoadedApk 直接获取到当前 加载的应用对象
3. 获取当前 已加载的应用(LoadedApk) 对象 (getPackageInfo())

3. 1  资源目次成员变量 mResourcePackages

是一个map, 表现1个大概多个路径.
同时,相当于一个缓存, 后续纵然App 更改了 LoadedApk里的内容,但是在这里生存的对象大概是稳定的.
    @GuardedBy("mResourcesManager")    @UnsupportedAppUsage    final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>();
PS: 尚有别的一个变量mPackages是生存 代码所在的目次
@GuardedBy("mResourcesManager")
@UnsupportedAppUsage
final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>();
3. 2 public 方法

在通过API getPackageInfo 获取 LoadedApk ,由几个public 的方法,参数差别处置惩罚流程略有差别.
都是不公开的,@UnsupportedAppUsage
    public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo, int flags) {}    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, int flags) {}    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo, int flags, int userId) {        public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) {}   3. 3 private 实现方法

内部的私有方法, 会根据packageName 查询 mResourcePackages 实验获取 LoadedApk 对象
假如不存在,大概会创建并生存(当进步程 和 传入的 appinfo 的userId差别时除外!!!)
判定userId的关键代码:
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));重点在于是从哪个进程调用这个方法的, 即UserHandle.myUserId() 的值取决于 !!调用者!! 的进程
私有API(1) 仅仅是获取:
    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,            boolean registerPackage, boolean isSdkSandbox, boolean isCallFromReceiver) {        /* APK_OPTIMIZATION } */        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));        synchronized (mResourcesManager) {            WeakReference<LoadedApk> ref;            if (differentUser || isSdkSandbox) {                // Caching not supported across users and for sdk sandboxes                ref = null;            } else if (includeCode) {                ref = mPackages.get(aInfo.packageName);            } else {                ref = mResourcePackages.get(aInfo.packageName);            }   私有方法API(2): 会举行创建 LoadedApk 并缓存起来 ()
假如缓存中没有,则会根据传入的 appInfo 创建一个新的 loadedApk 对象
当进步程 和 appInfo是同个用户的话, 生存到mResourcePackages
2485    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,2486            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,2487            boolean registerPackage) {2488        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));2489        synchronized (mResourcesManager) {2490            WeakReference<LoadedApk> ref;2491            if (differentUser) {  ////>>>>>>>>>>>>>>>>>> 查抄用户userId2492                // Caching not supported across users2493                ref = null;2494            } else if (includeCode) {2495                ref = mPackages.get(aInfo.packageName);2496            } else {2497                ref = mResourcePackages.get(aInfo.packageName);2498            }24992500            LoadedApk packageInfo = ref != null ? ref.get() : null;25012502            if (packageInfo != null) {2503                if (!isLoadedApkResourceDirsUpToDate(packageInfo, aInfo)) {2504                    List<String> oldPaths = new ArrayList<>();2505                    LoadedApk.makePaths(this, aInfo, oldPaths);2506                    packageInfo.updateApplicationInfo(aInfo, oldPaths);2507                }25082509                return packageInfo; //////>>>>>>>>>>>>>>>>>> 非空则返回2510            }25112512            if (localLOGV) {2513                Slog.v(TAG, (includeCode ? "Loading code package "2514                        : "Loading resource-only package ") + aInfo.packageName2515                        + " (in " + (mBoundApplication != null2516                        ? mBoundApplication.processName : null)2517                        + ")");2518            }25192520            packageInfo =2521                    new LoadedApk(this, aInfo, compatInfo, baseLoader,2522                            securityViolation, includeCode2523                            && (aInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); //////>>创建新的25242525            if (mSystemThread && "android".equals(aInfo.packageName)) {2526                packageInfo.installSystemApplicationInfo(aInfo,2527                        getSystemContext().mPackageInfo.getClassLoader());2528            }25292530            if (differentUser) {2531                // Caching not supported across users2532            } else if (includeCode) {2533                mPackages.put(aInfo.packageName,2534                        new WeakReference<LoadedApk>(packageInfo));2535            } else {2536                mResourcePackages.put(aInfo.packageName,2537                        new WeakReference<LoadedApk>(packageInfo));//////>>做缓存2538            }25392540            return packageInfo;2541        }2542    }3.4 调用 ActivityThread.getPackageInfo() 的地方:

(1) 通过 ApplicationInfo 创建 Context的时候
Context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED);
---> ContextWrapper -> ContextImpl
此中 mApplication 为ApplicationInfo 对象.
//ContextImpl.java    @Override    public Context createApplicationContext(ApplicationInfo application, int flags)            throws NameNotFoundException {        LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),                flags | CONTEXT_REGISTER_PACKAGE);        if (pi != null) {            ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY,                    mAttributionSource.getAttributionTag(),                    mAttributionSource.getNext(),                    null, mToken, new UserHandle(UserHandle.getUserId(application.uid)),                    flags, null, null);            final int displayId = getDisplayId();            final Integer overrideDisplayId = mForceDisplayOverrideInResources                    ? displayId : null;            c.setResources(createResources(mToken, pi, null, overrideDisplayId, null,                    getDisplayAdjustments(displayId).getCompatibilityInfo(), null));            if (c.mResources != null) {                return c;            }        }        throw new PackageManager.NameNotFoundException(                "Application package " + application.packageName + " not found");    }从上面可以看出,会先通过  ActivityThread.getPackageInfo 获取到 LoadedApk 实例对象.
3.5 拓展

ContextImpl 有几个通过差别参数,获取Context 的方法:
这里关注的是createApplicationContext 和 createPackageContextAsUser,
紧张差别在于前者传入 applicationInfo ,而后者是 packageName。
以是,差别会提如今 ActivityThread.getPackageInfo 获取 LoadedApk 对象上,
在根据 packageName查找缓存数组mResourcePackage, 后
假如不存在,前者会根据 applicationInfo 创建对象loadedApk对象,  后者则是通过packageName获取applicationInfo再创建.
//ContextImpl.java 获取Context 的几个方法  @Override    public Context createApplicationContext(ApplicationInfo application, int flags)            throws NameNotFoundException {        LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),                flags | CONTEXT_REGISTER_PACKAGE);        if (pi != null) {            ContextImpl c = new ContextImpl(this, mMainThread, pi, ContextParams.EMPTY,                    mAttributionSource.getAttributionTag(),                    mAttributionSource.getNext(),                    null, mToken, new UserHandle(UserHandle.getUserId(application.uid)),                    flags, null, null);            final int displayId = getDisplayId();            final Integer overrideDisplayId = mForceDisplayOverrideInResources                    ? displayId : null;            c.setResources(createResources(mToken, pi, null, overrideDisplayId, null,                    getDisplayAdjustments(displayId).getCompatibilityInfo(), null));            if (c.mResources != null) {                return c;            }        }        throw new PackageManager.NameNotFoundException(                "Application package " + application.packageName + " not found");    }    @Override    public Context createPackageContext(String packageName, int flags)            throws NameNotFoundException {        return createPackageContextAsUser(packageName, flags, mUser);    }    @Override    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)            throws NameNotFoundException {        if (packageName.equals("system") || packageName.equals("android")) {            // The system resources are loaded in every application, so we can safely copy            // the context without reloading Resources.            return new ContextImpl(this, mMainThread, mPackageInfo, mParams,                    mAttributionSource.getAttributionTag(),                    mAttributionSource.getNext(),                    null, mToken, user, flags, null, null);        }        LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),                flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());        if (pi != null) {            ContextImpl c = new ContextImpl(this, mMainThread, pi, mParams,                    mAttributionSource.getAttributionTag(),                    mAttributionSource.getNext(),                    null, mToken, user, flags, null, null);            final int displayId = getDisplayId();            final Integer overrideDisplayId = mForceDisplayOverrideInResources                    ? displayId : null;            c.setResources(createResources(mToken, pi, null, overrideDisplayId, null,                    getDisplayAdjustments(displayId).getCompatibilityInfo(), null));            if (c.mResources != null) {                return c;            }        }        // Should be a better exception.        throw new PackageManager.NameNotFoundException(                "Application package " + packageName + " not found");    }    @Override    public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {        try {            return createPackageContextAsUser(getPackageName(), flags, user);        } catch (NameNotFoundException e) {            throw new IllegalStateException("Own package not found: package=" + getPackageName());        }    }createPackageContextAsUser 涉及在ActivityThread获取applicationInfo 的逻辑如下
(终极照旧回归到 包罗applicationInfo参数 的  getPackageInfo方法)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,            int flags) {        return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());    }    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,            int flags, int userId) {        final boolean differentUser = (UserHandle.myUserId() != userId);        ApplicationInfo ai = PackageManager.getApplicationInfoAsUserCached(                packageName,                PackageManager.GET_SHARED_LIBRARY_FILES                | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,                (userId < 0) ? UserHandle.myUserId() : userId);        synchronized (mResourcesManager) {            WeakReference<LoadedApk> ref;            if (differentUser) {                // Caching not supported across users                ref = null;            } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {                ref = mPackages.get(packageName);            } else {                ref = mResourcePackages.get(packageName);            }            LoadedApk packageInfo = ref != null ? ref.get() : null;            if (ai != null && packageInfo != null) {                if (!isLoadedApkResourceDirsUpToDate(packageInfo, ai)) {                    List<String> oldPaths = new ArrayList<>();                    LoadedApk.makePaths(this, ai, oldPaths);                    packageInfo.updateApplicationInfo(ai, oldPaths);                }                if (packageInfo.isSecurityViolation()                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {                    throw new SecurityException(                            "Requesting code from " + packageName                            + " to be run in process "                            + mBoundApplication.processName                            + "/" + mBoundApplication.appInfo.uid);                }                return packageInfo;            }        }        if (ai != null) {            return getPackageInfo(ai, compatInfo, flags);        }        return null;    }    @UnsupportedAppUsage(trackingBug = 171933273)    public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,            int flags) {        boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;        boolean securityViolation = includeCode && ai.uid != 0                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null                        ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)                        : true);        boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;        if ((flags&(Context.CONTEXT_INCLUDE_CODE                |Context.CONTEXT_IGNORE_SECURITY))                == Context.CONTEXT_INCLUDE_CODE) {            if (securityViolation) {                String msg = "Requesting code from " + ai.packageName                        + " (with uid " + ai.uid + ")";                if (mBoundApplication != null) {                    msg = msg + " to be run in process "                        + mBoundApplication.processName + " (with uid "                        + mBoundApplication.appInfo.uid + ")";                }                throw new SecurityException(msg);            }        }        return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,                registerPackage);    }4. App 创建 Application对象

(20230322更新)
单进程,创建1个application对象,实验一次onCreate()方法
多进程(N),创建N个application对象,实验N次onCreate()方法
固然Application的假造内存地址类似(打印出来的),但它们的真实物理地址却差别
反射去调用Java的 "sun.misc.Unsafe" 类,获取物理内存地址.
参考>https://juejin.cn/post/7208345469658415159
--- End Now---
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2025-6-28 14:24, Processed in 0.121833 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表