当前位置:   article > 正文

Android平台框架学习

onnewlntent

最强Android架构剖析pdf notes:
1.Froyo(冻酸奶) Android 2.2-2.2.3 开始支持sd卡上安装应用,引入usb网络共享技术,
  通过引入jit(及时编译技术),提高dalvik运行速度(目前不会有什么设备还在使用比
  Froyo版本更早的系统了)。
2.Gingerbread(姜饼人) Android 2.3-2.3.7 引入并发的垃圾回收机制(运行应用时,同时
  运行gc,之前是运行gc要暂停应用运行),与传感器相关的hal层被大大扩展支持更多类型的
  传感器,引入对nfc(近场通信)的支持,支持obb(apk扩展文件,apk包的大小不超过50m,obb
  解决了这个限制,同时还能加密放在应用中的数据),ext4代替yaffs作为默认的文件系统。
3.Honeycomb(蜂巢) Android 3.0-3.2.6 引入fragment,可作为平板电脑系统,引入硬件加速
  的opengl渲染2d,还引入了renderscript(Android自己类的gl语言),Android进入存储加密时代
  支持在底层加密用户数据分区(与ios4同一起跑线,它也支持这个技术),是唯一一个源码没被
  公开的Android版本。
4.Ice Cream Sandwich(冰淇淋三明治) Android 4.0-4.0.4 ui有大量加强,加入网络新特性(vpn,
  wifi direct,android beam),新增api onTrimMemory(int level)回调函数(这个api会在系统
  内存不足时会被调用,根据传进来的level指定内存不足的等级)。
5.JellyBean(果冻豆) Android 4.1-4.3 支持在同一设备上有多个用户账户(更多使用在平板上),
  在Froyo基础上的ASEC容器提供了应用加密和预先锁定特性(ASEC提供一个安全存放数据的容器
  应用可以加密存放在其中的数据,并使之只能被使用该应用对应的uid进程读取),api17引入
  SELinux,api18支持(opengl_es3.0,蓝牙avrcp1.3和蓝牙低耗le) 。
6.KitKat(奇巧) Android 4.4-4.4.4 重点是“瘦身”(在低端设备上提供更流畅的操作体验
  ,重写框架代码,降低其内存所需,串行启动各个服务,减轻内存压力),引入ART作为dalvik
  虚拟机的一个可选的替代方案,
7.Lollipop(棒棒糖) Android 5.0-5.1.1 ui引入Material Design(扁平化的界面接口,为了让
  界面上的各元素能够拥有真实的光影效果),采用了ART虚拟机(通过使用AOT-Ahead of time 
  预先编译技术而不是JIT-just-in-time,提前将Dalvik字节码编译成原生代码为系统带来了很
  大的性能提升,除此之外ART还让app充分利用64位处理器),支持opengles 3.1,引入camera
  api2。
8.Marshmallow(棉花糖) Android 6.0 支持(移动支付,内置指纹认证授权),权限的强制检查
  和授予被移到了rt完成(降低恶意软件窃取私人信息),数据加密的改进(可以扩展到对整个
  存储分区以及扩展存储设备进行加密)。
9.Nougat(牛轧糖) Android 7.0-7.1 带来多窗口功能,支持重按手势,支持Vulkan新的3D渲染
  api的支持并在平台上支持VR应用,引入新的启动模式direct-boot(在系统启动后就能运行,
  之前是用户解锁屏幕后才会运行),增加新的特性(基于文件的加密,紧追ios的cprotect机制)。
10.android.os.Build.VERSION.SDK_INT 或者 adb shell getprop ro.build.version.sdk
  (获取Android系统api版本)具体的Android版本及其对应的api level如下:
Pie                     Android9        API 级别 28
Oreo                     Android8.1.0        API 级别 27
Oreo                     Android8.0.0        API 级别 26
Nougat                     Android7.1        API 级别 25
Nougat                     Android7.0        API 级别 24
Marshmallow             Android6.0        API 级别 23
Lollipop             Android5.1        API 级别 22
Lollipop             Android5.0        API 级别 21
KitKat                     Android4.4.4       API 级别 20
KitKat                     Android4.4        API 级别 19
Jelly Bean(MR2)     Android4.3        API 级别 18
Jelly Bean(MR1)     Android4.2-4.2.2   API 级别 17
Jelly Bean             Android4.1-4.1.1   API 级别 16
Ice Cream Sandwich(MR1) Android4.0.3-4.0.4 API 级别 15
Ice Cream Sandwich     Android4.0.1-4.0.2 API 级别 14
Honeycomb(MR2)             Android3.2-3.2.6   API 级别 13
Honeycomb(MR1)      Android3.1        API 级别 12
Honeycomb             Android3.0        API 级别 11
Gingerbread(MR1)     Android2.3.3-2.3.7 API 级别 10
Gingerbread             Android2.3-2.3.2   API 级别 9
Froyo                    Android2.2.2-2.2.3 API 级别 8
11.Android取得成功的关键因素之一是他丰富的的框架集。没有这些框架集可能会混的很差,通过提
   供各种框架Android让应用可以很方便地创建进程,允许开发者使用高级的java语言而不是底层
   的c/c++语言进行编程。
12.位于命名空间android.*中的包是供开发者使用,而位于com.android.*仅供系统内部使用。Android
   使用的所有框架都是被打包在设备的/system/framework/目录下的*.jar文件 L版本则是被编译进
   了boot.jar中。
13.Android中对Linux的扩展有引入Dalvik虚拟机(Dalvik名字是为了纪念冰岛北部的一个小渔村)。
   他运行的字节码是dex是dalvik executable缩写。相对于sun/oracle设计的jvm他在执行效率和共
   享方面做了更多的优化。
14.OTA(over the air Technology)升级系统,Android系統提供的標準軟體升級方式,可以無損失升級系統,
   主要手段是通過網絡自動下載OTA升級包、自動升級,也支持通過下載OTA升級包到SD卡升級。
   OTA升级相比刷机升级,好处是显而易见的,OTA升级可以直接在手机中在线完成,只需要借助移动网络或者
   Wifi网络即可,且升级无需备份数据,一般升级完成后,自动重启手机即可完成。而一般的刷固件升级,
   需要下载ROM固件,并且还需要刷机。不过升级过程中会下载一些升级包,会占据一些手机内存存储空间,
   另外如果手机系统非常卡,OTA升级系统也解决不了卡问题,但是转载自电脑百事网如果通过刷固件升级,
   可以将系统恢复到最初的纯净状态,对系统流畅性有一定帮助,只不过刷机升级比较麻烦,并且会清空手机数据。
15.boot镜像,他一般是由内核和ram disk组成的,作用是加载系统,假设启动正常,ram disk会
   被Android用作root文件系统(/),其中的/init.rc及相关的文件规定了系统余下的其他部分
   该如何被加载,boot镜像会被刷到boot分区去。
16.recovery镜像,由内核和另一个ram disk组成的,一般用来在正常的启动失败或者通过ota升级时,把
   系统加载到“recovery 模式”。这个镜像会被刷到recovery分区。
17./system分区镜像,这里存放着完整的Android系统,其中除了谷歌提供的二进制可执行文件和框架
   还有厂商和运营商提供类似的东西。
18./data 分区镜像,这里存放着默认出厂设置的数据文件,他们是/system分区中程序正常运行必须的文件
   当手机需要重置到出厂状态时也只需把这个分区镜像刷到/data分区,覆盖原来的数据即可。 
19.bootloader启动加载器(作用是将经过压缩的内核zImage和RAM disk加载到内存中),虽然Android设备的厂商可以随心所欲去实现自己的启动加载器,但他们大多选择lk(little
   kernel)启动加载器,lk只实现了启动功能中最基本的那一部分(lk只是个运行在arm处理器上的二进制镜像):
   基本的硬件支持,找到并启动内核(所有启动加载器的目的都是找到bootimage),基本的ui,支持console,
   使设备可被用作usb目标设备,支持闪存分区,支持数字签名。
20.bootloader也可以像其他系统镜像一样更新或者重刷。
21.boot镜像中存储的是操作系统的核心组件,内核和RAM disk。他的组成部分还有一个很小的头部,内核命令行
   一个hash以及一个可选的二级启动加载器。
