android_静默安装/adb执行/软件搬家/消息派发





静默安装:
  原理,直接调用Pm.java对象的的方法,不请求PackageInsatller的应用.
  root用户静默安装所调用脚本,LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install -r /sdcard/apk.apk
  判断是否为root用户,获取su进程,执行execCommand("echo root", true, false);
  根据用户是否为root,获取不同的进程,Process mProcess=Runtime.getRuntime().exec(isRoot?su:sh);
  判断是否为系统应用,if((app.flags & ApplicationInfo.FLAG_SYSTEM) > 0){ *** }
  普通应用程序申请不到android.permission.INSTALL_PACKAGES权限; 可以采用共享android:sharedUserId="android.uid.packageinstaller"
    //system用户;Project->clean.//java.lang.SecurityException: Neither user 10042 nor current process has android.permission.INSTALL_PACKAGES.
  setting中点击安全crash,android.security包下,public class KeyStore{ *** }  //KeyStore.getInstance()返回为空. //原因,vendor目录的内容没有读取到;可能厂商信息丢失;


adb命令执行过程:  
  adb的全称为Android Debug Bridge就是调试桥的作用.  adb的工作方式比较特殊采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯.  $adb shell ls #列举目录    
  adb shell后面跟的命令主要来自:源码\system\core\toolbox目录和源码\frameworks\base\cmds目录.
  函数启动点在adb.c中的main函数;内部调用adb_commandline.
  所有cmd处理函数都在:\system\core\adb\commandline.c中;由adb.c中调用int adb_commandline(int argc, char **argv);
  先分析PC端这边:首先建立adb server,(手工建立adb fork-server server调用adb_main(is_daemon, server_port),默认5037端口;自动建立,调用launch_server(server_port)
  ADB command-line client即发送命令界面,主要处理函数:int adb_commandline(int argc, char **argv);
  主要利用如下几个函数:adb_query查询;adb_connect连接;adb_status获取状态;
  adb install xxx.apk处理,commandline.c中调用install_app(*);调用Pm.java类下的runInstall();最终调用的mPackageManager.installPackageWithVerificationAndEncryption(*);
  设置中不安装未知来的应用,普通安装不上;  root用户静默安装能够安装上; 连接电脑,通过adb install a.apk,能够安装成功;


系统应用PackageInstaller应用:
  系统应用,能够申请到INSTALL_PACKAGES权限.该权限只能有系统应用申请到.
  original-package作用:
  <manifest>标签中package属性用于设置应用程序的进程名,即在运行时使用ddms查看到的进程名。
  <original-package>标签用以设置应用源码包名,即Java文件所在的源码程序包层次,android工程中真实的源代码层次结构。
  <manifest>中package属性若与<original-package>的android:name值相同,配置组建时android:name属性值可以使用".ClassName"形式。
  使用<original-package>标签后,在<activity><service><receiver><provider>中的android:name属性需要写完整的报名,".ClassName"形式无效。
  注意:<manifest>标签中package属性只是告诉系统应用的进程名;因此进程名(Manifest中package属性的值)与<original-package>的值可以不一样。
  流程:文件夹中点击apk直接安装,调用的是PackageInstaller应用。
  应用引用了android.content.pm.*包,解析配置文件;该包在/frameworks/base/core/java/android/content/pm下。
  获取应用名称:mPackageManager.getApplicationLabel(mPackageInfo.applicationInfo);
  mPackageParser.collectManifestDigest(**); 内部实现:pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je));
  第三方应用可以利用反射机制调用android.content.pm.PackageParser和android.content.res.AssetManager里的方法实现获取App名称。
hide的方法能够使用反射机制放问。
  com.android.internal.R.bool.config_useMasterVolume这个资源在什么地方呢?根据com.android.internal.R中internal猜想此配置文件应该是个系统配置,果然在out/target/common/R/com/android/internal/R.java中找到了该资源文件,该资源文件是由frameworks/base/core/res/res下编译生成的。  
  android主目录是用repo管理的,各个工程文件是用的git管理的。


