㈠ android P 系统稳定性问题分析方法总结
Android系统最开始是为手机设计的,在机顶盒,电视,带屏音箱等大屏上运行后,芯片厂家做些适配,产品厂家也会做系统客制化,有时候还要适配第三方应用..等待
这种适配容易引人系统的稳定性问题,系统稳定性对于用户体验至关重要,很多问题也都比较类似,android系统对系统性能,稳定性分析工具也比较多,下面根据工作中遇到的问题做个总结。
从表现来看有: 死机重启, 自动关机, 无法开机,冻屏,黑屏以及闪退, 无响应等情况;
从技术层面来划分无外乎两大类: 长时间无法执行完成(Timeout) 以及异常崩溃(crash). 主要分类如下:
ANR(Application Not responding),是指普通app进程超过一定时间没有执行完,系统会弹出应用无响应对话框. 如果
该进程运行在system进程, 更准确的来说,应该是(System Not Responding, SNR)
ANR产生的原因可能是各种各样的,但常见的原因可以分为:
1.logcat日志
2.trace文件(保存在/data/anr/traces.txt)
从logcat里可以看到死锁的打印
从traces.txt可以看到线程的函数调用栈
10-16 00:50:10 820 907 E ActivityManager: ANR in com.android.systemui, time=130090695
10-16 00:50:10 820 907 E ActivityManager: Reason: Broadcast of Intent { act=android.intent.action.TIME_TICK flg=0x50000114 (has extras) }
10-16 00:50:10 820 907 E ActivityManager: Load: 30.4 / 22.34 / 19.94
10-16 00:50:10 820 907 E ActivityManager: Android time :[2015-10-16 00:50:05.76] [130191,266]
10-16 00:50:10 820 907 E ActivityManager: CPU usage from 6753ms to -4ms ago:
10-16 00:50:10 820 907 E ActivityManager: 47% 320/netd: 3.1% user + 44% kernel / faults: 14886 minor 3 major
10-16 00:50:10 820 907 E ActivityManager: 15% 10007/com.sohu.sohuvideo: 2.8% user + 12% kernel / faults: 1144 minor
10-16 00:50:10 820 907 E ActivityManager: 13% 10654/hif_thread: 0% user + 13% kernel
10-16 00:50:10 820 907 E ActivityManager: 11% 175/mmcqd/0: 0% user + 11% kernel
10-16 00:50:10 820 907 E ActivityManager: 5.1% 12165/app_process: 1.6% user + 3.5% kernel / faults: 9703 minor 540 major
10-16 00:50:10 820 907 E ActivityManager: 3.3% 29533/com.android.systemui: 2.6% user + 0.7% kernel / faults: 8402 minor 343 major
......
10-16 00:50:10 820 907 E ActivityManager: +0% 12832/cat: 0% user + 0% kernel
10-16 00:50:10 820 907 E ActivityManager: +0% 13211/zygote64: 0% user + 0% kernel
10-16 00:50:10 820 907 E ActivityManager: 87% TOTAL: 3% user + 18% kernel + 64% iowait + 0.5% softirq
发生ANR的时间 00:50:10 ,可以从这个时间点之前的日志中,还原ANR出现时系统的运行状态
发生ANR的进程 com.android.system.ui
发生ANR的原因 Reason关键字表明了ANR的原因是处理TIME_TICK广播消息超时
CPU负载 Load关键字表明了最近1分钟、5分钟、15分钟内的CPU负载分别是30.4、22.3、19.94.CPU最近1分钟的负载最具参考价值,因为ANR的超时限制基本都是1分钟以内, 这可以近似的理解为CPU最近1分钟平均有30.4个任务要处理,这个负载值是比较高的
CPU使用统计时间段 CPU usage from XX to XX ago关键字表明了这是在ANR发生之前一段时间内的CPU统计,类似的还有CPU usage from XX to XX after关键字,表明是ANR发生之后一段时间内的CPU统计
各进程的CPU使用率
以com.android.systemui进程的CPU使用率为例,它包含以下信息:
总的CPU使用率: 3.3%,其中systemui进程在用户态的CPU使用率是2.6%,在内核态的使用率是0.7%
缺页次数fault:8402 minor表示高速缓存中的缺页次数,343 major表示内存的缺页次数。minor可以理解为进程在做内存访问,major可以理解为进程在做IO操作。 当前minor和major值都是比较高的,从侧面反映了发生ANR之前,systemui进程有有较多的内存访问操作,引发的IO次数也会较多
CPU使用汇总 TOTAL关键字表明了CPU使用的汇总,87%是总的CPU使用率,其中有一项iowait表明CPU在等待IO的时间,占到64%,说明发生ANR以前,有大量的IO操作。app_process、 system_server, com.android.systemui这几个进程的major值都比较大,说明这些进程的IO操作较为频繁,从而拉升了整个iowait的时间
traces.txt 如下
----- pid 29533 at 2015-10-16 00:48:29 -----
Cmd line: com.android.systemui
DALVIK THREADS (54):
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 dsCount=0 obj=0x75bd5818 self=0x7f8549a000
| sysTid=29533 nice=0 cgrp=bg_non_interactive sched=0/0 handle=0x7f894bbe58
| state=S schedstat=( 289080040422 93461978317 904874 ) utm=20599 stm=8309 core=0 HZ=100
| stack=0x7fdffda000-0x7fdffdc000 stackSize=8MB
| held mutexes=
at com.mediatek.anrappmanager.MessageLogger.println(SourceFile:77)
Android系统中,有硬件WatchDog用于定时检测关键硬件是否正常工作,类似地,在framework层有一个软件WatchDog用于定期检测关键系统服务是否发生死锁事件。
watchdog 每过30s 检测一次, 如果要监控的线程30s 后没有响应,系统会mp出此进程堆栈,如果超过60s 没有相应,会触发watchdog,并重启系统
10:57:23.718 579 1308 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in monitor com.android.server.am.ActivityManagerService on foreground thread (android.fg), Blocked in handler on main thread (main), Blocked in handler on ActivityManager (ActivityManager)
10:57:23.725 579 1308 W Watchdog: android.fg annotated stack trace:
10:57:23.726 579 1308 W Watchdog: at com.android.server.am.ActivityManagerService.monitor(ActivityManagerService.java:26271)
10:57:23.727 579 1308 W Watchdog: - waiting to lock <0x0bb47e39> (a com.android.server.am.ActivityManagerService)
10:57:23.727 579 1308 W Watchdog: at com.android.server.Watchdog DeliveryTracker.alarmTimedOut(AlarmManagerService.java:4151)
10:57:23.733 579 1308 W Watchdog: - waiting to lock <0x00aaee38> (a java.lang.Object)
......
10:57:23.736 579 1308 W Watchdog: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)
10:57:23.739 579 1308 W Watchdog: ActivityManager annotated stack trace:
10:57:23.740 579 1308 W Watchdog: at com.android.server.am.ActivityStack$ActivityStackHandler.handleMessage(ActivityStack.java:405)
10:57:23.740 579 1308 W Watchdog: - waiting to lock <0x0bb47e39> (a com.android.server.am.ActivityManagerService)
10:57:23.740 579 1308 W Watchdog: at android.os.Handler.dispatchMessage(Handler.java:106)
10:57:23.741 579 1308 W Watchdog: *** GOODBYE!
分析:
提示 ActivityManagerService的android.fg,main,ActivityManager 线程Block了,但logcat里只能看到
android.fg等待0x0bb47e39 锁,main 等待0x00aaee38锁,ActivityManager等待0x0bb47e39锁,无法进一步分析,需要看traces.txt
Cmd line: system_server
......
"main" prio=5 tid=1 Blocked
当出现应用闪退,可以从两个方面查看:
1、是否应用崩溃:
可以通过logcat –s AndroidRuntime DEBUG过滤日志,查看应用奔溃的具体堆栈信息。
其中AndroidRuntime的TAG打印java层信息,DEBUG的TAG打印native层的信息。
2、是否被lowmemorykiller杀掉:
可以通过 logcat –s lowmemorykiller 过滤日志,注意adj 0是代表前台进程。例如:
03-08 04:16:58.084 310 310 I lowmemorykiller: Killing'com.google.android.tvlauncher' (2520), uid 10007, adj 0
发生这种情况,需要mpsys meminfo 查看当前内存状态,是否有进程内存泄漏,导致系统内存不够,出现前台进程被杀,造成闪退。
测试过程中,经常遇到屏幕闪烁的现象,需要排除是OSD层闪烁,还是video层闪烁。
1、先通过android原生方法:screencap截图, screenrecord 录制视频,这里都是截取的OSD层,查看是否有闪屏现象。
2、OSD没有问题,就需要从更底层的显示模块分析,一般需要芯片厂家提供debug手段,不同芯片厂家方案不一样。
3, 有时候输出不稳定,hdmi/mipi信号干扰,输出频率异常等也会导致闪屏,这种情况需要硬件协助分析。
如果OSD层也闪烁,则需从系统和应用层面分析。如曾遇到在开机向导界面,有个应用不断被唤起,导致走开机向导时出现连续闪灰屏的现象。
黑屏分UI黑屏,视频播放黑屏但UI正常等,2种场景
1、screencap截屏,排查OSD层图形是否正常,
2、如果OSD图形正常,需要排查显示输出模块是否异常。
3、电视机里面屏显是单独控制,如果屏参配置错误会导致整改黑屏。
OSD异常,需要排查顶层activity是否黑屏,window是否有异常等.
1,排查视频图层或者window是否创建成功。
2,排查解码是否有异常,不同的应用youtube,netflix,iptv解码方式不一样,需要具体问题具体分析。
如下,ActivityManager因为空对象引用而挂掉,导致system_server重启
*** [FATAL EXCEPTION IN SYSTEM PROCESS: ActivityHanager [
^ava.lang.NullPointerException: Attempt to invoke virtual method 'void co®.android.internal.os.KernelSingleUidTimeReader.iBarkDataAsStale(boolean)' on a null object reference
at com.android.internal.os.BatteryStatsIiaplSConstants.(BatteryStatslnpl.java:13355)
at com.android.internal.os.BatteryStatsInplSConstants.upddteConstants(BatteryStatsImpl.java:13330)
at com.android.internal-o-batteryStatslMpl$Constants-onChange(BatteryStatsInpl-java:13316)
at android.database.Contentobserver.onChange(ContentObserver.java:145)
解决方法:修复空指针
DEBUG : pid: 296, tid: 1721, name: Binder:296_4 >>> /system/bin/surfaceflinger <<<
DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr ------
DEBUG : Abort message: 'status.cpp:149] Failed HIDL return status not checked: Status(EXTRANSACTIONFAILED):
DEBUG : r0 00000000 rl 000006b9
DEBUG : C4 00000128 r5 000006b9
r2 00000006 r3 a5c5d620
r6 a235d60c r7 0000010c
DEAD_OB3ECT:
DEBUG : r8 00000019 r9 0000015d
DEBUG : ip a6ablbec sp a235d5f8
rlO a568f090 rll a620dce9
Ir a5be901d pc a5be0da2
/system/lib/libc.so (abort+62)
/system/lib/libbase.so (android::base::DefaultAborter(char const )+6)
backtrace:
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libsurfaceflinger.so
/system/lib/libbase.so (android::base::LogMessage::~LogMessage()+502)
/system/lib/libhidlbase.so (android::hardware::details::return_status::~return_status()+184)
(android::Hwc2::impl::Composer::getActiveConfig(unsigned long long, unsigned int )+56)
(HWC2::Display::getActiveConfig(std::_1::shared_ptr<HWC2::Display::Config const>*) const+38)
(android::HWComposer::getActiveConfig(int) const+64)
(android::SurfaceFlinger::resyncToHardwareVsync(bool)+64)
可以根据backtrace来进行定位异常崩溃的地方。Android P上, backtrace使用Java上下文来显示,省去使用addr2line来转换的一个过程,方便调试分析问题。但是实际场景中,
有些native进程崩溃只有pc地址,而无函数信息,或者需要定位到具体的某个文件某个函数,则可借助堆栈分析工具addr2line。
addr2line:根据堆栈定位具体函数和文件
addr2line -e libsurfaceflinger.so -f 00071a09
addr2line -e libsurfaceflinger.so -f 00071a09
_
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:1229
需注意两点:
1、需用带debug信息的LINK目录里面的so库,机顶盒上的so库是无法定位的:
out/target/proct/xx/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates/LINKED/libsurfaceflinger.so
或者:out/target/proct/xx/symbols/system/lib/libsurfaceflinger.so
2、定位的文件,必现和机器上出现问题的版本一致,否则定位不准确
debuggerd:打印当前进程实时堆栈:debuggerd –b pid
主要可以分为以下3类
1)Data abort
Unable to handle kernel NULL pointer dereference at virtual address...
Unable to handle kernel paging request at virtual address...
Unhandled fault...at...
Unhandled prefetch abort...at...
2)BUG/BUG_ON
Oops - BUG...
例如:
Out of memory and no killable processes...
rbus timeout...
...
PS:WARN_ON只mp stacks,kernel还是正常
3)bad mode
Oops - bad mode...
日志打印:
〃错误类型原因
[214.962667] 08:14:19.315 (2)-0488 Unable to handle kernel paging request at virtual address 6b6b6cl7
[214.973889] 08:14:19.326 (2)-0488 addr:6b6b6c17 pgd = d0824000
[214.980132] [6b6b6c17J •pgd=O000eO0e
〃Oopsttl误码序号
[214.983865] 08:14:19.336 (2)-0488 Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[214.9914S3] Moles linked in: 8192eu ufsd(PO) jnl(O) fusion(O)
〃发生也错误的CPU序号
(215.001878] 08:14:19.354 (2)-0488 CPU: 2 PID: 488 Comm: system_server Tainted: P 4.4.3+ #113
(2)-0488 Hardware name: rtd284x
[215.011865] 08:14:19.364
〃当前PC指针 98:14:19.377 (2)-0488 PC is at mutex_unlo<k+0xc/0x38
(21S.024846] 08:14:19.383 (2)-0488 LR is at storage_pm_event+0xb4/0xe8
(21S.031026]
//Registers 08:14:19.390 (2)-0488 :[<ceb78ffc>] Ir : [<C0542034>] psr: 200f0013
I 215.037644] sp : ccf79e38 ip : eceoeeee fp : 9b34648c
I 215.037644]
08:14:19.404 (2)-0488 rlO: 00000080 r9 :Cl8b3864 r8 : oeeeeeoe
215.051370]
215.058692] 08:14:19.411 (2)-0488 P7 : C1293a98 P6 :C1293940 r5 : C1293940 r4 :C1293a80
21S.067345]
[ 215.076014] 08:14:19.420 (2)-0488 r3 : 00000033 r2 :00000000 ri : 000^000 re :6b6b6c07
[ 215.085307]
08:14:19.428 (2)-0488 Flags: nzCv IRQs on FIQs on Mode SVC 32 ISA ARM Segment user
08:14:19.438 (2)-0488 Control: 10c5383d Table: 1082406a DAC: 00000055
//Process.不 ,定是该process的错误,只是发生错误时,刚好在运行该process
[215.093168]
//Stacks 08:14:19.446 (2)-0488 Process syste«i_server (pid: 488, stack limit = 0xccf78218)
(21S.101827] 08:14:19.454 (2)-0488 Stack: 0xccf79e38 (Oxccf79d7。 to 0xccf7a08Q) - par(0xcf796d4)
---[ end trace 45d55384id6a0974 ]--- Kernel panic not syncing: Fatal exception
[217.359794] 08:14:21.712 (0)-0488
解决方案: kernel异常一般找芯片原厂协助分析。
系统卡顿时,一般先分三步走:
1、查看当前系统的CPU,IO等参数,输入top、iotop命令: (如:iotop -s io -m 9)
如果有异常飙高的进程,kill掉后会发现系统恢复正常。
之前项目上遇到过某些U盘IO性能比较差,媒体中心又在后台扫描媒体问题,导致系统各种卡顿,io wait时间比较长。
2、系统进程卡住,触发Watchdog:ps –A |grep system_server,一般而言,system_server正常的进程号是200多,如果发现进程号变成几千,则可能出现重启,结合tombstone和 /data/anr下的trace文件分析重启原因
3、当前应用出现卡顿,造成ANR。输入logcat | grep ANR,如果有ANR打印,再去/data/anr下面查看相应进程的traces文件
有时在应用里面操作卡顿,按键响应延迟,但是却没有生成ANR,此时如果退出该应用(如果无法退出,在抓取足够信息的情况下,可以串口直接kill掉卡顿的应用),则一切正常,可能是应用自身实现问题,或者调用了其它接口导致(例如曾遇到应用调用了中间件、mediaplayer某些接口导致操作严重卡顿,按键响应延迟),这种情况则需应用和相应接口的实现者去排查。
系统完全卡死,一般分三种情况
1,串口无响应,大概率kernel panic,
2,串口日志狂输出,把系统堵塞, 优化日志输出,关注关闭后压测。
3,Input系统完全堵塞,导致任何输入都无响应。
㈡ android 怎么打印函数堆栈 java
C++也是支持异常处理的,异常处理库中,已经包含了获取backtrace的接口,Android也是利用这个接口来打印堆栈信息的。在Android的C++中,已经集成了一个工具类CallStack,在libutils.so中。
使用方法:
[cpp]viewplain
#include<utils/CallStack.h>
...
CallStackstack;
stack.update();
stack.mp();
使用方式比较简单。目前Andoid4.2版本已经将相关信息解析的很到位,符号表查找,demangle,偏移位置校正都做好了。
㈢ android 怎么编译so文件
android NDK编译多个so文件
android编译系统的makefile文件Android.mk写法如下
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下
Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。
(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始
以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_EXECUTABLE)表示编译成可执行程序
(3)举例如下(frameworks/base/libs/audioflinger/Android.mk):
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) 模块一
ifeq ($(AUDIO_POLICY_TEST),true)
ENABLE_AUDIO_DUMP := true
endif
LOCAL_SRC_FILES:= \
AudioHardwareGeneric.cpp \
AudioHardwareStub.cpp \
AudioHardwareInterface.cpp
ifeq ($(ENABLE_AUDIO_DUMP),true)
LOCAL_SRC_FILES += AudioDumpInterface.cpp
LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_CFLAGS += -DGENERIC_AUDIO
endif
LOCAL_MODULE:= libaudiointerface
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_SRC_FILES += A2dpAudioInterface.cpp
LOCAL_SHARED_LIBRARIES += liba2dp
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_C_INCLUDES += $(call include-path-for, bluez)
endif
include $(BUILD_STATIC_LIBRARY) 模块一编译成静态库
include $(CLEAR_VARS) 模块二
LOCAL_SRC_FILES:= \
AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libmedia
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
else
LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_A2DP
endif
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
include $(BUILD_STATIC_LIBRARY) 模块二编译成静态库
include $(CLEAR_VARS) 模块三
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
AudioResampler.cpp.arm \
AudioResamplerSinc.cpp.arm \
AudioResamplerCubic.cpp.arm \
AudioPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libmedia \
libhardware_legacy
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
LOCAL_CFLAGS += -DGENERIC_AUDIO
else
LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
endif
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
else
LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
LOCAL_SHARED_LIBRARIES += liba2dp
endif
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt -lpthread
endif
endif
ifeq ($(BOARD_USE_LVMX),true)
LOCAL_CFLAGS += -DLVMX
LOCAL_C_INCLUDES += vendor/nxp
LOCAL_STATIC_LIBRARIES += liblifevibes
LOCAL_SHARED_LIBRARIES += liblvmxservice
# LOCAL_SHARED_LIBRARIES += liblvmxipc
endif
include $(BUILD_SHARED_LIBRARY) 模块三编译成动态库
(4)编译一个应用程序(APK)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory-->直译(建立在java子目录中的所有Java文件)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build-->直译(创建APK的名称)
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK-->直译(告诉它来建立一个APK)
include $(BUILD_PACKAGE)
(5)编译一个依赖于静态Java库(static.jar)的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# List of static libraries to include in the package
LOCAL_STATIC_JAVA_LIBRARIES := static-library
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK
include $(BUILD_PACKAGE)
(6)编译一个需要用平台的key签名的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := platform
# Tell it to build an APK
include $(BUILD_PACKAGE)
(7)编译一个需要用特定key前面的应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := vendor/example/certs/app
# Tell it to build an APK
include $(BUILD_PACKAGE)
(8)添加一个预编译应用程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Mole name should match apk name to be installed.
LOCAL_MODULE := LocalMoleName
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
(9)添加一个静态JAVA库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Any libraries that this library depends on
LOCAL_JAVA_LIBRARIES := android.test.runner
# The name of the jar file to create
LOCAL_MODULE := sample
# Build a static jar file.
include $(BUILD_STATIC_JAVA_LIBRARY)
(10)Android.mk的编译模块中间可以定义相关的编译内容,也就是指定相关的变量如下:
LOCAL_AAPT_FLAGS
LOCAL_ACP_UNAVAILABLE
LOCAL_ADDITIONAL_JAVA_DIR
LOCAL_AIDL_INCLUDES
LOCAL_ALLOW_UNDEFINED_SYMBOLS
LOCAL_ARM_MODE
LOCAL_ASFLAGS
LOCAL_ASSET_DIR
LOCAL_ASSET_FILES 在Android.mk文件中编译应用程序(BUILD_PACKAGE)时设置此变量,表示资源文件,
通常会定义成LOCAL_ASSET_FILES += $(call find-subdir-assets)
LOCAL_BUILT_MODULE_STEM
LOCAL_C_INCLUDES 额外的C/C++编译头文件路径,用LOCAL_PATH表示本文件所在目录
举例如下:
LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_CC 指定C编译器
LOCAL_CERTIFICATE 签名认证
LOCAL_CFLAGS 为C/C++编译器定义额外的标志(如宏定义),举例:LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1
LOCAL_CLASSPATH
LOCAL_COMPRESS_MODULE_SYMBOLS
LOCAL_COPY_HEADERS install应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO
LOCAL_COPY_HEADERS_TO install应用程序时复制头文件的目的路径
LOCAL_CPP_EXTENSION 如果你的C++文件不是以cpp为文件后缀,你可以通过LOCAL_CPP_EXTENSION指定C++文件后缀名
如:LOCAL_CPP_EXTENSION := .cc
注意统一模块中C++文件后缀必须保持一致。
LOCAL_CPPFLAGS 传递额外的标志给C++编译器,如:LOCAL_CPPFLAGS += -ffriend-injection
LOCAL_CXX 指定C++编译器
LOCAL_DX_FLAGS
LOCAL_EXPORT_PACKAGE_RESOURCES
LOCAL_FORCE_STATIC_EXECUTABLE 如果编译的可执行程序要进行静态链接(执行时不依赖于任何动态库),则设置LOCAL_FORCE_STATIC_EXECUTABLE:=true
目前只有libc有静态库形式,这个只有文件系统中/sbin目录下的应用程序会用到,这个目录下的应用程序在运行时通常
文件系统的其它部分还没有加载,所以必须进行静态链接。
LOCAL_GENERATED_SOURCES
LOCAL_INSTRUMENTATION_FOR
LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME
LOCAL_INTERMEDIATE_SOURCES
LOCAL_INTERMEDIATE_TARGETS
LOCAL_IS_HOST_MODULE
LOCAL_JAR_MANIFEST
LOCAL_JARJAR_RULES
LOCAL_JAVA_LIBRARIES 编译java应用程序和库的时候指定包含的java类库,目前有core和framework两种
多数情况下定义成:LOCAL_JAVA_LIBRARIES := core framework
注意LOCAL_JAVA_LIBRARIES不是必须的,而且编译APK时不允许定义(系统会自动添加)
LOCAL_JAVA_RESOURCE_DIRS
LOCAL_JAVA_RESOURCE_FILES
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_LDFLAGS 传递额外的参数给连接器(务必注意参数的顺序)
LOCAL_LDLIBS 为可执行程序或者库的编译指定额外的库,指定库以"-lxxx"格式,举例:
LOCAL_LDLIBS += -lcurses -lpthread
LOCAL_LDLIBS += -Wl,-z,origin
LOCAL_MODULE 生成的模块的名称(注意应用程序名称用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE)
LOCAL_MODULE_PATH 生成模块的路径
LOCAL_MODULE_STEM
LOCAL_MODULE_TAGS 生成模块的标记
LOCAL_NO_DEFAULT_COMPILER_FLAGS
LOCAL_NO_EMMA_COMPILE
LOCAL_NO_EMMA_INSTRUMENT
LOCAL_NO_STANDARD_LIBRARIES
LOCAL_OVERRIDES_PACKAGES
LOCAL_PACKAGE_NAME APK应用程序的名称
LOCAL_POST_PROCESS_COMMAND
LOCAL_PREBUILT_EXECUTABLES 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用,指定需要复制的可执行文件
LOCAL_PREBUILT_JAVA_LIBRARIES
LOCAL_PREBUILT_LIBS 预编译including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)时所用, 指定需要复制的库.
LOCAL_PREBUILT_OBJ_FILES
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
LOCAL_PRELINK_MODULE 是否需要预连接处理(默认需要,用来做动态库优化)
LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)
LOCAL_RESOURCE_DIR
LOCAL_SDK_VERSION
LOCAL_SHARED_LIBRARIES 可链接动态库
LOCAL_SRC_FILES 编译源文件
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_LIBRARIES 可链接静态库
LOCAL_UNINSTALLABLE_MODULE
LOCAL_UNSTRIPPED_PATH
LOCAL_WHOLE_STATIC_LIBRARIES 指定模块所需要载入的完整静态库(这些精通库在链接是不允许链接器删除其中无用的代码)
LOCAL_YACCFLAGS
OVERRIDE_BUILT_MODULE_PATH
㈣ android的系统结构
Android 是运行于Linux kernel之上,但并不是GNU/Linux。因为在一般GNU/Linux 里支持的功能,Android 大都没有支持,包括Cairo、X11、Alsa、FFmpeg、GTK、Pango及Glibc等都被移除掉了。Android又以Bionic 取代Glibc、以谨段Skia 取代Cairo、再以opencore取代FFmpeg等等。Android 为了达到商业应用,必须移除被GNU GPL授权证所约束的部份,例如Android将驱动程序移到 Userspace,使得Linux driver 与 Linux kernel彻底分开。Bionic/Libc/Kernel/ 并非标准的Kernel header files。Android 的 Kernel header 是利用工具由 Linux Kernel header 所产生的,这样做是为了保留常数、数据结构与宏。
Android 的 Linux kernel控制包括安全(Security),存储器管理(Memory Management),程序管理(Process Management),网络堆栈(Network Stack),驱动程序模型(Driver Model)等。下载Android源码之前,先要安装其构建工具 Repo来初始化源码。Repo 是 Android 用来辅助Git工作的一个工具。 APK是安卓应用的后缀,是AndroidPackage的缩写,即Android安装包祥陵誉(apk)。APK是类似Symbian Sis或Sisx的文件格式。通过将APK文件直接传到Android模拟器或Android手机中执行即可安装。apk文件和sis一样,把android sdk编译的工程打包成一个安装程序文件,格式为apk。 APK文件其实是zip格式,但后缀名被修改为apk,通过UnZip解压后,可以看到Dex文件,Dex是Dalvik VM executes的全称,即Android Dalvik执行程序,并非Java ME的字节码而是Dalvik字节码。
APK文件结构
一个APK文件结构为:
1. META-INF (注:Jar文件中常可以看到);
2. res (注:存放资源文件的目录) ;
3. AndroidManifest.xml (注:程序全局配置文件) ;
4. classes.dex (注:Dalvik字节码);
5. resources.arsc (注:编译后的二进制资源文件)。
总结下我们发现Android在运行一个程序时首先需要UnZip,然后类似Symbian那样直接执行安装,和Windows Mobile中的PE文件有区别,这样做对于程序的保密性和可靠性不是很高,通过dexmp命令可以反编译,但这样做符合发展规律,微软的 Windows Gadgets或者说WPF也采用了这种构架方式。
在Android平台中dalvik vm的执行文件被打包为apk格式,最终运行时加载器会解压然后获取编译后androidmanifest.xml文件中的permission分支相关的安全访问,但仍然存在很多安全限制,如果你将apk文件传到/system/app文件夹下会发现执行是不受限制的。
最终我们平时安装的文件可能不是这个文件夹,而在android rom中系统的apk文件默认会放入这个文件夹,它们拥有着root权限。 Android 的HAL(硬件抽像层)是能以封闭源码形式提供硬件驱动模块。HAL 的目的是为了把 Android framework 与 Linux kernel 隔开,让 Android 不至过度依赖 Linux kernel,以达成 Kernel independent 的概念汪塌,也让 Android framework 的开发能在不考量驱动程序实现的前提下进行发展。
HAL stub 是一种代理人(Proxy)的概念,Stub 是以 *.so 档的形式存在。Stub 向 HAL“提供”操作函数(Operations),并由 Android runtime 向 HAL 取得 Stub 的Operations,再 Callback 这些操作函数。HAL 里包含了许多的 Stub(代理人)。Runtime 只要说明“类型”,即 Mole ID,就可以取得操作函数。 操作系统与应用程序的沟通桥梁,应用分为两层:函数层(Library)和虚拟机(Virtual Machine)。 Bionic是 Android 改良libc的版本。Android 同时包含了Webkit,所谓的Webkit 就是Apple Safari 浏览器背后的引擎。Surface flinger 是就2D或3D的内容显示到屏幕上。Android使用工具链(Toolchain)为Google自制的Bionic Libc。
Android采用OpenCORE作为基础多媒体框架。Open CORE可分7大块:PVPlayer、PVAuthor、Codec、PacketVideo Multimedia Framework(PVMF)、Operating System Compatibility Library(OSCL)、Common、OpenMAX。
Android 使用skia 为核心图形引擎,搭配OpenGL/ES。skia与Linux Cairo功能相当,但相较于Linux Cairo, skia 功能还只是雏形的。2005年Skia公司被Google收购,2007年初,Skia GL源码被公开,Skia 也是Google Chrome 的图形引擎。
Android的多媒体数据库采用SQLite数据库系统。数据库又分为共用数据库及私用数据库。用户可通过ContentResolver类(Column)取得共用数据库。
Android的中间层多以Java 实现,并且采用特殊的Dalvik 虚拟机(Dalvik Virtual Machine)。Dalvik虚拟机是一种“暂存器型态”(Register Based)的Java虚拟机,变量皆存放于暂存器中,虚拟机的指令相对减少。
Dalvik虚拟机可以有多个实例(Instance), 每个Android应用程序都用一个自属的Dalvik虚拟机来运行,让系统在运行程序时可达到优化。Dalvik 虚拟机并非运行Java字节码(Bytecode),而是运行一种称为.dex格式的文件。 Android本身是一个权限分立的操作系统。在这类操作系统中,每个应用都以唯一的一个系统识别身份运行(Linux用户ID与群组ID)。系统的各部分也分别使用各自独立的识别方式。Linux就是这样将应用与应用,应用与系统隔离开。
系统更多的安全功能通过权限机制提供。权限可以限制某个特定进程的特定操作,也可以限制每个URI权限对特定数据段的访问。
Android安全架构的核心设计思想是,在默认设置下,所有应用都没有权限对其他应用、系统或用户进行较大影响的操作。这其中包括读写用户隐私数据(联系人或电子邮件),读写其他应用文件,访问网络或阻止设备待机等。
安装应用时,在检查程序签名提及的权限,且经过用户确认后,软件包安装器会给予应用权限。从用户角度看,一款Android应用通常会要求如下的权限:
拨打电话、发送短信或彩信、修改/删除SD卡上的内容、读取联系人的信息、读取日程信的息,写入日程数据、读取电话状态或识别码、精确的(基于GPS)地理位置、模糊的(基于网络获取)地理位置、创建蓝牙连接、对互联网的完全访问、查看网络状态,查看WiFi状态、避免手机待机、修改系统全局设置、读取同步设定、开机自启动、重启其他应用、终止运行中的应用、设定偏好应用、震动控制、拍摄图片等。
一款应用应该根据自身提供的功能,要求合理的权限。用户也可以分析一款应用所需权限,从而简单判定这款应用是否安全。如一款应用是不带广告的单机版,也没有任何附加的内容需要下载,那么它要求访问网络的权限就比较可疑。
㈤ Android APP加密方法都有哪些
1 伪加密是Android4.2.x系统发布前的Android加密方式之一,通过java代码对APK(压缩文件)进行伪加密,其修改原理是修改连续4位字节标记为”P K 01 02”的后第5位字节,奇数表示不加密偶数表示加密。
2 混淆保护
把原来有具体含义的类名,变量名,方法名,修改成让人看不懂的名字,例如方法名getUserName编程了方法名。
混淆保护只是增加了代码阅读难度,对于破解基本上是没有实质性作用的
运行时验证,主要是指在代码启动的时候本地获取签名信息然后对签名信息进行检验来判断自己的应用是否是正版,如果签名信息不是正版则提示盗版或者直接崩溃。当然你可以把必要的数据放在服务器端。Android APP加密方法都有哪些?破解:找到smali文件中,判断是否相等的部分。改为常量true,即失效。
总之,反编译一些apk之后,只要是java代码写的总会有smil文件。对于smil文件,如果耐心读的话,还是可以查看到一些关键代码的。
相较于应用来说,游戏apk因为采用cocos2d-x或者 unity3D,采用的是c++和c# 编写的跨平台程序,在apk采用JNI的方式。所以没有smali,可以防止静态被破解apk包。
当然游戏包apk在运行的时候,会把.*so加载到内存中。动态也是可以在内存中抓取相应的数据。只不过NDK相对于smali破解来说,根部不是一个层级的关系。
3 使用第三方Android加密平台
㈥ 安卓app360加固怎么反编译
1 对比
上传demo进行加固,解包后对比下原包和加固包,发现加固包在assets文件夹下多了libjiagu.so,libjiagu_x86,lib文件夹下多了libjiagu_art.so,同时修改了dex文件和AndroidManifest文件
打开manifest文件,看到xxx加固对Application标签做了修改,添加了壳入口,也就是我们反编译后看到的StubApplication.smali这个文件。
相比于之前版本的加固,自从1.x.x.x加固版本之后,多了几次反调试,使得动态难度稍微增大了一些,不过针对脱壳机脱壳,再多了反调试也是无用。或者通过修改系统源码,也能达到消除反调试的作用。
2 动态调试
(1)把app安装到手机,以调试模式打开app
(2)以shell模式root权限打开IDA的android_server监听
(3)tcp转发
(4)打开IDA,修改配置为在进程开始时下断
(5)搜索到进程后jdwp转发,pid值即为我们进程号,并在命令行下附加。
成功附加后,可以下段了,打开Debugger Option
我们选择在线程开始和库加载时下断,修改成功后,jdb附加,点击运行
程序会断在elf头处,按下G键,搜索mmap,在mmap函数的段首和断尾下段
F9运行,来到断尾时F8单步,
来到此处时,在 BLunk_5C999C2C下断,F9一下,F7跟进去
跟进去今后在BLX LR处进行下断,此处就是进行反调试的地方,原理依然是获取TracePid的值判断当前是不是处于调试状态,建议第一次调试的人在fgets和fopen处下断,再f7跟进此调用就可以看到TracePid的值了。
跟进去之后,我们直接把方法移到最下方,就可以看到kill符号了,这就是杀进程的地方,如果当前处于调试状态,则直接结束进程。
我们在此函数的所有cmpR0,#0处下断,F9一下后即断在断点处,观察寄存器窗口的R0值,实质就是当前的TracePid的16进制的值
不确定的可以使用cat /proc/pid/status进行对比一下,我们直接把R0置0,右键选择Zero Value即可清0,继续F9
我们看到程序又来到了mmap处,继续f9
当继续断在调用反调试功能的方法时,继续F7跟进,依然在所有的cmp R0,#0处下断,断下后把R0清0后继续F9运行
目前的规律是,调用BLXLR的第一次,第二次和第四次是进行反调试判断的,第三次并不影响,可以直接f9跳过去,三次反调试搞定后,就可以愉快的F9运行并观察堆栈窗口了
当看到出现如下所示时:
说明壳已经开始解密并释放dex文件了,我们直接F8单步十几步,最后F9一下就可以看到我们需要的dex头了
直接脚本mp出来即可,最后把libjiagu的所有文件删除,并修复下Application标,如果存在则修复,不存在删除即可
㈦ android怎样破解已使用加壳技术的APP
破解加了dex壳的app,关键是要获得解密后的源dex,现在Android加壳技术大多都是通过DexClassLoader或者隐藏的函数openDexFile来将源dex加载进来,然后动态替换Application来启动源程序,跟Windows上传统的PE文件加壳有一定区别。
要破解传统的壳,需要跟踪控制流找到OEP,然后把源程序从内存中mp下来,重建输入表,最困难的就是要跟着外壳的控制流走,安全工程师为了加大破解难度,使用了很多技术来让破解者走得更艰难。安全工程师与破解者对抗的关键点就在寻找OEP的困难性上。
在Android平台上,正因为新兴的dex加壳技术不成熟,导致有些另类的脱壳方法可以绕过分析算法,直接将源程序mp下来。
举个例子,安卓在4.0版本以后提供openDexFile这个函数来从内存中加载dex,所需要提供的参数是源dex在内存中的地址,所以只要对这个函数下断,然后从寄存器里找到内存地址,就能将解密后的源dex从内存中mp下来,直接对其反编译就能获得源代码了。
更进一步,关于openDexFile这个函数,其实它与libdvm.so这个库有密不可分的关系,这个库里提供大量操作dex文件的函数,如果对这个库里的相关函数下断,然后从内存中暴力mp一大块内存区域,经常能直接将内存中的源dex给抓下来。