22.linux支持两种文件格式的RAM disk(他提供了最初的文件系统,在操作系统启动时,它被用作根文件系统,
   他会和内核一起被boot loader预加载到ram):initrd ext4文件系统镜像和initramfs cpio文件(只需占用
   很少内存空间的简单格式)。
22.与大多数操作系统的内核不同,Linux的内核大多是经过压缩的。
23.手机启动:
   固件启动,boot ROM(是记录在只读部件中的,是记录一小段在手机刚一加电到加载sbl之前必须要先执行
   的启动代码)执行pbl(初级启动加载器)初始化其他的硬件部件,使他们处于至少可以使用的状态,然后boot ROM就会加载sbl(次级启动加载器
   ,sbl是一个软件,不受硬件rom容量限制,可以记录更多数据,所以可执行更复杂的初始化任务,如,显示一个启动画面),然后应用处理器才
   能启动其他的组件,执行aboot中的代码,然后才是Android的boot loader正式登场。
   ---->
   内核启动过程,Android内核的启动过程和linux的没什么太大的区别。内核启动线程执行完毕后会转入用户态。
   用PID 1启动/init(运行的各种Android相关的服务)。
   ---->
   Android 进程init(主要是加载他的配置文件主要有两个init.rc init.内核参数获取到的字符串.rc),
   所有unix系统都有个特殊的进程,他是内核启动完毕后,用户态中启动的第一个进程,负责
   启动系统,并作为系统中其他进程的祖先进程,Android也沿用可这个约定俗成的规矩。init能识别特定的前缀,
   这些前缀表示该如何处理这些属性(persist:系统重启后依然生效,ro:标记只读属性)。init.rc中的各个启动
   阶段:
       1.early-init 初始化的第一个阶段,用于设置selinux和oom
       2.init 创建文件系统,mount点以及写内核变量
       ...
   init 进程的初始化工作由以下步骤组成:
       1.检查自身这个二进制可执行文件是不是被当成ueventd或者watchdogd调用,如果是的话余下执行流程会转到
         相应的守护进程的主循环那。
       2.创建/dev /proc /sys等目录并且mount他们
       3.添加文件/dev/.booting ,在启动完毕后这个文件会被清空
       4.调用open_devnull_stdio()函数完成守护进程化。
       ...
        把init.rc文件中各个on语句块里规定的action以及内置的action添加到一个名为action_queue的队列里去
        最后主循环中将逐个执行init.rc文件的命令,然后init在大部分时间处于休眠状态。
24.Android在后台运行着好几个守护进程,用来完成各种杂七杂八的事务性和操作性工作,这些服务的定义大多散落在
   init.rc文件中的service语句块中,唯一影响他们启动顺序的是他们所属的分类,分在core类中的服务会首先启动
   接着是main类中的服务(都是native service)。core类中服务(不需要访问/data分区):
                            1.adbd adb服务功能的守护进程,adb root会把系统属性service.adb.root 设为1。
                            2.healthd 健康度守护进程,周期性检测设备健康值。
                            3.lmkd(L) 实行low memory killer机制
                            4.logd(L) 实行日志机制
                            5.vold 卷管理守护进程
                        main类服务(网络服务):
                            1.netd 这个网络守护进程来控制各个网络接口并管理他们的配置
                            2.mdnsd 这个守护进程执行设备间相互发现的功能
                            3.mtpd 负责提供ppp 和 来l2tp功能的守护进程
                            4.racoon 负责vpn功能的守护进程
                            5.rild 负责移动设备e上提供所有电话相关的功能
                        main类服务(图形及多媒体服务):
                            1.surfaceflinger 位于Android图形栈中的中心位置
                            2.bootanimation 专门被surfaceflinger用作在它被加载时的占位符,以及开机动画
                              相关的设置(/data/local/bootanimation.zip或者/system/media/bootanimation.zip
                              desc .txt 文件的第一行中依次规定的是开机动画的宽度、高度以及每秒显示的帧数( fps )。
                              注意,组成开机动画的各个png图片也必须严格符合这一规格。
                              若都没有默认用在/system/framework/framework-res.apk的/assets/images目录里的图。)
                            3.mediaserver 负责录播功能的进程
                            4.drmserver 复制保护需求的内容提供一个数字版权管理的框架
                       main其他类服务:
                            1.installd 负责安装和卸载app的守护进程
                            2.keystore 负责提供密钥存储服务的守护进程
                            3.debuggerd 负责收集核心crash信息的守护进程
                            4.sdcard 提供用户态中对sd卡的支持的守护进程
                            5.zygote(虚拟机都是从Zygote 这里fork()出来的) 
                              提供一台初始化完毕的空的dalvik虚拟机的形式,
                              对所有Android框架运行时提供了核心支持
                              作用:缩短应用的启动时间,优化共享内存
25.strace 工具,跟踪进程中的系统调用(ps只是提供当前进程的快照,top是查看当前最活跃的进程 是strace -f -p pid)
26.Android 安全性是虚拟机层和原生代码层这两个层面共同提供的。从jellbean开始通过引入selinux,使用一个强制实施的访问
   控制框架,有效把所有进程置于沙箱里,将其束缚在可信区域内,到了lollipop版中,这些框架又被进一步扩展,已经对package
   进行限制。


Android进阶解密pdf notes
1.替代DVM的ART机制与DVM不同,DVM中的应用每次运行,字节码都需通过及时编译器转换为机器码,这使得应用的运行效率
  降低。而在ART中系统在安装应用的时会进行一次预编译(AOT)将字节码预先编译成机器码并存储本地,运行效率大大提高。
2.Android5.0以上源码目录结构:
        art              全新的ART运行环境
        bionic           系统c库
        bootable         启动引导相关代码
        build            存放系统编译规则及generic等基础开发包配置
        cts              Android兼容性测试套件标准
        dalvik           dalvik虚拟机
        developers       开发者目录
        development      与应用程序开发相关
        device           设备相关配置
        docs             参考文档目录
        external         开源模组相关文件
        frameworks     应用程序框架,Android系统核心部分,由java,c++编写(/base:向上提供接口给应用调用,向下与c/c++程序库及硬件抽象层做链接)
        hardware         主要是硬件抽象层的代码
        libcore          核心库相关文件
        libnativehelper  动态库,实现jni库的基础
        out              编译完成后的输出目录
        pdk              plug development kit 缩写,本地开发套件
        platform_testing 平台测试
        prebuilts        x86和arm架构下预编译的一些资源
        sdk              sdk和模拟器
        packages         应用程序包(/apps:核心应用程序 /experimental:第三方应用程序 inputmethods:输入法目录
                                    /providers:内容提供者目录 /screensaver:屏幕保护 /service:通信服务 /wallpapers:墙纸)
        system           底层文件系统库,应用和组件
        toolchain        工具链文件
        tools            工具文件
        makefile         全局makefile文件,用来定义编译规则
3.init进程(进口函数在源码system/core/init/init.cpp:LoadBootScripts(am,sm)->parser.ParseConfig("/init.rc");)linux内核加载完成后,
  他首先会查找系统文件中的init.rc(是Android初始化语言Android init language编写的脚本,包含5种类型语句:action,command,service,
  option,import)文件,并启动init进程(fork()方法创建子线程)。
  init进程启动主要是做了三件事(源码中可以看到):
           a.创建和挂载启动所需的文件目录
           b.初始化和启动属性服务
           c.解析init.rc配置文件并启动Zygote进程
