Android14 修改 Frameworks/base 实现当两个第三方 apk 使用了相同的 authority,导致其中一个无法安装的问题
问题描述
两个第三方 apk,authority name 相同,当已安装了一个 apk 后,另一个 apk 将无法安装,提示 INSTALL_FAILED_CONFLICTING_PROVIDER
log
C:\Users\lzz>adb install D:\Users\llk\Desktop\DeviceUnite_national_release_0.2.10_202603262020_release_202603262020.apk Performing Streamed Install adb: failed to install D:\Users\llk\Desktop\DeviceUnite_national_release_0.2.10_202603262020_release_202603262020.apk: Failure [INSTALL_FAILED_CONFLICTING_PROVIDER: Scanning Failed.: Can't install because provider name sohostbconfig (in package com.komect.device) is already used by com.cmcc.jarvis] // 反编译查看 AndroidManifest.xml // com.komect.deviceunite <provider android:name="com.komect.deviceunite.DeviceContentProvider" android:exported="true" android:authorities="sohostbconfig" // 相同 android:grantUriPermissions="true"/> // com.cmcc.jarvis <provider android:name="com.cmcc.jarvis.providers.AjLoginPhoneProviders" android:exported="true" android:authorities="sohostbconfig"/> // 相同
具体修改实现(Framework 层 hook)
a.扫描 apk 阶段改掉其中一个 apk 的 authority b.运行时根据包名做 authority 重定向 例子中 jarvis 较复杂牵扯太多,故针对 deviceUnite hook// aframeworks/base/services/core/java/com/android/server/am/ContentProviderHelper.java diff--git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index3f7d8ba..4fda73a100644---a/services/core/java/com/android/server/am/ContentProviderHelper.java+++b/services/core/java/com/android/server/am/ContentProviderHelper.java @@-163,6+163,19@@publicclassContentProviderHelper{true,userId);}+privatestaticfinalStringDU_PACKAGE="com.komect.device";+privatestaticfinalStringOLD_AUTHORITY="sohostbconfig";+privatestaticfinalStringNEW_AUTHORITY="com.komect.device.sohostbconfig";++privateStringremapAuthorityForDeviceUnite(StringcallingPackage,Stringauthority){+if(DU_PACKAGE.equals(callingPackage)&&OLD_AUTHORITY.equals(authority)){+Slog.i(TAG,"remap authority: "+authority+" -> "+NEW_AUTHORITY++" callingPkg="+callingPackage);+returnNEW_AUTHORITY;+}+returnauthority;+}+privateContentProviderHoldergetContentProviderImpl(IApplicationThreadcaller,Stringname,IBindertoken,intcallingUid,StringcallingPackage,StringcallingTag,booleanstable,intuserId){@@-356,6+369,7@@publicclassContentProviderHelper{if(!providerRunning){try{checkTime(startTime,"getContentProviderImpl: before resolveContentProvider");+name=remapAuthorityForDeviceUnite(callingPackage,name);cpi=AppGlobals.getPackageManager().resolveContentProvider(name,ActivityManagerService.STOCK_PM_FLAGS|PackageManager.GET_URI_PERMISSION_PATTERNS,// bframeworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java diff--git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java index fac681a..1a90468100644---a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java+++b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java @@-294,12+294,32@@publicclassComponentResolverextendsComponentResolverLockedimplements}}+privatestaticfinalStringDU_PACKAGE="com.komect.device";+privatestaticfinalStringOLD_AUTHORITY="sohostbconfig";+privatestaticfinalStringNEW_AUTHORITY="com.komect.device.sohostbconfig";++privatestaticStringrewriteAuthorityIfNeeded(StringpackageName,Stringauthority){+if(DU_PACKAGE.equals(packageName)&&OLD_AUTHORITY.equals(authority)){+returnNEW_AUTHORITY;+}+returnauthority;+}+@GuardedBy("mLock")privatevoidaddProvidersLocked(@NonNullComputercomputer,AndroidPackagepkg,booleanchatty){finalintprovidersSize=ArrayUtils.size(pkg.getProviders());StringBuilderr=null;for(inti=0;i<providersSize;i++){ParsedProviderp=pkg.getProviders().get(i);+if(DU_PACKAGE.equals(pkg.getPackageName())){+finalStringoldAuth=p.getAuthority();+finalStringnewAuth=rewriteAuthorityIfNeeded(pkg.getPackageName(),oldAuth);+if(!Objects.equals(oldAuth,newAuth)){+Slog.i(TAG,"rewrite provider authority for "++pkg.getPackageName()+": "+oldAuth+" -> "+newAuth);+ComponentMutateUtils.setAuthority(p,newAuth);+}+}mProviders.addProvider(computer,p);if(p.getAuthority()!=null){String[]names=p.getAuthority().split(";");@@-784,8+804,10@@publicclassComponentResolverextendsComponentResolverLockedimplementsinti;for(i=0;i<providersSize;i++){ParsedProviderp=pkg.getProviders().get(i);-if(p.getAuthority()!=null){-finalString[]names=p.getAuthority().split(";");+Stringauthority=p.getAuthority();+authority=rewriteAuthorityIfNeeded(pkg.getPackageName(),authority);+if(authority!=null){+finalString[]names=authority.split(";");for(intj=0;j<names.length;j++){if(mProvidersByAuthority.containsKey(names[j])){finalParsedProviderother=mProvidersByAuthority.get(names[j]);