欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android记录一次InstallerPackage apk报错的问题分析

程序员文章站 2022-12-03 07:55:25
前言 测试这两天给我提了一个BUG,说把APK放内部储存里面,然后点击安装的时候,软件安装包程序停止运行!纳尼!原生的啊。我肯定没有动过07-01 17:43:29.120 3257 3295 E AndroidRuntime: FATAL EXCEPTION: InstallThread07-01 17:43:29.120 3257 3295 E AndroidRuntime: Process: com.android.packageinstaller, PID: 325707-01...

前言

 	测试这两天给我提了一个BUG,说把APK放内部储存里面,然后点击安装的时候,软件安装包程序停止运行!纳尼!原生的啊。我肯定没有动过
07-01 17:43:29.120  3257  3295 E AndroidRuntime: FATAL EXCEPTION: InstallThread
07-01 17:43:29.120  3257  3295 E AndroidRuntime: Process: com.android.packageinstaller, PID: 3257
07-01 17:43:29.120  3257  3295 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.AppOpsManager.checkPackage(int, java.lang.String)' on a null object reference
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.Parcel.readException(Parcel.java:1690)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.Parcel.readException(Parcel.java:1637)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.content.pm.IPackageInstaller$Stub$Proxy.createSession(IPackageInstaller.java:249)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.content.pm.PackageInstaller.createSession(PackageInstaller.java:297)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at com.android.packageinstaller.InstallAppProgress.doPackageStage(InstallAppProgress.java:295)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at com.android.packageinstaller.InstallAppProgress.-wrap2(InstallAppProgress.java)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at com.android.packageinstaller.InstallAppProgress$5.run(InstallAppProgress.java:396)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:836)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:103)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:203)
07-01 17:43:29.120  3257  3295 E AndroidRuntime: 	at android.os.HandlerThread.run(HandlerThread.java:61)

z

分析

撸起袖子改BUG,对于程序员而言,这还得了啊,对于用户也是体验极差的
1.可以看到报错地方时在createSession的时候出错了。跟踪代码就是PackageInstallerService.java中的createSession 在具体点就是

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.AppOpsManager.checkPackage(int, java.lang.String)' on a null object reference

这一段。然后我们在

 private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
            throws IOException {
        final int callingUid = Binder.getCallingUid();
        mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");

        if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            throw new SecurityException("User restriction prevents installing");
        }

        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
            params.installFlags |= PackageManager.INSTALL_FROM_ADB;

        } else {
            mAppOps.checkPackage(callingUid, installerPackageName);//这里打LOG看看是哪个空指针了

            params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
            params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;
            params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
        }

        // Only system components can circumvent runtime permissions when installing.
        if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
                && mContext.checkCallingOrSelfPermission(Manifest.permission
                .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
            throw new SecurityException("You need the "
                    + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
                    + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
        }
        .......省略
}

得出结论是 mAppOps 为空 。这个玩意是什么请百度,AppOpsManager;
2.这个初始化的地方是在

    public void systemReady() {
        mAppOps = mContext.getSystemService(AppOpsManager.class);
    }

于是加了LOG发现他确实没有走systemReady()方法,所以怎么说这个为空很正常

3.继续跟踪代码发现,他是在PackageManagerService.java中的systemReady()中调用的

    @Override
    public void systemReady() {
    .......
            // If we upgraded grant all default permissions before kicking off.
        for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId);
        }

        // If we did not grant default permissions, we preload from this the
        // default permission exceptions lazily to ensure we don't hit the
        // disk on a new user creation.
        if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
            mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions();
        }

        // Kick off any messages waiting for system ready
        if (mPostSystemReadyMessages != null) {
            for (Message msg : mPostSystemReadyMessages) {
                msg.sendToTarget();
            }
            mPostSystemReadyMessages = null;
        }

        // Watch for external volumes that come and go over time
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        storage.registerListener(mStorageListener);
	Slog.w("tuliyuan---PKMS"," SYSTEM READY "+(mInstallerService==null));
        mInstallerService.systemReady();
        mPackageDexOptimizer.systemReady();

    ..........

很奇怪这里为什么没走,也没有return函数啊,未必pkms的systemReady没走?于是找到启动PKMS的地方SystemServer.java 搜索systemReady
发现

        try {
	    Log.i("tuliyuan---systemserver", "=== mPackageManagerService systemReady ===");
            mPackageManagerService.systemReady();
        } catch (Throwable e) {
            reportWtf("making Package Manager Service ready", e);
        }

有个try catch…
心里咯噔一下。不会吧不会吧不会吧? pkms哪里报错了只是崩溃捕获了?
adb reboot;adb logcat -b all > log.txt一看 果然。。。

07-01 17:19:15.925  1113  1113 E SystemServer: BOOT FAILURE making Package Manager Service ready
07-01 17:19:15.925  1113  1113 E SystemServer: java.lang.NullPointerException: Attempt to read from field 'java.util.ArrayList android.content.pm.PackageParser$Package.requestedPermissions' on a null object reference
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.pm.DefaultPermissionGrantPolicy.grantRuntimePermissionsLPw(DefaultPermissionGrantPolicy.java:892)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.pm.DefaultPermissionGrantPolicy.grantRuntimePermissionsLPw(DefaultPermissionGrantPolicy.java:882)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.pm.DefaultPermissionGrantPolicy.grantDefaultSystemHandlerPermissions(DefaultPermissionGrantPolicy.java:601)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.pm.DefaultPermissionGrantPolicy.grantDefaultPermissions(DefaultPermissionGrantPolicy.java:220)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:19041)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:1553)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.SystemServer.run(SystemServer.java:420)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.server.SystemServer.main(SystemServer.java:292)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at java.lang.reflect.Method.invoke(Native Method)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1084)
07-01 17:19:15.925  1113  1113 E SystemServer: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:945)

根据LOG得知是 上面过滤默认权限的时候报错了

然后 找到了该死的错误

		
		 PackageParser.Package baidu_location = getSystemPackageLPr("com.baidu.map.location");

		grantRuntimePermissionsLPw(baidu_location, STORAGE_PERMISSIONS, userId);
	     grantRuntimePermissionsLPw(baidu_location, PHONE_PERMISSIONS, userId);
		 
                 

这个baidulocation已经不要了!没有内置,然后找不到包 就错了。。。所以

		 PackageParser.Package baidu_location = getSystemPackageLPr("com.baidu.map.location");
		 if(baidu_location != null){
		 	grantRuntimePermissionsLPw(baidu_location, STORAGE_PERMISSIONS, userId);
	         	grantRuntimePermissionsLPw(baidu_location, PHONE_PERMISSIONS, userId);
		 }

这样就好了

总结

别忘了判断一下空指针异常!!!

本文地址:https://blog.csdn.net/qq_18906227/article/details/107376111