Android6.0 PKMS拦截adb安装应用
来源:互联网 发布:装修公司 网络运营 编辑:程序博客网 时间:2024/04/29 06:15
我们再PKMS汇总拦截adb 安装的应用,在分析PKMS的时候我们也知道,在installPackageAsUser有如下代码,代表是adb安装的。
- if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
- installFlags |= PackageManager.INSTALL_FROM_ADB;
- }
所以我们可以在startCopy函数中做手脚
- final boolean startCopy() {
- boolean res;
- try {
- if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
- if (++mRetries > MAX_RETRIES) {//超过4次
- Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
- mHandler.sendEmptyMessage(MCS_GIVE_UP);
- handleServiceError();
- return false;
- } else {
- handleStartCopy();
- res = true;
- }
- } catch (RemoteException e) {
- if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
- mHandler.sendEmptyMessage(MCS_RECONNECT);
- res = false;
- }
- //add
- if (mApkPath == null) {
- handleReturnCode();
- return res;
- }
- adb 安装的
- if ((((InstallParams)this).installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
- mLock = new ReentrantLock();
- mCondition = mLock.newCondition();
- class AlertDialogThread extends Thread {
- public Handler mHandler;
- public void run() {
- Looper.prepare();
- showAlertDialog();
- Looper.loop();
- }
- }
- AlertDialogThread alertDialogThread = new AlertDialogThread();
- alertDialogThread.start();
- mLock.lock();
- try {
- mCondition.await();
- } catch (InterruptedException e) {
- }
- mLock.unlock();
- /*if (!mContinueToInstall) {
- res = false;
- }*/
- }
- handleReturnCode();
- return res;
- }
上面代码就是增加了一个显示的dialog,点击继续才会继续安装,这里我们有一个当点击取消或者5秒没有点击就不继续安装,这里返回值res不能为false。为什么呢?我们来看下调用startCopy的地方,当startCopy返回true才会把mPendingInstalls中的第一项删除,否则就会不断调用startCopy直到超过4次才会删除。所以我们上面不继续安装的话也不能返回一个false。
- else if (mPendingInstalls.size() > 0) {
- HandlerParams params = mPendingInstalls.get(0);
- if (params != null) {
- if (params.startCopy()) {
- // We are done... look for more work or to
- // go idle.
- if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Checking for more work or unbind...");
- // Delete pending install
- if (mPendingInstalls.size() > 0) {
- mPendingInstalls.remove(0);
- }
- if (mPendingInstalls.size() == 0) {
- if (mBound) {
- if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Posting delayed MCS_UNBIND");
- removeMessages(MCS_UNBIND);
- Message ubmsg = obtainMessage(MCS_UNBIND);
- // Unbind after a little delay, to avoid
- // continual thrashing.
- sendMessageDelayed(ubmsg, 10000);
- }
- } else {
- // There are more pending requests in queue.
- // Just post MCS_BOUND message to trigger processing
- // of next pending install.
- if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Posting MCS_BOUND for next work");
- mHandler.sendEmptyMessage(MCS_BOUND);
- }
- }
- }
再看看在HandlerParams 中增加的代码,大部分是显示dialog相关。
- private abstract class HandlerParams {
- private static final int MAX_RETRIES = 4;
- /**
- * Number of times startCopy() has been attempted and had a non-fatal
- * error.
- */
- private int mRetries = 0;
- /** User handle for the user requesting the information or installation. */
- private final UserHandle mUser;
- HandlerParams(UserHandle user) {
- mUser = user;
- mApkPath = null;//add
- }
- UserHandle getUser() {
- return mUser;
- }
- private Builder mAlertDialogBuilder;
- private AlertDialog mAlertDialog;
- private CountDownTimer mCountDownTimer;
- protected String mApkPath;
- protected boolean mContinueToInstall = true;//注意这个很重要
- private void cancelAlertDialog(Dialog dialog) {
- mLock.lock();
- if (mHandler.mPendingInstalls.size() != 0) {
- InstallParams params = (InstallParams)mHandler.mPendingInstalls.get(0);
- try {
- if (params.observer != null) {
- params.observer.onPackageInstalled("", INSTALL_FAILED_USER_CANCELLED, null, null);
- }
- } catch (RemoteException re) {
- }
- }
- mHandler.mPendingInstalls.clear();
- mHandler.disconnectService();
- mContinueToInstall = false;//没有点击继续安装
- mCondition.signal();
- mLock.unlock();
- dialog.dismiss();
- }
- private Drawable getApkIcon(Context context, String apkPath) {
- PackageManager pm = context.getPackageManager();
- PackageInfo info = pm.getPackageArchiveInfo(apkPath,
- PackageManager.GET_ACTIVITIES);
- if (info != null) {
- ApplicationInfo appInfo = info.applicationInfo;
- appInfo.sourceDir = apkPath;
- appInfo.publicSourceDir = apkPath;
- try {
- return appInfo.loadIcon(pm);
- } catch (OutOfMemoryError e) {
- Log.e("getApkIcon", e.toString());
- }
- }
- return null;
- }
- private CharSequence getAppLabel(Context context, String apkPath) {
- PackageManager pm = context.getPackageManager();
- PackageInfo info = pm.getPackageArchiveInfo(apkPath,
- PackageManager.GET_ACTIVITIES);
- if (info != null) {
- ApplicationInfo appInfo = info.applicationInfo;
- appInfo.sourceDir = apkPath;
- appInfo.publicSourceDir = apkPath;
- return appInfo.loadLabel(pm);
- }
- return null;
- }
- private void showAlertDialog() {
- final Context settingsContext = new ContextThemeWrapper(mContext,
- com.android.internal.R.style.Theme_DeviceDefault_Settings);
- mAlertDialogBuilder = new AlertDialog.Builder(settingsContext);
- mAlertDialogBuilder.setTitle(getAppLabel(mContext, mApkPath));
- mAlertDialogBuilder.setMessage(R.string.install_hint);
- mAlertDialogBuilder.setIcon(getApkIcon(mContext, mApkPath));
- mAlertDialogBuilder.setNegativeButton(R.string.adb_install_cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mCountDownTimer.cancel();
- cancelAlertDialog(mAlertDialog);
- }
- });
- mAlertDialogBuilder.setPositiveButton(R.string.adb_install_continue_to_install,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mCountDownTimer.cancel();
- mLock.lock();
- mContinueToInstall = true;//点击继续安装
- mCondition.signal();
- mLock.unlock();
- mAlertDialog.dismiss();
- }
- });
- mAlertDialog = mAlertDialogBuilder.create();
- Window alertDialogWindow = mAlertDialog.getWindow();
- alertDialogWindow.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);// TYPE_SYSTEM_DIALOG
- mAlertDialog.setCanceledOnTouchOutside(false);
- mAlertDialog.show();
- alertDialogWindow.setGravity(Gravity.BOTTOM);
- final Button negativeButton = mAlertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
- int intervalMs = 1000;
- int timeLeftMs = 5000;
- final String cancel = mContext.getString(R.string.adb_install_cancel);
- mCountDownTimer = new CountDownTimer(timeLeftMs, intervalMs) {
- public void onTick(long millisUntilFinished) {
- negativeButton.setText(cancel + "(" + millisUntilFinished / 1000 + ")");
- }
- public void onFinish() {
- cancelAlertDialog(mAlertDialog);
- }
- };
- mCountDownTimer.start();
- }
其中有一个mApkPath我们接下来看在哪赋值。
就是handleStartCopy函数最后在copyApk函数(就是在copy apk到data/app目录下新建的临时目录)之后,mApkPath就是其目录下的base.apk
- ret = args.copyApk(mContainerService, true);
- mApkPath = args.getCodePath() + "/base.apk";
我们再看下有了这个apkPath就可以调用PackageManager的getPackageArchiveInfo来获取PackageInfo,然后解析出ICon和Label等。
- PackageInfo info = pm.getPackageArchiveInfo(apkPath,
- PackageManager.GET_ACTIVITIES);
我们来看看这个函数,也是调用PackageParser来解析apk。
- public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
- final PackageParser parser = new PackageParser();
- final File apkFile = new File(archiveFilePath);
- try {
- PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
- if ((flags & GET_SIGNATURES) != 0) {
- parser.collectCertificates(pkg, 0);
- parser.collectManifestDigest(pkg);
- }
- PackageUserState state = new PackageUserState();
- return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
- } catch (PackageParserException e) {
- return null;
- }
- }
我们继续分析handleReturnCode函数,当mContinueToInstall为true就调用processPendingInstall函数继续装载应用,当为false,就调用doPreInstall。联系到之前mContinueToInstall默认为true,因为不是adb安装的话mContinueToInstall就应该默认为true,要不然不能继续装载应用了。
- @Override
- void handleReturnCode() {
- // If mArgs is null, then MCS couldn't be reached. When it
- // reconnects, it will try again to install. At that point, this
- // will succeed.
- if (mArgs != null) {
- if (mContinueToInstall) {
- processPendingInstall(mArgs, mRet);
- } else {
- mArgs.doPreInstall(PackageManager.INSTALL_FAILED_MISSING_FEATURE);
- }
- }
- }
我们再来看doPreInstall函数,当状态不是success,就删除一些临时文件。
- int doPreInstall(int status) {
- if (status != PackageManager.INSTALL_SUCCEEDED) {
- cleanUp();
- }
- return status;
- }
- Android6.0 PKMS拦截adb安装应用
- Android PKMS拦截adb安装应用
- Android6.0 PKMS扫描目录和调用接口安装应用的区别
- Android6.0 PKMS扫描目录和调用接口安装应用的区别
- Android PKMS深入分析安装应用
- Android6.0 PKMS的mSettings,mPackages变量分析
- Android6.0 AMS启动Activity(六) AMS与PKMS关系(通过Intent获取ActivityInfo)
- Android6.0 AMS启动Activity(六) AMS与PKMS关系(通过Intent获取ActivityInfo)
- Android Fk-PKMS(2) PackageManagerService之应用的安装与卸载
- Android6.0 应用调试
- [RK3288][Android6.0] 调试笔记 --- 通过adb安装APK时间很长问题
- android6.0 Launcher2应用解析
- Android6.0 PackageManagerService卸载应用
- Android6.0应用权限分类
- Android6.0 PackageManagerService 安装lib
- Android6.0 PackageManagerService(PMS)-安装
- adb应用安装失败分析
- Android6.0 在framwoard 层系统拦截HOME键
- iPhone6无法开机
- 7. Reverse Integer
- sysbench压力测试工具使用方法
- centos7+maven安装
- ios逆向工程-静态分析
- Android6.0 PKMS拦截adb安装应用
- Android Service介绍
- 第十一周项目1-验证算法(1)层次遍历算法的验证
- 二进制小技巧
- 260. Single Number III (找到数组中仅出现一次的两个数)
- swift 关于内外部标签的问题
- mysql5.6解决binlog为row格式时增长量过大问题
- 【免费下载】Android Annotations 视频教程
- getCurrentSession()和openSession()的区别