4.Zygote进程启动和介绍:
     a.源码:/frameworks/base/cmds/app_process/app_main.cpp (runtime.start("com.android.internal.os.ZygoteInit", args, zygote))
     b.简介:Android系统中dvm,art,应用程序进程以及运行系统的关键服务的systemserver进程都是由Zygote进程创建,称之为孵化器。由于Zygote
             在启动时会创建dvm或art,因此通过fork而创建的应用进程和systemserver进程可以在内部获取一个dvm或art的实例副本。原来Zygote
             进程不是zygote而是app_process,这个名称是Android.mk中定义的,zygote进程启动后。linux系统下的pctrl系统会调用app_process
             将其名称换成zygote.
     c.zygote启动jvm,源码(/frameworks/base/core/jni/AndroidRuntime.cpp->if(startVm(&mJavaVM, &env,zygote)!= 0))随后会
       通过jni调用ZygoteInit.java(/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)中的main方法,然后
       zygote进入java框架层,在ZygoteInit.java main()方法中有启动systemserver进程( Runnable r = forkSystemServer(abiList, socketName, zygoteServer))
       ZygoteInit.java main()方法中主要做的4件事:
            1.创建一个server端的socket
            2.预加载类和资源
            3.启动systemserver进程
            4.等待AMS请求创建新的应用程序进程
     d.zygote进程启动共主要做的5件事
            1.创建APPruntime并调用start方法,启动zygote进程
            2.创建jvm,并为jvm注册jni方法
            3.通过jni调用zygoteinit.java main函数进入zygote的java框架层
            4.通过registerzygotesocket方法创建服务端的socket,并通过runselectloop方法等待ams的请求来创建新的应用程序进程
            5.启动systemserver进程
5.systemserver进程的介绍:
     a.zygoteinit.java中的forkSystemServer(abiList, socketName, zygoteServer)启动systemserver进程
     b.主要用于创建系统服务,AMS,WMS,PMS都是由它创建的。(主要操作在/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中)
     c.zygoteinit.java中通过ZygoteInit.nativeZygoteInit()方法创建binder线程池,这样systemserver进程就可以使用binder与其他进程通信了,RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader)
       方法用于进入systemserver的main方法(/frameworks/base/services/java/com/android/server/SystemServer.java)。
     d.SystemServer.java中有startBootstrapServices()方法(启动引导服务),startCoreServices()(启动核心服务),startOtherServices()(启动其他服务)
       引导服务(activitymanagerservice:负责四大组件的启动,切换,调度,packagemanagerservice:对apk安装,解析,删除,卸载等操作,等等其他服务)
       核心服务(batteryservice:管理电池的服务,usagestatsservice:收集用户使用app的频率和时长,等其他服务)
       其他服务(cameraservice:摄像头相关的服务,windowmanagerservice:窗口管理的服务,等其他服务)
     e.systemserver进程创建后主要做的3件事:
            1.启动binder线程池,这样可以与其他进程进行通信
            2.创建systemservicemanager用于对系统的服务进行创建,启动和生命周期管理
            3.启动各种系统服务
6.Launcher概述
     a.系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序是launcher,launcher启动
       过程会请求packagemanagerservice返回系统中已经安装的应用程序的信息,将这些信息封装成一个快捷图标列表显示在系统的
       屏幕上,用户可以点击图标来启动相应的应用程序。
     b.systemserver进程在启动的过程中启动packagemanagerservice,会将系统中的应用程序安装完成
       之前已启动的ams会启动launcher。启动launcher的入口是ams的systemReady方法(/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java,
       在systemserver.java的startotherservice方法中调用),getHomeIntent()后mActivityStartController.startHomeActivity(intent, aInfo, myReason)
       启动launcher了。
7.app进程启动:
     a.要启动一个应用程序,首先保证应用程序所需的应用程序进程已经启动。ams在启动应用程序时会检查
       这个应用程序需要的应用程序进程是否存在,不存在就会请求zygote进程启动需要的应用程序进程。
       zygote fork自身创建应用程序进程,这样应用程序进程创建过程中获取zygote进程启动时创建的
       虚拟机实例,除此之外还会创建binder线程池和消息循环,以此使用binder进行进程间通信及处理信息。
       应用程序进程启动后,就会创建一个消息循环。

8.应用程序根activity启动:
     a.有根activity(app的第一个activity)启动和普通activity启动
     b.根activity启动:
           1.Launcher请求AMS过程
              1.1点击app图标Launcher(会执行/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
                 ->startActivitySafely(View v, Intent intent, ItemInfo item)->/frameworks/base/core/java/android/app/Activity.java
                 ->startActivity(Intent intent, @Nullable Bundle options)->ActivityManager获取AMS代理对象,ActivityManager.getService()
                 ->/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java,AMS.startActivity())
                 请求AMS来启动该应用程序
           2.AMS到ApplicationThread调用过程
              2.1AMS.startActivity()->/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java(Android7.0新增),
                 startActivity()(参数里的caller是Launcher所在的应用进程的的ApplicationThread对象)-> startActivityUnchecked()
                 ,主要处理与栈管理相关的逻辑->/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java,
                 resumeFocusedStackTopActivityLocked()->/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java,
                 resumeTopActivityUncheckedLocked()->resumeTopActivityInnerLocked()->ActivityStackSupervisor.java,startSpecificActivityLocked()
                 ,获取该应用的进程,进程已运行->realStartActivityLocked(),ApplicationThread(ActivityThread的内部类)是AMS所在进程(system_server)和app进程的通信
                 桥梁,用app进程对象获取applicationthread,然后在调用applicationthread的相关方法,运行到app进程中(Android8.0是这样,Android9.0有点不同,但最终都会
                 进入ActivityThread.java中,也就是app进程中)。运行在上诉方法调用都是在AMS所在的进程。
           3.ActivityThread启动Activity
             3.1ActivityStackSupervisor.java,realStartActivityLocked()->/frameworks/base/core/java/android/app/ActivityThread.java,performLaunchActivity(),
                会获取要启动的activity的包名和类名,然后用类加载器来创建要启动的activity的实例,然后makeApplication方法会调用Application的onCreat方法,然后用activity
                实例调用attach方法(这个方法中会创建PhoneWindow对象与activity进行关联)初始化activity。->/frameworks/base/core/java/android/app/Instrumentation.java,
                callActivityOnCreate()->/frameworks/base/core/java/android/app/Activity.java,performCreate()->onCreate()到此根activity就启动了,即app程序启动了。
9.根Activity启动过程中涉及的进程
     a.首先Launcher进程向AMS请求创建根activity,AMS会判断该app进程是否存在,存在则启动,不存在则请求Zygote进程创建,app进程启动后,AMS启动根activity。
     b.普通activity启动过程会只涉及到AMS和app进程。
10.Service的启动过程
     a.分为两部分:
          1.ContextImpl到AMS的调用过程
             1.1/frameworks/base/core/java/android/content/ContextWrapper.java,startService()-                        >/frameworks/base/core/java/android/app/ContextImpl.java,
             startService()->startServiceCommon()->ActivityManager.getService().startService(),获取代理IActivityManager调用startService()->AMS的startService
             方法。
          2.ActivityThread启动Service
            2.1/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java,startService()->/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java,
               startServiceLocked()->startServiceInnerLocked()->bringUpServiceLocked(),获取service想在那个进程中运行,默认是当前app进程,也可以在AndroidManifest.xml配置android:process来指定想要运行的
               进程,如果该app进程存在-> realStartServiceLocked(),获取ActivityThread中的ApplicationThread->/frameworks/base/core/java/android/app/ActivityThread.java,scheduleCreateService()->
                handleCreateService()->service.attach(),service.onCreate()这样service就启动了。
    b.bindservice复杂些,但过程类似
