下面摘录自官方
从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。如需详细了解有关此限制的决定,请参阅通过减少非 SDK 接口的使用来提高稳定性。
随着每个 Android 版本的发布,会有更多非 SDK 接口受到限制。 我们知道这些限制会影响您的发布工作流,同时我们希望确保您拥有相关工具来检测非 SDK 接口的使用情况、有机会向我们提供反馈,并且有时间根据相应新政策做出规划和调整。
为最大程度地降低非 SDK 使用限制对开发工作流的影响,我们将非 SDK 接口分成了几个名单,这些名单界定了非 SDK 接口使用限制的严格程度(取决于应用的目标 API 级别)。下表介绍了这些名单:
尽管您目前仍可以使用某些非 SDK 接口(取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。如果您的应用依赖于非 SDK 接口,建议您开始计划迁移到 SDK 接口或其他替代方案。如果您无法为应用中的功能找到无需使用非 SDK 接口的替代方案,我们建议您请求添加新的公共 API。
下表说明了当您的应用尝试访问屏蔽名单中的非 SDK 接口时可能会出现的预期行为。
1.谷歌建议开发者尽量使用公开的sdk接口,并没有禁止非sdk接口的使用
2.非sdk接口,开发者一般都是通过反射的机制进行使用,api>=28会进行限制,也就是说访问非sdk接口可能会失败
3.非sdk接口会进行等级分类,包括blacklist, greylist-max-x, greylist, whitelist等,其中greylist与whitelist不受限制
4.非sdk接口的等级可能会随着targetSdk以及系统sdk版本变化
Blacklist-api的配置文件一般在aops源码的aosp/frameworks/base/config/hiddenapi-force-blacklist.txt
以访问Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V为例
然后运行时抛出了异常NoSuchMethodException
非sdk接口,greylist以及whitelist不受限制,但是blacklist以及greylist-max-x会进行限制
这个是本文的主题,后面会通过手段达到目的
其内部调用了getMethod函数
第三个参数recursivePublicMethods为false,所以内部实际调用的是getDeclaredMethodInternal
getDeclaredMethodInternal为native函数,会调用到c++,源码可在art/runtime/native/java_lang_Class.cc中查找
大家可以留意一下art/runtime/native这个目录,包含了很多native-jni的函数实现
其内部调用了mirror::Class::GetDeclaredMethodInternal
源码中关键的地方做了标注,上述代码中有9个关键的地方,大家可自行查看,其中ShouldDenyAccessToMember为非sdk接口限制的关键函数
fn_get_access_context的源头是在java_lang_Class->getMethodIdInternal传过来的函数指针,即GetHiddenapiAccessContextFunction
也就是说,如果caller的domain值越小,能访问的hiddenapi范围越广。比如corePlatform能访问所有级别的api,但是application级别不能访问corePlatform以及platform级别的api。
###
这里返回了false(重点), 后边的代码省略,因为当前已经找到了两处返回false的地方(返回false表示可以访问)。
也就是说policy策略关闭时,可以自由访问hiddenapi,该方案可使用开源方案,但是需要适配不同的系统版本。
开源的方案是通过修改runtime内存实现的, 内存hidden_apipolicy的偏移值可因为系统版本,也可因为厂家定制导致不统一,所以该方案兼容性问题较大。
runtime->GetHiddenApiExemptions, 顾名思义:获取豁免的hiddenapi签名
该函数会遍历exemptions,只要有一个exemption,匹配当前访问的method->signature前缀,就可返回false。
无论MemberSignature的type_为field还是method,其返回值都是以class_name.c_str为前缀
另外,我们知道一个class的签名,形式都是如Ljava/lang/String;这种,肯定是以L开头的。
也就是说,想要调用setHiddenApiExemptions, 必须fake掉hiddenapi的限制。
所以看一下java_lang_Class中的GetHiddenapiAccessContextFunction
在此,domain_通过ComputeDomain初始化
直接搜索
代码中一共判断了5个文件位置,分别对应不同的domain
1.只是为了判断相关module的dir是否存在,一般都是存在的
2.artModule路径为/apex/com.android.art(android 11), 安卓10上的代码稍有区别
3.conscryptModule路径为/apex/com.android.conscrypt
4.apex的路径为/apex/
5.SystemFramework的路径为/system/framework
先随便找个debug的app看一下运行时apex路径都有哪些
这里有一个java.lang.System类,该类我们经常使用其加载so库,比如System.loadLibrary。
所以,我们可以通过System.loadLibrary,然后在native层的JNI_OnLoad中通过反射调用setHiddenApiExemptions(此时caller为java.lang.System.其domain级别为corePlatform),然后就可以随意访问hiddenapi了
核心代码:
| 名单 |
说明 |
屏蔽名单 (blacklist) |
无论应用的目标 API 级别是什么,您都无法使用的非 SDK 接口。 如果您的应用尝试访问其中任何一个接口,系统就会抛出错误。 |
有条件屏蔽 (greylist-max-x) |
从 Android 9(API 级别 28)开始,当有应用以该 API 级别为目标平台时,我们会在每个 API 级别分别限制某些非 SDK 接口。这些名单会以应用无法再访问该名单中的非 SDK 接口之前可以作为目标平台的最高 API 级别 (max-target-x) 进行标记。例如,在 Android Pie 中未被屏蔽、但现在已被 Android 10 屏蔽的非 SDK 接口会列入 max-target-p (greylist-max-p) 名单,其中的“p”表示 Pie 或 Android 9(API 级别 28)。如果您的应用尝试访问受目标 API 级别限制的接口,系统就会将此 API 视为已列入屏蔽名单。 |
不支持 (greylist) |
当前不受限制且您的应用可以使用的非 SDK 接口。 但请注意,这些接口不受支持,可能会在未发出通知的情况下随时发生更改。预计这些接口在未来的 Android 版本中会被有条件地屏蔽,并列在 max-target-x 名单中。 |
SDK (whitelist) |
已在 Android 框架软件包索引中正式记录、受支持并且可以自由使用的接口。 |
| 访问方式 |
结果 |
| Dalvik 指令引用某个字段 |
抛出 NoSuchFieldError
|
| Dalvik 指令引用某个方法 |
抛出 NoSuchMethodError
|
通过 Class.getDeclaredField() 或 Class.getField() 进行反射 |
抛出 NoSuchFieldException
|
通过 Class.getDeclaredMethod()、Class.getMethod() 进行反射 |
抛出 NoSuchMethodException
|
通过 Class.getDeclaredFields()、Class.getFields() 进行反射 |
结果中未获取到非 SDK 成员 |
通过 Class.getDeclaredMethods()、Class.getMethods() 进行反射 |
结果中未获取到非 SDK 成员 |
通过 env->GetFieldID() 进行 JNI 调用 |
返回 NULL,抛出 NoSuchFieldError
|
通过 env->GetMethodID() 进行 JNI 调用 |
返回 NULL,抛出 NoSuchMethodError
|
//android-11.0.0_r36
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$ vim config/hiddenapi-force-blacklist.txt
Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/invoke/VarHandle;->acquireFence()V
Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->fullFence()V
Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->loadLoadFence()V
Ljava/lang/invoke/VarHandle;->releaseFence()V
Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->storeStoreFence()V
Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
//android-11.0.0_r36
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$
liuzhuangzhuang@virtualbox:~/work/aosp/frameworks/base$ vim config/hiddenapi-force-blacklist.txt
Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/invoke/VarHandle;->acquireFence()V
Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->fullFence()V
Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
Ljava/lang/invoke/VarHandle;->loadLoadFence()V
Ljava/lang/invoke/VarHandle;->releaseFence()V
Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
Ljava/lang/invoke/VarHandle;->storeStoreFence()V
Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
try {
Class runtimeClass = Class.forName("dalvik.system.VMRuntime");
Method nativeLoadMethod = runtimeClass.getDeclaredMethod("setTargetSdkVersionNative",
new Class[] {int.class});
Log.d("whulzz", "setTargetSdkVersionNative success!");
} catch (Exception e) {
e.printStackTrace();
}
try {
Class runtimeClass = Class.forName("dalvik.system.VMRuntime");
Method nativeLoadMethod = runtimeClass.getDeclaredMethod("setTargetSdkVersionNative",
new Class[] {int.class});
Log.d("whulzz", "setTargetSdkVersionNative success!");
} catch (Exception e) {
e.printStackTrace();
}
08-16 12:57:13.379 21326 21326 W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [int]
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.Class.getMethod(Class.java:2072)
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.Class.getDeclaredMethod(Class.java:2050)
08-16 12:57:13.380 21326 21326 W System.err: at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:17)
08-16 12:57:13.380 21326 21326 W System.err: at com.example.demo.DemoApplication.onCreate(DemoApplication.java:26)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1190)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6584)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.access$1400(ActivityThread.java:226)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1889)
08-16 12:57:13.380 21326 21326 W System.err: at android.os.Handler.dispatchMessage(Handler.java:107)
08-16 12:57:13.380 21326 21326 W System.err: at android.os.Looper.loop(Looper.java:225)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.main(ActivityThread.java:7564)
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.reflect.Method.invoke(Native Method)
08-16 12:57:13.380 21326 21326 W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
08-16 12:57:13.381 21326 21326 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
08-16 12:57:13.379 21326 21326 W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [int]
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.Class.getMethod(Class.java:2072)
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.Class.getDeclaredMethod(Class.java:2050)
08-16 12:57:13.380 21326 21326 W System.err: at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:17)
08-16 12:57:13.380 21326 21326 W System.err: at com.example.demo.DemoApplication.onCreate(DemoApplication.java:26)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1190)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6584)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.access$1400(ActivityThread.java:226)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1889)
08-16 12:57:13.380 21326 21326 W System.err: at android.os.Handler.dispatchMessage(Handler.java:107)
08-16 12:57:13.380 21326 21326 W System.err: at android.os.Looper.loop(Looper.java:225)
08-16 12:57:13.380 21326 21326 W System.err: at android.app.ActivityThread.main(ActivityThread.java:7564)
08-16 12:57:13.380 21326 21326 W System.err: at java.lang.reflect.Method.invoke(Native Method)
08-16 12:57:13.380 21326 21326 W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
08-16 12:57:13.381 21326 21326 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
|
本文 |
Free reflection |
| setHiddenApiExemptions |
是 |
是 |
| dex放到bootclasspath |
否 |
是 |
| 元反射 |
否 |
是 |
| 兼容安卓11 |
是 |
不太清楚 |
| 第三方ROM兼容性得分 |
优秀 |
良好 |
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return getMethod(name, parameterTypes, false);
}
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return getMethod(name, parameterTypes, false);
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
throws NoSuchMethodException {
if (name == null) {
throw new NullPointerException("name == null");
}
if (parameterTypes == null) {
parameterTypes = EmptyArray.CLASS;
}
for (Class<?> c : parameterTypes) {
if (c == null) {
throw new NoSuchMethodException("parameter type is null");
}
}
Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
: getDeclaredMethodInternal(name, parameterTypes);
// Fail if we didn't find the method or it was expected to be public.
if (result == null ||
(recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
throw new NoSuchMethodException(getName() + "." + name + " "
+ Arrays.toString(parameterTypes));
}
return result;
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
throws NoSuchMethodException {
if (name == null) {
throw new NullPointerException("name == null");
}
if (parameterTypes == null) {
parameterTypes = EmptyArray.CLASS;
}
for (Class<?> c : parameterTypes) {
if (c == null) {
throw new NoSuchMethodException("parameter type is null");
}
}
Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
: getDeclaredMethodInternal(name, parameterTypes);
// Fail if we didn't find the method or it was expected to be public.
if (result == null ||
(recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
throw new NoSuchMethodException(getName() + "." + name + " "
+ Arrays.toString(parameterTypes));
}
return result;
}
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
liuzhuangzhuang.das@virtualbox:~/work/aosp/art/runtime/native$ ls
dalvik_system_BaseDexClassLoader.cc java_lang_Object.cc java_lang_reflect_Proxy.cc java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h java_lang_Object.h java_lang_reflect_Proxy.h java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc java_lang_ref_FinalizerReference.cc java_lang_ref_Reference.cc libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h java_lang_ref_FinalizerReference.h java_lang_ref_Reference.h libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc java_lang_reflect_Array.cc java_lang_String.cc native_util.h
dalvik_system_VMDebug.h java_lang_reflect_Array.h java_lang_StringFactory.cc org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc java_lang_reflect_Constructor.cc java_lang_StringFactory.h org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h java_lang_reflect_Constructor.h java_lang_String.h org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc java_lang_reflect_Executable.cc java_lang_System.cc org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h java_lang_reflect_Executable.h java_lang_System.h scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc java_lang_reflect_Field.cc java_lang_Thread.cc scoped_fast_native_object_access-inl.h
dalvik_system_ZygoteHooks.h java_lang_reflect_Field.h java_lang_Thread.h sun_misc_Unsafe.cc
java_lang_Class.cc java_lang_reflect_Method.cc java_lang_Throwable.cc sun_misc_Unsafe.h
java_lang_Class.h java_lang_reflect_Method.h java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc java_lang_reflect_Parameter.cc java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h java_lang_reflect_Parameter.h java_lang_VMClassLoader.h
liuzhuangzhuang.das@virtualbox:~/work/aosp/art/runtime/native$ ls
dalvik_system_BaseDexClassLoader.cc java_lang_Object.cc java_lang_reflect_Proxy.cc java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h java_lang_Object.h java_lang_reflect_Proxy.h java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc java_lang_ref_FinalizerReference.cc java_lang_ref_Reference.cc libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h java_lang_ref_FinalizerReference.h java_lang_ref_Reference.h libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc java_lang_reflect_Array.cc java_lang_String.cc native_util.h
dalvik_system_VMDebug.h java_lang_reflect_Array.h java_lang_StringFactory.cc org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc java_lang_reflect_Constructor.cc java_lang_StringFactory.h org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h java_lang_reflect_Constructor.h java_lang_String.h org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc java_lang_reflect_Executable.cc java_lang_System.cc org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h java_lang_reflect_Executable.h java_lang_System.h scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc java_lang_reflect_Field.cc java_lang_Thread.cc scoped_fast_native_object_access-inl.h
dalvik_system_ZygoteHooks.h java_lang_reflect_Field.h java_lang_Thread.h sun_misc_Unsafe.cc
java_lang_Class.cc java_lang_reflect_Method.cc java_lang_Throwable.cc sun_misc_Unsafe.h
java_lang_Class.h java_lang_reflect_Method.h java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc java_lang_reflect_Parameter.cc java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h java_lang_reflect_Parameter.h java_lang_VMClassLoader.h
static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
jstring name, jobjectArray args) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()->IsActiveTransaction());
ObjPtr<mirror::Class> klass = DecodeClass(soa, javaThis);/*1.获取class.*/
if (UNLIKELY(klass->IsObsoleteObject())) {
ThrowRuntimeException("Obsolete Object!");
return nullptr;
}
Handle<mirror::Method> result = hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
return nullptr;
}
return soa.AddLocalReference<jobject>(result.Get());
}
static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
jstring name, jobjectArray args) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()->IsActiveTransaction());
ObjPtr<mirror::Class> klass = DecodeClass(soa, javaThis);/*1.获取class.*/
if (UNLIKELY(klass->IsObsoleteObject())) {
ThrowRuntimeException("Obsolete Object!");
return nullptr;
}
Handle<mirror::Method> result = hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {
return nullptr;
}
return soa.AddLocalReference<jobject>(result.Get());
}
vim art/runtime//mirror/class.cc
template <PointerSize kPointerSize, bool kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
Thread* self,
ObjPtr<Class> klass,
ObjPtr<String> name,
ObjPtr<ObjectArray<Class>> args,
const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
// Covariant return types (or smali) permit the class to define
// multiple methods with the same name and parameter types.
// Prefer (in decreasing order of importance):
// 1) non-hidden method over hidden
// 2) virtual methods over direct
// 3) non-synthetic methods over synthetic
// We never return miranda methods that were synthesized by the runtime.
StackHandleScope<3> hs(self);
auto h_method_name = hs.NewHandle(name);
if (UNLIKELY(h_method_name == nullptr)) {
ThrowNullPointerException("name == null");
return nullptr;
}
auto h_args = hs.NewHandle(args);
Handle<Class> h_klass = hs.NewHandle(klass);
constexpr hiddenapi::AccessMethod access_method = hiddenapi::AccessMethod::kNone;
ArtMethod* result = nullptr;
bool result_hidden = false;
for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {/*4.遍历virtual method*/
if (m.IsMiranda()) {
continue;
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
ObjPtr<String> np_name = np_method->ResolveNameString();
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*5.判断方法名与参数类型*/
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
}
continue;
}
bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*6.调用ShouldDenyAccessToMember*/
if (!m_hidden && !m.IsSynthetic()) {
// Non-hidden, virtual, non-synthetic. Best possible result, exit early.
return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
} else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
// Remember as potential result.
result = &m;
result_hidden = m_hidden;
}
}
if ((result != nullptr) && !result_hidden) {
// We have not found a non-hidden, virtual, non-synthetic method, but
// if we have found a non-hidden, virtual, synthetic method, we cannot
// do better than that later.
DCHECK(!result->IsDirect());
DCHECK(result->IsSynthetic());
} else {
for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {/*7.遍历direct method*/
auto modifiers = m.GetAccessFlags();
if ((modifiers & kAccConstructor) != 0) {
continue;
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
ObjPtr<String> np_name = np_method->ResolveNameString();
if (np_name == nullptr) {
self->AssertPendingException();
return nullptr;
}
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*8.判断方法名与参数类型*/
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
}
continue;
}
DCHECK(!m.IsMiranda()); // Direct methods cannot be miranda methods.
bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*9.调用ShouldDenyAccessToMember*/
if (!m_hidden && !m.IsSynthetic()) {
// Non-hidden, direct, non-synthetic. Any virtual result could only have been
// hidden, therefore this is the best possible match. Exit now.
DCHECK((result == nullptr) || result_hidden);
return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
} else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
// Remember as potential result.
result = &m;
result_hidden = m_hidden;
}
}
}
return result != nullptr
? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
: nullptr;
}
vim art/runtime//mirror/class.cc
template <PointerSize kPointerSize, bool kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
Thread* self,
ObjPtr<Class> klass,
ObjPtr<String> name,
ObjPtr<ObjectArray<Class>> args,
const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
// Covariant return types (or smali) permit the class to define
// multiple methods with the same name and parameter types.
// Prefer (in decreasing order of importance):
// 1) non-hidden method over hidden
// 2) virtual methods over direct
// 3) non-synthetic methods over synthetic
// We never return miranda methods that were synthesized by the runtime.
StackHandleScope<3> hs(self);
auto h_method_name = hs.NewHandle(name);
if (UNLIKELY(h_method_name == nullptr)) {
ThrowNullPointerException("name == null");
return nullptr;
}
auto h_args = hs.NewHandle(args);
Handle<Class> h_klass = hs.NewHandle(klass);
constexpr hiddenapi::AccessMethod access_method = hiddenapi::AccessMethod::kNone;
ArtMethod* result = nullptr;
bool result_hidden = false;
for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {/*4.遍历virtual method*/
if (m.IsMiranda()) {
continue;
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
ObjPtr<String> np_name = np_method->ResolveNameString();
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*5.判断方法名与参数类型*/
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
}
continue;
}
bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*6.调用ShouldDenyAccessToMember*/
if (!m_hidden && !m.IsSynthetic()) {
// Non-hidden, virtual, non-synthetic. Best possible result, exit early.
return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
} else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
// Remember as potential result.
result = &m;
result_hidden = m_hidden;
}
}
if ((result != nullptr) && !result_hidden) {
// We have not found a non-hidden, virtual, non-synthetic method, but
// if we have found a non-hidden, virtual, synthetic method, we cannot
// do better than that later.
DCHECK(!result->IsDirect());
DCHECK(result->IsSynthetic());
} else {
for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {/*7.遍历direct method*/
auto modifiers = m.GetAccessFlags();
if ((modifiers & kAccConstructor) != 0) {
continue;
}
auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
// May cause thread suspension.
ObjPtr<String> np_name = np_method->ResolveNameString();
if (np_name == nullptr) {
self->AssertPendingException();
return nullptr;
}
if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {/*8.判断方法名与参数类型*/
if (UNLIKELY(self->IsExceptionPending())) {
return nullptr;
}
continue;
}
DCHECK(!m.IsMiranda()); // Direct methods cannot be miranda methods.
bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);/*9.调用ShouldDenyAccessToMember*/
if (!m_hidden && !m.IsSynthetic()) {
// Non-hidden, direct, non-synthetic. Any virtual result could only have been
// hidden, therefore this is the best possible match. Exit now.
DCHECK((result == nullptr) || result_hidden);
return Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
} else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
// Remember as potential result.
result = &m;
result_hidden = m_hidden;
}
}
}
return result != nullptr
? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
: nullptr;
}
template<typename T>
inline bool ShouldDenyAccessToMember(T* member,
const std::function<AccessContext()>& fn_get_access_context,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member != nullptr);
// Get the runtime flags encoded in member's access flags.
// Note: this works for proxy methods because they inherit access flags from their
// respective interface methods.
const uint32_t runtime_flags = GetRuntimeFlags(member);
// Exit early if member is public API. This flag is also set for non-boot class
// path fields/methods.
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
return false;
}
// Determine which domain the caller and callee belong to.
// This can be *very* expensive. This is why ShouldDenyAccessToMember
// should not be called on every individual access.
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
// Non-boot classpath callers should have exited early.
DCHECK(!callee_context.IsApplicationDomain());
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
return false;
}
// Check if this is platform accessing core platform. We may warn if `member` is
// not part of core platform API.
/*5.根据domain级别区分对待hiddenapi策略*/
switch (caller_context.GetDomain()) {
case Domain::kApplication: {
DCHECK(!callee_context.IsApplicationDomain());
// Exit early if access checks are completely disabled.
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
return false;
}
// If this is a proxy method, look at the interface method instead.
member = detail::GetInterfaceMemberIfProxy(member);
// Decode hidden API access flags from the dex file.
// This is an O(N) operation scaling with the number of fields/methods
// in the class. Only do this on slow path and only do it once.
ApiList api_list(detail::GetDexFlags(member));
DCHECK(api_list.IsValid());
// Member is hidden and caller is not exempted. Enter slow path.
return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
}
case Domain::kPlatform: {
DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
// Member is part of core platform API. Accessing it is allowed.
if ((runtime_flags & kAccCorePlatformApi) != 0) {
return false;
}
// Allow access if access checks are disabled.
EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {
return false;
}
// If this is a proxy method, look at the interface method instead.
member = detail::GetInterfaceMemberIfProxy(member);
// Access checks are not disabled, report the violation.
// This may also add kAccCorePlatformApi to the access flags of `member`
// so as to not warn again on next access.
return detail::HandleCorePlatformApiViolation(member,
caller_context,
access_method,
policy);
}
case Domain::kCorePlatform: {
LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
UNREACHABLE();
}
}
}
template<typename T>
inline bool ShouldDenyAccessToMember(T* member,
const std::function<AccessContext()>& fn_get_access_context,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member != nullptr);
// Get the runtime flags encoded in member's access flags.
// Note: this works for proxy methods because they inherit access flags from their
// respective interface methods.
const uint32_t runtime_flags = GetRuntimeFlags(member);
// Exit early if member is public API. This flag is also set for non-boot class
// path fields/methods.
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
return false;
}
// Determine which domain the caller and callee belong to.
// This can be *very* expensive. This is why ShouldDenyAccessToMember
// should not be called on every individual access.
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
// Non-boot classpath callers should have exited early.
DCHECK(!callee_context.IsApplicationDomain());
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
return false;
}
// Check if this is platform accessing core platform. We may warn if `member` is
// not part of core platform API.
/*5.根据domain级别区分对待hiddenapi策略*/
switch (caller_context.GetDomain()) {
case Domain::kApplication: {
DCHECK(!callee_context.IsApplicationDomain());
// Exit early if access checks are completely disabled.
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
return false;
}
// If this is a proxy method, look at the interface method instead.
member = detail::GetInterfaceMemberIfProxy(member);
// Decode hidden API access flags from the dex file.
// This is an O(N) operation scaling with the number of fields/methods
// in the class. Only do this on slow path and only do it once.
ApiList api_list(detail::GetDexFlags(member));
DCHECK(api_list.IsValid());
// Member is hidden and caller is not exempted. Enter slow path.
return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
}
case Domain::kPlatform: {
DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
// Member is part of core platform API. Accessing it is allowed.
if ((runtime_flags & kAccCorePlatformApi) != 0) {
return false;
}
// Allow access if access checks are disabled.
EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {
return false;
}
// If this is a proxy method, look at the interface method instead.
member = detail::GetInterfaceMemberIfProxy(member);
// Access checks are not disabled, report the violation.
// This may also add kAccCorePlatformApi to the access flags of `member`
// so as to not warn again on next access.
return detail::HandleCorePlatformApiViolation(member,
caller_context,
access_method,
policy);
}
case Domain::kCorePlatform: {
LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
UNREACHABLE();
}
}
}
//java_lang_Class.cc
Handle<mirror::Method> result = hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
//java_lang_Class.cc
Handle<mirror::Method> result = hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(/*2.调用GetDeclaredMethodInternal*/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));/*3.hiddenapi访问上下文*/
//java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread* self) {
return [=]() REQUIRES_SHARED(Locks::mutator_lock_) { return GetReflectionCaller(self); };
}
//java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread* self) {
return [=]() REQUIRES_SHARED(Locks::mutator_lock_) { return GetReflectionCaller(self); };
}
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
return false;
}
if ((runtime_flags & kAccPublicApi) != 0) {/*1.如果方法是public api,则允许访问*/
return false;
}
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext caller_context = fn_get_access_context();/*2.获取caller的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
const AccessContext callee_context(member->GetDeclaringClass());/*3.获取所调用方法的上下文*/
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
return false;
}
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {/*4.caller是否可以不受约束访问callee*/
return false;
}
//hidden_api.h
// Returns true if this domain is always allowed to access the domain of `callee`.
bool CanAlwaysAccess(const AccessContext& callee) const {
return IsDomainMoreTrustedThan(domain_, callee.domain_);
}
//hidden_api.h
// Returns true if this domain is always allowed to access the domain of `callee`.
bool CanAlwaysAccess(const AccessContext& callee) const {
return IsDomainMoreTrustedThan(domain_, callee.domain_);
}
//art/libartbase/base/hiddenapi_domain.h
enum class Domain : char {
kCorePlatform = 0,
kPlatform,
kApplication,
};
inline bool IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
return static_cast<char>(domainA) <= static_cast<char>(domainB);
}
//art/libartbase/base/hiddenapi_domain.h
enum class Domain : char {
kCorePlatform = 0,
kPlatform,
kApplication,
};
inline bool IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
return static_cast<char>(domainA) <= static_cast<char>(domainB);
}
template<typename T>
bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) {
DCHECK(member != nullptr);
Runtime* runtime = Runtime::Current();
EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
<< "Should never enter this function when access checks are completely disabled";
MemberSignature member_signature(member);
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
// Avoid re-examining the exemption list next time.
// Note this results in no warning for the member, which seems like what one would expect.
// Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return false;
}
.....
省略
....
template<typename T>
bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method) {
DCHECK(member != nullptr);
Runtime* runtime = Runtime::Current();
EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
<< "Should never enter this function when access checks are completely disabled";
MemberSignature member_signature(member);
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
// Avoid re-examining the exemption list next time.
// Note this results in no warning for the member, which seems like what one would expect.
// Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return false;
}
.....
省略
....
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
return false;
}
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
if (policy == EnforcementPolicy::kDisabled) {/*5.1.如果policydisable,则返回false,即允许访问*/
return false;
}
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
return hidden_api_policy_;
}
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
return hidden_api_policy_;
}
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
// Avoid re-examining the exemption list next time.
// Note this results in no warning for the member, which seems like what one would expect.
// Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return false;
}
// Check for an exemption first. Exempted APIs are treated as white list.
if (member_signature.DoesPrefixMatchAny(runtime->GetHiddenApiExemptions())) {
// Avoid re-examining the exemption list next time.
// Note this results in no warning for the member, which seems like what one would expect.
// Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return false;
}
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-8-16 20:53
被whulzz编辑
,原因: 添加git仓库