截取用户的所有操作:修改android.view包下的View.java
  public boolean dispatchKeyEvent(KeyEvent event){***},按键消息。
  public boolean dispatchTouchEvent(MotionEvent event){***},触摸消息。
  截取按键Home的操作:修改com.android.internal.policy.impl包下的PhoneWindowManager.java
  private void handleLongPressOnHome(){***},长按Home键。
  interceptKeyBeforeDispatching(**){***},拦截所有的按键消息。
  android.hardware.input包下的InputManager.java类负责监听设备并与设备通讯。
  com.android.server.wm包下的InputMonitor.java类,public int interceptKeyBeforeQueueing(**){***},方法内调用mWindowManagerPolicy.interceptKeyBeforeQueueing(**);
  ListView的Apapter中更新进度条:
  mListView.setAdapter(*);//最后会调用requestLayout()方法;内部,如果HeaderView或FooterView不为空,则传入adpter会被包装一层;
  mListView.getAdapter();//未必是setAdapter传入的adpter.   mAdapter是AbsListView.java的变量.
    AbsListView中,内部类 class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver{ *** } //它是DataSetObserver抽象类的实现.
    内部类 class RecycleBin{ *** }  //The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of storage: ActiveViews and ScrapViews.
    RecycleBin内变量 private ArrayList<View>[] mScrapViews;//Unsorted views that can be used by the adapter as a convert view.
    mAbsListView.obtainView();//方法内调用了mAdapter.getView()方法.
  android.database包下,public abstract class DataSetObserver{ *** }
  View类中:protected Object mTag;//The view's tag.
    private SparseArray<Object> mKeyedTags; //Map used to store views' tags.//感觉应该是和ViewGroup中的多个View对应的.
  org.jf.dexlib.Util包下,public class SparseArray<E> { *** }//keyValue键值对;比hashmap效率高.


根视图内部消息派发mView.dispatchTouchEvent():
  应用窗口,PhoneWindow的DecorView;
  private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{ *** }
    public class FrameLayout extends ViewGroup{ *** }                         
  非应用窗口,ViewGroup;public abstract class ViewGroup extends View implements ViewParent,ViewManager{ *** }


获取view的边界信息:
  mView.getLocationInWindow(*); //Computes the coordinates of this view in its window.
  mView.getLocationOnScreen(*); //Computes the coordinates of this view on the screen.
  mView.getGlobalVisibleRect(*); //If some part of this view is not clipped by any of its parents, then return that area in r in global (root) coordinates.
  mView.getLocalVisibleRect(*);
android手机目录及软件搬家:
  /system存放的是rom的信息; /system/app存放rom本身附带的软件即系统软件; /system/data存放/system/app 中核心系统软件的数据文件信息.
  /data存放的是用户的软件信息(非自带rom安装的软件); /data/app存放用户安装的软件;  /data/data存放所有软件(包括/system/app和/data/app和/mnt/asec中装的软件)的一些lib和xml文件等数据信息;
  /data/dalvik-cache存放程序的缓存文件,这里的文件都是可以删除的.


  软件搬家,流行有两种方案,分别是app2ext和data2ext;
  app2ext的原理是,删除data区中的app文件夹,然后在sd卡的ext分区上创建一个app文件,并通过软链接映射到data区;系统显示这个程序是安装在“内置空间”的;
  data2ext则更彻底,它不是用软链接,而是直接用“挂载”功能,Linux下所有的存储设备都必须挂载成一个文件夹才能进行文件操作(如sd卡就挂载在/mnt/sdcard目录下面).
  dalvik-cache是虚拟机预编译缓存,data(不同于/data,这个是/data/data)是存储程序数据的地方,例如游戏的存档记录,软件的配置信息等.
  data2ext由于是把整个data分区都放在sd卡上,因此,我们刷ROM需要WIPE的时候,这个data分区的内容就可能不会被wipe,这可以保存用户的个人资料,但是也可能造成系统莫名其妙的故障.

     https://github.com/search?q=android+install+apk+silent+&type=Repositories&ref=searchresults

发布了8 篇原创文章 · 获赞 7 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/liu31187/article/details/18656495
今日推荐