11.Context
    a.Context意为上下文,是一个app程序环境信息的接口。
    b.使用context的方式有两种:1.启动activity,访问资源,调用系统服务等 2.调用方法时传入context,比如弹出toast,创建dialog等。
    c.activity,service,application简介继承context,一个app进程context数:activity数+service数+application数。
    d.Application Context创建过程:
          d.1先从app启动着手,ActivityThread.java(performLaunchActivity())->/frameworks/base/core/java/android/app/LoadedApk.java,
             makeApplication()->/frameworks/base/core/java/android/app/Instrumentation.java,newApplication()返回application并且attach
             传进来的ContextImpl->/frameworks/base/core/java/android/app/Application.java,attach()->/frameworks/base/core/java/android/content/ContextWrapper.java,
             attachBaseContext()把ContextWrapper中的mBase变量取值于刚才一路传进来的ContextImpl。所以getApplicationContext返回的是Application(继承自ContextWrapper
             里面的mBase是ContextImpl所以Application可以代表Context)。
    e.Activity Context创建过程

          e.1从启动activity开始,ActivityThread.java(performLaunchActivity())->createBaseContextForActivity()创建ContextImpl->appContext.setOuterContext(activity)
             ->activity.attach()先attachBaseContext(/frameworks/base/core/java/android/view/ContextThemeWrapper.java)然后attachBaseContext(/frameworks/base/core/java/android/content/ContextWrapper.java)
              把创建好的activity的ContextImpl赋值给ContextWrapper中的mBase变量(activity中getBaseContext()返回的就是这个mBase变量),然后再创建PhonWindow app程序窗口,创建好与Activity交互的回调,如点击等操作
             (mWindow.setCallback(activity))然后设置他的WindowManager,然后获取其WindowManager并赋值给activity对象中的mWindowManager变量。   
12.ActivityManagerService
    a.Android7.0中AM对activity进行管理,后面交给AMS处理,AM中通过AMN的getDefault方法获取到AMP,通过AMP就可以和AMN进行通信,而AMN是抽象类,他将功能交给
      子类AMS处理,因此AMP是AMS的代理类。Android8.0去掉了AMP,用的是AIDL进行通信。
    b.AMS启动是在SystemServer进程中启动的:
          a.1/frameworks/base/services/java/com/android/server/SystemServer.java,main()->new SystemServer().run()创建SystemServiceManager对系统的服务进行创建,启动和生命
             周期管理->startBootstrapServices()(创建启动mActivityManagerService = mSystemServiceManager.startService().getService())
          a.2/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java,startService(ActivityManagerService.Lifecycle.class(extends SystemService))->
             /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java,构造Lifecycle(Context context)(创建mService = new ActivityManagerService(context))->
             Lifecycle,onStart()(mService.start()),最后mSystemServiceManager.startService().getService()->Lifecycle,getService()(return  mService)。               
    c.数据结构
          c.1ActivityRecord,TaskRecord和ActivityStack,他们是Activity任务栈模型的基础。
          c.2ActivityRecord,内部记录了Activity的所有信息(如AndroidManifest节点信息),他用来描述一个Activity,他是启动Activity时被创建的
          c.3TaskRecord,内部记录了任务栈的所有信息(如启动此任务栈的intent),他是用来描述一个Activity任务栈的。
          c.4ActivityStack,用来管理系统所有的Activity,内部维护activity所有状态等数据。
    d.Activity栈管理
          d.1Activity LaunchMode和IntentFLAG(果LaunchMode和FLAG设定的Activity的启动方式有冲突,则以FLAG设定的为准。)
             standerd :默认模式,每次启动Activity 都会创建一个新的Activity 实例。
             singleTop:如果要启动的Activity 已经在栈顶,则不会重新创建Activity ,同时该
                         Activity 的onNewlntent 方怯会被调用。如果要启动的Activity 不在栈顶,则会重新
                         创建该Activity 的实例。(FLAG_ACTIVITY_SINGLE_TOP)
             singleTask:如果要启动的Activity 已经存在于它想要归属的栈中,那么不会创建该
                          Activity 实例,将栈中位于该Activity 上的所有的Activity 出栈,同时该Activity 的
                          onNewlntent 方法会被调用。如果要启动的Activity 不存在于它想要归属的栈中,井
                          且该栈存在,则会重新创建该Activity 的实例。如果要启动的Activity 想要归属的
                          栈不存在,则首先要创建一个新栈,然后创建该Activity 实例并压入到新栈中(根activity)。(FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK两者同时使用)
             singlelnstance:和singleTask 基本类似,不同的是启动Activity 时,首先要创建一个新栈,然后
                            创建该Activity 实例并压入新栈中,新栈中只会存在这一个Activity实例。
             FLAG_ACTIVITY_CLEAR_TOP:如果要启动的Activity存在栈中,则将所有位于他上面的Activity清出栈,并且如果intent加上flag,Intent.FLAG_ACTIVITY_SINGLE_TOP
                                     则该Activity会重用之前的,如果没加,则会一起清出栈,然后再重建实例。
             FLAG_ACTIVITY_NO_HISTORY:activity不压入栈中一但离开就不会在栈中(c b a -> c启动d(设置该flag)->d启动e->栈中变成e c b a)
             FLAG_ACTIVITY_
             
          d.2android:taskAffinity xml属性只有在launchMode=singleTask或者FLAG_ACTIVITY_NEW_TASK的时候才有作用,这个属性可以把不同的Activity分在不同的任务栈中。
13.WindowManager
    a.PhonWindow是在Activity启动过程中的attach方法中创建的/frameworks/base/core/java/android/app/Activity.java,attach()( mWindow = new PhoneWindow(this, window, activityConfigCallback),
      mWindow.setWindowManager()设置管理器)
14.JNI(java native interface)
    a.jni方法注册,静态注册(多用于ndk开发),动态注册(多用于framework开发)
          a.1jni 中JNIEnv是native世界中的java环境的代表,JNIEnv*指针就可以在native世界中访问java世界的代码进行操作。
             jclass是jni的数据类型对应java的java.lang.Class实例,jobject也是jni数据类型,对应java的Object
          a.2静态注册是java的native方法通过方法指针来与jni进行关联(根据默认的jni函数生成规则来关联):
              a.2.1缺点是jni层函数名称过长,声明native方法需要用javah生成头文件,初次调用native方法时需要创建关联
                   影响效率。
          a.3动态注册,用一种结构记录java的native方法和jni方法的关联关系它就是JNINativeMethod(在jni.h中被定义):
             typedef struct{
               
               const char* name;//java方法名             
               
               const char* signature;//java方法的签名信息
               
               void* fnPtr;//jni中对应java的方法的方法指针

             }
            创建好这个要注册的结构体组,然后在JNI_OnLoad函数(System.loadLibrary函数调用后被调用)中最后通过
            最终通过调用的JNIEnv的RegisterNatives函数来完成JNI的注册。
          a.4在jni_onload函数中注册native方法主要步骤(参考地址:http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp):
             每个步骤要check是否操作成功,失败直接返回
               a.4.1check jni version,并且获取JNIEnv* env
               a.4.2用jclass clazz=env->FindClass(声明native方法的java类,包名+类名,“.”用“/”代替的字符串)赋值
               a.4.3最后env->RegisterNatives(clazz, gMethods, numMethods)来注册native方法
15.java jni基本数据对应关系:
    Java                 Native                  Signature(方法签名,在包装注册native方法的结构体中,用“(参数签名)反回类型签名”来表示如“()[F”)
   
    byte          jbyte            B        
  char          jchar            C
  double         jdouble           D
  float         jfloat            F
  int            jint             I
  short         jshort            S
  long          jlong            J
  boolean        jboolean          Z
  void           void            V

   java jni 引用数据类型的对应关系:
                                                   L+classname+;
    Class                 jclass                   Ljava/lang/Class;
    String                jstring                  Ljava/lang/String;
    Throwable             jthrowable               Ljava/lang/Throwable;
    Object[]              jobjectArray             [Ljava/lang/Object;           
    byte[]                jbyteArray               [B
     ....
16.通过java文件生成签名文件:
    a.javac xxx.java->javap -s -p xxx.class
17.无论是c(typedef const struct JNINativeInterface* JNIEnv)还是c++(typedef _JNIEnv JNIEnv,struct _JNIEnv)
   jnienv类型都和jninativeinterface结构(有FindClass和GetMethodID方法等)有关。
18.Jni引用类型:
    a.1本地引用,当native方法返回时,会被自动释放。只在创建他的线程有用,不能垮线程使用。受jvm管理。
    a.2全局引用,native方法返回时不会被释放,不会被gc回收,需要手动释放。可以跨线程使用。不受jvm管理。
    a.3弱全局引用,和全局引用差不多,但是不同的点是可以被gc回收然后指向NULL
19.java虚拟机(是整个java平台的基石,是java语言编译代码的运行平台):
    a.JDK(Java development kit)包含java语言,java虚拟机,java api类库,是java程序开发的最小环境。
    b.java虚拟机与java语言没有必要的联系,只与特定的二进制文件class有关,无论任何语言,只要能编译层
      class文件就可以被jvm识别并执行。                                                                                                                      c.一个java文件加载到java虚拟机内存中从内存中卸载的过程叫类的生命周期(加载,链接(验证,准备和解析),初始化,使用和卸载)
         c.1加载:查找并加载Class文件。
         c.2链接:包括(验证:确保被导入的类型正确性,准备:为类的静态字段分配字段并用默认值初始化这些字段,解析:虚拟机将常量池内的符号
                  引用替换为直接引用)
         c.3初始化:将类变量初始化为正确的初始值
    d.jvm两种类加载器,自定义类加载器(通过继承java.lang.ClassLoader类),系统加载器(引导类加载器:用c/c++实现用于加载JDK核心类库,jvm的启动就是通过
      这个加载器创建个初始类来完成的;拓展类加载器:用于加载java的拓展类,加载jre/lib/ext目录下的类库等;应用程序类加载器:
      又被称为系统类加载器,用于加载当前app classpath目录类库等)。
    f.java虚拟机在执行java程序的过程中会把他所管理的内存区域划分为不同的数据区域:
         f.1程序计数器:保证程序连续执行,处理器必须具有某些手段确定下条指令的地址,他就是起这个作用的。jvm中字节码解释器工作时是通过改变计数器来选取
            下一条需要执行的字节码指令的。还是线程私有化的。程序计数器是jvm中唯一没有规定任何oom情况的数据区域。
         f.2jvm栈:每一条jvm线程都有个线程私有的jvm栈,生命周期与线程相同,栈中存储线程中java方法的调用状态,包括局部变量,参数,返回值
                   返回值以及运算结果等。平时说的栈内存指的是jvm栈。
         f.3本地方法栈:jvm实现可能要用到c stacks来支持native语言,这个c stacks就是本地方法栈。
         f.4java堆(heap):java heap 是被所有线程共享的运行时内存区域,用来放对象实例,几乎所有的
                            对象实例都在这里分配内存,这些对象被垃圾收集器管理。
         f.5方法区:是被所有线程共享的运行时区域,用来存储已经被java虚拟机加载的类的结构信息,包括
                    运行时常量池,字段和方法信息,静态变量等数据,方法区是java堆的逻辑组成部分。
         f.6运行时常量池:class文件不仅包含类的版本,接口,字段和方法等信息还包含常量池,用来存放
                         编译时期生成的字面量和符号引用,这些内容在类加载后存放在方法区的运行时常
                         量池中。
20.Dalvik虚拟机(DVM,是Google专门为Android平台开发的虚拟机)
     a.DVM和JVM区别:
         a.1基于的架构不同,jvm是基于栈在栈中读写数据,所需指令更多,导致速度变慢,dvm基于寄存器
            指令紧凑,简洁,指令比基于栈的指令大,但是数量少。
         a.2执行的字节码不同,java se程序中java类被编译成.class文件并打包成jar,然后jvm通过相应的class
            文件和jar文件(包含多个class文件,其包含了该类的常量池,类信息,属性等)获取相应的字节码
           (.java->.class->.jar),dvm会用dx工具把所有的.class文件转化为.dex文件,然后dvm从.dex文
            件读取指令和数据(.java->.class->.dex)。jvm加载jar,然后加载里面所有的class文件,这种
            加载方式很慢,对内存有限的移动设备不合适。而在.apk中的dex文件将所有的.class包含的信息整
            合在一起,这样加载速度就很快,class文件包含很多的冗余信息,dex工具会去除这些信息,并把所有
            的class文件整合到dex文件,减少了i/o操作,加快了类的查找速度。
         a.3dvm允许在有限的内存中同时运行多个线程,Android中每个应用都运行在一个DVM实例中,每个DVM实例
            都运行在独立的进程中。
         a.4DVM由Zygote进程创建和初始化,需要创建一个app应用时,Zygote会fork自身,快速创建和初始化一个DVM实例
            用于app的运行。
         a.5dvm有共享机制,dvm拥有预加载共享的机制,不同的app之间在运行时可以共享相同的类,有更高的效率,jvm
            不存在这种共享,不同的程序是彼此独立的,即使使用了相同的类,运行时也是单独加载运行,无法共享。
         a.6dvm早期没有jit,jvm使用了jit,而早期的dvm没有使用,每次执行代码时,都需要通过解释器将dex代码编译成
            机器码,然后交给系统处理,效率不高。在Android2.2后dvm使用了jit,会对多次运行的代码进行编译,下次执行
            相同的逻辑时,直接使用,效率变高了。
21.dvm源码位于dalvik/目录下:
        a.1 dexdump:生成dex文件的反编译查看工具,主要用来查看编译出来的代码的正确性和结构
            dexgen:  dex代码生成器项目
            dx:      java字节码转化为dvm机器码工具
            libdex: 生成主机和设备处理dex文件的库
            tools:   一些编译和运行相关的工具
22.ART虚拟机(Android4.4发布的,用来替换Dalvik虚拟机,Android5.0默认采用ART)
       a.1art和dvm区别:
          a.1.1dvm中应用每次运行时,字节码都需要jit编译器编译为机器码,使得app运行效率变低,而在art中,系统在安装app时会进行一次aot(ahead of time complie),将字节码预先编译成机器码存储在本地,app每次运行就不需要执行编译了,效率大大提高。但是安装时间变长,机器码需要的存储空间变大,在Android7.0中art中加入jit作为aot的一个补充,在app安装的时候不会将字节码全部编译成机器码,而在运行中将热点代码编译成机器码,从而缩短app安装时间和节省空间。
          a.1.2dvm是为32位cpu设计的,而art支持64位并兼容32位cpu
          a.1.3art对垃圾回收进行了改进,频繁执行gc,减少gc暂停次数。
          a.1.4art运行时堆栈空间划分和dvm不同
23.查看Android系统运行用的是dvm还是art 获取系统属性值(adb shell getprop persist.sys.dalvik.vm.lib.2 如果是libart.so是art
    如果是libdvm.so则是dvm)。
24.Android中的ClassLoader
      a.1java classloader加载jar,class,Android classloader加载dex
      b.Android classloader分为自定义类加载器和系统类加载器(bootclassloader,pathclassloader,dexclassloader)
        同样遵循双亲委托模式加载方法为loadclass()
          b.1bootclassloader Android系统启动时会用这个加载器预加载常用类,用java实现的,是/libcore/ojluni/src/main/java/java/lang/ClassLoader.java内部单例子类
          b.2dexclassloader 可以用来加载dex文件以及包含dex压缩的文件(apk和jar文件),最终都要加载dex文件
                             继承自/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java,方怯都在BaseDexClassLoader中实现。
          b.3pathclassloader 用来加载系统类和app的类,继承自/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
                             通常用来加载已安装的apk的dex文件(安装的apk dex文件存储在/data/dalvik-cahe中)。
25.热修复
      a.核心技术(代码修复(类加载方案:是先加载新的dex,把旧dex挤下去,不加载;底层替换方案:和反射有关,替换关于方法信息的结构体或其中的字段;
        Instant run方案:和ASM有关,是java字节码操控框架,可直接参产生class文件,也可以在类被加载到虚拟机前动态改变类的行为),资源修复
       (参考Instant Run,AS2.0新增的运行机制),动态链接库修复(原理是加载so,加载so主要是/libcore/ojluni/src/main/java/java/lang/System.java类的load和loadLibrary
        load是加载指定的完整路径的so,而loadLibrary是加载app安装后自动从apk包里复制到/data/data/packagename/lib下的so,两个方法都会调用/libcore/ojluni/src/main/native/Runtime.c
        的nativeLoad方法->/art/openjdkjvm/OpenjdkJvm.cc, JVM_NativeLoad(),修复的原理是新的so放到要加载的前面,旧的so就不会被加载))。

other:
 1.添加ssh key :
   1.1 ssh-keygen.exe -t rsa
   1.2 cat ~/.ssh/id_rsa.pub 看key拷贝到项目仓库处,完成设置
   1.3 然后git clone 地址 就可以拉下来了
 2.用ndk自带工具编译可执行程序:
   2.1 aarch64-linux-android-gcc.exe -g -fpie -pie --sysroot=E:\AndroidNDK\android-ndk-r14b\platforms\android-22\arch-arm64 
       E:\AndroidNDK\android-ndk-r14b\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\22m\valgrind_text.cpp 
       -o vargrind_run -lstdc++
 3.valgrind 使用,编译好版本把lib和bin文件拷入手机中然后设置权限777,然后设置库路径
    export VALGRIND_LIB="/...../lib/valgrind"最后执行(在bin目录下)
    ./valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --log-file="valgrind.log" /data/local/vargrind_run

 4.关于checkleak工具使用,相关的camera进程的手动启动问题
  4.1打开camera top后可以看到camera相关的进程名字如(相关的camera进程名字cameraserver) :
    11425 cameraserver 20   0 1.3G 136M  40M S  145   4.8   0:08.51 camerahalserver ASAN_OPTIONS=abort_on_error=1
    1320 u0_a43       -2   0 4.1G 136M 105M S 27.0   4.8   0:43.99 com.mediatek.camera
    9338 root         20   0  48M 2.8M 1.1M R 23.3   0.1   0:49.32 adbd --root_seclabel=u:r:su:s0
    319 logd         18  -2  72M  58M 2.7M S 22.6   2.0   1:14.38 logd
    371 system       -2  -8 2.1G  32M  29M S 12.0   1.1   1:15.26 surfaceflinger
    5677 root         20   0 9.0M 3.0M 2.4M R 10.0   0.1   0:11.38 logcat -v long -v epoch
    358 system       -3   0  36M 9.2M 8.3M S  5.3   0.3   0:37.67 android.hardware.graphics.composer@2.1-service
    783 system       18  -2 4.4G 265M 178M S  4.6   9.4  34:23.73 system_server
    1844 u0_a13       20   0 4.5G 205M 174M S  4.0   7.3   0:25.51 com.google.android.gms
    469 cameraserver 20   0  49M  15M  12M S  3.0   0.5   0:09.30 cameraserver
    11779 root         20   0  10M 3.8M 2.9M R  2.6   0.1   0:00.47 top
    1819 u0_a37       20   0 4.2G 134M 106M S  2.6   4.7   0:08.62 com.google.android.googlequicksearchbox:search
  4.2在查找下camera进程的相关rc文件,与top看到的camera进程名字相关的
    find -name "*.rc" | xargs grep camera 
  4.3找到后在cat一下,看下camera进程名字和启动程序在哪如:
    service camerahalserver /vendor/bin/hw/camerahalserver 
    class main
    user cameraserver
    group audio camera input drmrpc sdcard_rw system media graphics
    ioprio rt 4
    capabilities SYS_NICE
    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
    再stop camerahalserver ,要手动启动则运行/vendor/bin/hw/camerahalserver
    想恢复原stop前的情况则start camerahalserver 即可。(stop/start 服务名)

5.注解:
  5.1标准注解:
    @Override 重写的标记;@Deprecated过时的标记;@SuppressWarning 取消特定代码段中的警告
    @SafeVarargs:可变长度参数标注
  5.2元注解:注解其他注解,从而创建新的注解
    @Target 注解所修饰的对象范围
      ElementType.TYPE
                 .FIELD
                 ....
    @Inherited 表示注解可以被继承
    @Documented 表示这个注解应该被javadoc工具记录
    @Retention 用来声明注解的保留政策
      RetentionPolicy.SOURCE 源码级注解,只会保留在.java中,不会保留在.class中
      RetentionPolicy.CLASS 编译时注解,会保留到.class中,不会保留在jvm中
      RetentionPolicy.RUNTIME 运行时注解,jvm中会保留该注解信息,通过反射获取该注解信息
    @Repeatable 允许一个注解在同一声明类型上多次使用
 6.设计模式
   6.1创建型设计模式(与对象创建有关)
    6.1.1单列模式:双重检查模式DCL(有时会失效是因为java内存模型一些原因会失败,
         高并发环境也会失效,虽然发生概率很小,由于编译器优化了程序指令, 允许
         对象在构造函数未调用完前, 将共享变量的引用指向部分构造的对象, 虽然对
         象未完全实例化, 但已经不为null了),推荐使用静态内部类单列模式如下
       (类初始化的过程是非并行的,这些都有JLS((Java Language Specification)保证):
        public class Singleton{
          
           private Singleton(){
                
           }
           public static Singleton get_instance(){
               return SingletonHolder.m_instance;
           }
           private static class SingletonHolder{
              private static final Singleton m_instance = new Singleton();
           }

        }
    6.1.2 工厂模式(Factory:工厂类,IProduct:抽象产品类,Product:具体产品类):
        public abstract class Computer{
           public abstract void start();
        } 
        public class LenovoComputer extends Computer{
           @Override
           public void start(){
             Log.i("22m","联想电脑启动");
           }
        }
        public class AsusComputer extends Computer{
           @Override
           public void start(){
             Log.i("22m","华硕电脑启动");
           }
        }
        public class ComputerFactory {
           public static Computer create_computer(Class clz){
             Computer m_computer =nll;
             String computer_class_name= clz.getName()
             try{
               computer = Class.forName(computer_class_name).newInstance();
             }catch(Exception e){
               e.printStackTrace();
             }
             return computer;
           }
        }      
    6.1.3 创建者模式(builder)
   6.2结构型设计模式
   6.3行为型设计模式

7.jni study(java native interface c/c++的高效性和安全性)
    7.1函数命名规则为:JNIEXPORT jstring JNICALL Java_类全路径_方法名(如Java_com_study_jnilearn_HelloWorld_sayHello)
    7.2函数固定的参数:JNIEnv* 第一个参数,指向jvm函数表的指针;jclass/jobject第二个参数,调用java中native方法的实例或者Class对象
       如果native方法是实例方法则是jobject,静态方法则是jclass。
    7.3jni获取java构造方法的同一名称“<init>”
    7.4字符串编码(java:utf-16,无论英文还是中文都是2字节;jni:utf-8,是变长编码的unicode,一般ascii字符是1字节,中文是3字节
      c/c++:GB2312,ascii就是一个字节,中文一般是GB2312编码,用2个字节表示一个汉字)
    7.5 javac xx/xxx/xx.java -> 生成class文件 ;  javah -jni 包名.文件名 ->生成头文件(在java目录下)
    
 8.ADB的使用:
    adb logcat 输出所有的日志 

    adb logcat > <文件名> 输出日志到此文件中

    adb logcat -s <tag> 输出符合标签的日志 如:log.i(“tag”,"zzm)

    adb logcat --help 显示帮助信息

    adb logcat <选项> <过滤项>  logcat 的基本使用格式

    adb logcat -c 清楚缓存的日志

    adb -s <device id> logcat 指定哪个手机的log输出

    adb logcat | grep <过滤的信息> 显示包含过滤信息的日志

    adb logcat | grep -i <过滤信息> 忽略大小写 显示包含过滤信息的日志

    adb logcat | grep "^..<过滤信息> | ^..<过滤信息>"    显示包含多个过滤信息的日志

    adb logcat | grep -v <过滤信息>  不显示包含过滤信息的日志

    adb logcat -v <格式信息(thread,time..)>  控制日志的格式输出

    adb shell--->logcat > /sdcard/log.txt 输出日志到手机根目录下的log.txt中 

    adb devices 显示全部运行的Android设备

    adb start-server 启动

    adb kill-server 停止

    adb version 查看版本

    adb shell 进入shell模式,相当于进入Android设备的linux环境

    adb root 获取root权限(手机先得root)

    adb remount 重新mount设备分区,让system分区从只读变成可读可写,首先得获取root权限,然后就可以在system/app下随意修改东西了

    adb install -r(replace) <apk路径> 安装apk

    adb uninstall <-k> <包名>  卸载apk,-k是保存apk产生的数据

    adb pull <手机文件(夹)路径> <电脑目录> 把手机的文件(夹)copy到电脑 ,电脑根目录如:D:\.

    adb push  <电脑文件(夹)路径>  <手机路径> 把电脑的文件(夹)copy到手机

    adb help 查看帮助信息(包括版本等)

    adb shell (/system/bin/) screencap -p 路径/xx.jpg(xx.png)  截屏保存在手机上

    adb reboot 重启手机

    adb reboot -p 关机

    adb shell dumpsys (<dbinfo>数据库存储信息包括sql语句,<meminfo>内存信息) <packagename> 查看某应用信息

    adb shell pm list packages 列出手机安装的所有的apk包名

    adb shell pm list packages -s 列出手机安装的系统应用的apk包名

    adb shell pm list packages -3 列出手机安装的第三方应用apk的包名

    adb shell pm list packages "| grep 名字" 列出符合名字的过滤过的手机应用的apk包名

    adb shell screenrecord --help 显示命令的参数详解,这只是个例子

    adb shell am force-stop <包名> 强制关闭某个应用

    adb shell am start -n <包名/应用的入口activity> 打开某个应用

    adb shell wm size 获取手机的屏幕分辨率

    adb shell wm density 获取手机屏幕的像素密度

    adb shell screenrecord (<--time-limit xx秒>视频录制的时间限制,也可以ctrl+c 停止录制,<--size a x b >录制视频分辨率设置为a*b,<--rotate >录制的视频旋转90度,<--bit-rate>录制视频的帧率设置) <录制视频的生成路径/名字.mp4>                                                                                            不支持声音录制

    adb shell getprop  查看手机设备信息

    adb shell setprop  设置手机可写的设备信息

    pm path <包名>  查看apk的安装路径

 9.git基本使用 :   
     
      a.结合Gerrit和Jenkins 使用的流程: 1.提交到gerrit 的git库中---->2.通过Jenkins 自行进行自动测试和代码分析(如果过了)——>3.人工review审核(过了)---->4.提交到项目库中完成同步'''''
  
      c.https 访问资源 :对于初学者比较方便,可用性高,密码账户也可以不用每次都输入,主要用于开源项目比较好 可以任何人拉取代码(具体配置还没弄过)'''''
  
      d.ssh 方式访问资源:clone 前先配置key ,主要用于公司内部项目,需要是项目的拥有者才能拉取和推代码'''''
  
      e.git 拉取项目出现的问题以及解决办法 : 1.Missing change_id --->gitdir=$(git rev-parse --git-dir); scp -p -P 29418 自己的地址(如qiao.yuan@10.120.40.207):hooks/commit-msg ${gitdir}/hooks/--->重新提交,来生成一个Change-id:
  
      git commit --amend  2.signing failed: agent refused operation---> eval "$(ssh-agent -s)" ssh-add 添加ssh配置信息 3.其他部分的问题 参考 [http://wiki.cktcd.net/wiki/SCM_FAQ SCM FAQ]'''''
    b.常用命令(在项目文件夹下运行git bash-linux 命令)'''''
  
     git config --global user.name "你的用户名" 设置用户名(提交的时候要验证) 
 
     git config --global user.email "你的email"  设置你的邮箱(提交需要验证) 
 
     git init 初始化本地仓库(在目前目录下) 
 
     git add <文件名> 添加文件 
 
     git commit <文件名> -m "提交日志"  提交某文件 
 
     ls -al 显示此文件夹下的所有文件(linux) 
 
     pwd显示当前目录(linux) 
 
     git status 查看当前的仓库状态(是否有新的文件未add等信息) 
 
     git rm <文件名> 删除某文件 
 
     git reset --hard HEAD~N  回退到第n次提交的状态下 
 
     git log --oneline --decorate 查看所有分支所指的对象,和当前所在分支 
 
     git branch <分支名>  创建新的分支 
 
     git checkout <分支名> 切换分支 
 
     ssh-keygen -t rsa 生成ssh key(-t:类型,默认是rsa,还有dsa ; -f:生成的key的名字 ;-C :注释,key的最后内容一般为email) 但是最后生成的key 必须是默认的id_rsa名字在.shh文件夹下,才能正常使用 
 
     git branch 查看当前分支 
 
     git remote -v  显示clone的具体信息,地址等 
 
     git config --global user.name(user.email) "xxx" 修改 ~/.gitconfig 配置文件 (配置文件的修改会覆盖上层的相同配置) 
 
     git config --system user.name(user.email) "xxx" 修改 /etc/gitconfig 配置文件(配置文件的修改会覆盖上层的相同配置) 
 
     git config user.name(user.email) "xxx" 修改项目.git/config 配置文件(配置文件的修改会覆盖上层的相同配置) 
 
     git config --global -l 查看 ~/.gitconfig 配置文件 
 
     git config --system -l 查看/etc/gitconfig 配置文件 
 
     git config --local -l 查看 项目.git/config配置文件 
 
     git config -e --global  查看 ~/.gitconfig 配置文件,并且处于编辑状态 
 
     git config -e --system  查看/etc/gitconfig 配置文件,并且处于编辑状态 
 
     git config -e  --local  查看 项目.git/config配置文件,并且处于编辑状态 
 
     git log (show) 可以查看提交记录 
 
     git pull --rebase 同步服务器最新代码 
 
     git branch -vv  查看本地分支和远程分支的情况 
 
     git remote -v 查看远程库的信息 
 
     git checkout -b <分支名>创建分支并进入分支

     git pull 从服务器下载数据库,合并自己的数据库

     git fetch 从服务器下载数据库放到新的分支,不合并到自己的数据库

     git merge <分支名> 合并分支

     git rebase <分支名> 与 merge 不同 他是线性 的合并

     cat .git/HEAD (git symbolic-ref HEAD) 查看HEAD的指向 ,一般 HEAD-->分支-->记录 或者 HEAD-->记录

     ^ ^^ ~  ~<num> 分别是上一步 ,上两步 ,上一步 ,上两步的提交记录

     git branch -f <分支名>  <分支名或者记录的哈希值> 移动分支如果没有分支就创建分支然后移动到目标地方

     git branch -a  查看所有的分支包括远程

     git reset 撤销变更 (不适合远程)

     git revert 撤销变更,多一个记录

     git cherry-pick <分支名,提交记录哈希> ... 复制提交记录到HEAD处

     git rebase -i <分支名> <分支名> 将第二个分支链式记录复制到第一分支处 

     git tag <tagname> <分支名> 在分支名处建立tag

     git describe <分支名> 显示离分支名最近的分支的tag和相距几个提交记录以及记录的哈希值

     git fetch 只更新本地对应远程的分支,不更新本地的分支
   
     git pull (fetch + merge)
   
     git push 不带参数的push 相关的配置和push.default文件相关
   
     git pull --rebase (fetch + rebase)

     git checkout -b <分支名> o/master 创建分支可以追踪远程分支的

     git branch -u  o/master  同上

     git push origin <分支名> 将分支下的所有记录push到远程 HEAD指向的是最上层的提交记录
     git练习网址:https://learngitbranching.js.org/

 10.Ubuntu 基本使用:

     a.File transfer protocol


     c.如果安装的ubuntu 没有界面可以: apt-get install x-window-system-core-->如果有错误可以(根据提示来处理)更新sudo apt update-->apt-get install gnome-core-->然后reboot''''' 

     d.修改时间和时区:sudo tzselect-->选择Asia china beijing -->复制文件 sudo cp /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime -->sudo apt-get install ntpdate-->sudo nptdate time.windows.com-->'''''

      sudo date -s mm/dd/yy 修改月日年-->

      sudo date -s hh:mm:ss 修改时分秒-->

      最后reboot


     e.添加新的磁盘(挂载磁盘才能被系统所识别和使用):先格式化成ext3格式 sudo mkfs -t ext3 /dev/xxx -->创建挂载目录通常可建在~/下 -->手动挂载 sudo mount /dev/xxx ~/xxx-->修改/etc/fstab文件可以开机自动挂载'''''

      (如果只读,可以给权限,再修改)文件末尾加上/dev/xxx /home/电脑用户名/xxx ext3 defaults 0 0(vim /etc/fstab)


     f.有关权限常识 :
 
       -(类型:文件夹d,文件名-) ---(user的权限) ---(group的权限) ---(other的权限)
      如 :d rwx rw- rwx

      sudo chmod <u(user)/g(group)/o(other)/a(all)> <+(and)/-(reduce)/=(canle before and give only one)> <r(can read)/w(can write)/x(can 执行)>'''''


      g.安装adb和fastboot : sudo apt-get install android-tool-adb android-tools-fastboot'''''


      h.安装和卸载jdk(从官网源处安装):sudo add-apt-repositry ppa:webupd8team/java-->sudo apt-get update---->sudo apt-get install oracle-java8-installer(安装) ;sudo apt-get remove oracle-java8-installer(卸载)''''' 


      j.创建虚拟机上ubuntu映射网盘到windows上:'''''
        安装samba sudo apt-get install samba---->修改配置苏sudo vim /etc/samba/smb.conf 文件末尾加上 ([xxxx] path=xxxx  browseable=yes  guest ok=no writable=yes)---->重启samba sudo /etc/init.d/smbd restart'''''

        >设置权限sudo chmod -R 777 xxxx ---->(接下来的可能需要操作的)添加samba用户 sudo touch /etc/smaba/smbpasswd sudo smbpasswd -a <用户名> 输入密码就添加好了(此用户一定首先被系统添加了的)'''''

        >在windows下创建映射网盘 输入ubuntu ip 加上xxx 然后输入添加samba的用户名和密码 即可创建好了网盘映射'''''


      k.虚拟机三种网络设置:桥接bridge(默认) NAT  HOST-ONLY(至于本机可以相连)


      l.vim是vi的升级版本,gedit是图形界面的编辑器


      m.ubuntu 环境配置有两种: 修改~/.bashrc(作用域某个用户)  修改/etc/profile(所有用户)


      n.wmware虚拟机配置网络:
       bridged(桥接模式):相当于创建一台独立的电脑,说的通俗的就是现在虚拟机就相当于和你主机同在一个网络的另一台真实的电脑。
                         所以要想使用桥接使虚拟机上网,前提必须你的主机处在局域网中,也就是你的主机上网得有路由器,这时才能
                         用桥接使虚拟机上网。至于虚拟机的IP设置方式和你主机一样,用不用设置IP要看你的路由器是否开启了DHCP和DNS,
                         主机不用虚拟机也不用,主机要设置那么虚拟机也要设置。对于那些使用拨号上网方式并且没用路由器的就不要用桥接。
                         你可以让它跟主机通信,但是网络需要手工配置。在这种模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独
                         立的主机,它可以访问网内任何一台机器。需要手工为系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,
                         这样虚拟系统才能和宿主机器进行通信。同时,由于这个虚拟系统是局域网中的一个独立的主机系统,那么就可以手工
                         配置它的TCP/IP配置信息,以实现通过局域网的网关或路由器访问互联网。简而言之,使用桥接模式的虚拟系统和宿主
                         机器的关系,就像连接在同一个Hub上的两台电脑。想让它们相互通讯,你就需要为虚拟系统配置IP地址和子网掩码,否
                         则就无法通信。如果你想利用VMWare在局域网内新建一个虚拟服务器,为局域网用户提供网络服务,就应该选择桥接模式。
       host-only(主机模式):是与主机隔离的,但是虚拟机之间是可以相互通信,相当于这两台机器通过双绞线互连。这时虚拟机只能和主机通讯,
                           默认它是不能上网的。(当然不是绝对的,要想上网不过要进行另外的设置),在某些特殊的网络调试环境中,要求
                           将真实环境和虚拟环境隔离开,这时你就可采用host-only模式。在host-only模式中,所有的虚拟系统是可以相互通
                           信的,但虚拟系统和真实的网络是被隔离开的。在此模式下,虚拟系统的TCP/IP配置信息(如IP地址、网关地址、DNS
                           服务器等),都是由VMnet1(host-only)虚拟网络的DHCP服务器来动态分配的。如果你想利用VMWare创建一个与网内其
                           他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可以选择host-only模式。
       NAT(网络地址转换模式):虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网,虚拟系统也就无法和本局域网中的其
                             他真实主机进行通讯。说的通俗的就是在你的主机和虚拟机之间加了一个路由器,虚拟机通过这个路由器上网。NAT
                             方式就不用考虑那么多,只要你主机能上网虚拟机就能上网,所以一般没有特殊要求推荐用NAT方式。使用NAT模式可
                             以很方便的实现在虚拟系统里访问互联网。NAT模式下的虚拟系统的TCP/IP配置信息是由VMnet8(NAT)虚拟网络的DHCP
                             服务器提供的,无法进行手工修改,因此虚拟系统也就无法和本局域网中的其他真实主机进行通讯。采用NAT模式最大
                             的优势是虚拟系统接入互联网非常简单,你不需要进行任何其他的配置,只需要宿主机 器能访问互联网即可。如果你
                             想无需做什么操作,安装系统后就可上网,那么可以选择NAT模式。
 

  b.常用命令和常识

   sudo apt-get install <软件名字> 从默认软件源处下载安装软件

   ~/ 指向 Home根目录

   cat  <文件名> 查看某文件

   /etc 系统级别配置目录(配置的作用域对于所有的用户)

   ctrl + h  显示/隐藏文件夹和文件,前缀是.的文件默认是隐藏文件

   mv <文件名> <文件夹名> 将文件移动到文件里面

   mkdir <文件夹名>  创建文件夹

   vi <文件名> 编辑文件(若果不存在就创建),(按i 进入编辑状态,esc退出编辑状态,:w-保存不退出vi; :w!-强制保存不退出vi; :wq 或者x-保存并且退出vi; :wq! - 强制保存并退出)

   lsusb 查看所有连接好了的usb设备

   uname -o  操作系统的信息

   uname -p 处理器信息

   uname -v 内核版本

   lsb_release -a 系统详细信息

   date 日期信息

   cal 日历信息

   sudo -i 进入管理员

   xrandr 屏幕分辨率信息

   xrandr -s w x h 设置屏幕分辨率(可在虚拟机上设置ubuntu系统的窗口大小)

   cd .. 返回上一目录

   timedatectl 查看系统时间相关信息

   sudo apt-get remove <软件名> 卸载软件

   sudo fdisk -l 查看当前系统分区情况

   df -h 查看磁盘使用情况和挂载情况

   sudo chmod -R 777 <文件名>  给文件名所有权限

   sudo chmod -R 777 * 给当前目录文件,文件夹给予所有权限

   ./ (source)<文件名>  执行脚本文件

   dpkg -l 查看所有安装的软件

   which  <软件名> 查看软件安装位置

   locate <软件名> 看与此软件相关的文件的所有位置

   sudo adduser <用户名>  添加系统用户

   sudo useradd <用户名>  添加三无用户但是可以灵活创建

   sudo  passwd <用户名>  更改用户名的密码

   sudo pdbed -L -v 查看samba 用户详情信息

   cat /etc/passwd  查看ubuntu所有用户

   sudo smbpasswd -a <用户名> 添加samba用户

   sudo smbpasswd -x <用户名> 删除samba 用户

   touch <文件名> 创建新的文件

   sudo apt-get update 更新软件信息数据库

   sudo apt-get upgrade 更新已安装的软件

   source <软件名> 执行后文件内容立马生效

   cat /proc/cpuinfo |grep 'processor' |wc -l 查看cpu个数

   cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c 查看cpu型号

   cat /proc/cpuinfo| grep "cpu cores"| uniq 查看cpu core数量

   grep 'processor' /proc/cpuinfo | sort -u | wc -l  查看cpu 总线程数

   ls -l 显示当前目录的不是隐藏的文件和文件夹, ..代表存在着父目录

   ls -al 显示当前目录的所有文件和文件夹, ..代表存在着父目录
  
   ls 只显示目录名和文件名
  
   ll -t 有时间的排序显示当前目录所有文件和文件夹

转载于:https://my.oschina.net/u/2987490/blog/3036174

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/150155
推荐阅读
相关标签
  

闽ICP备14008679号