pkms-start-scan and install

这篇博客主要介绍了如何通过ADB命令行工具进行应用安装,并探讨了Android系统的包管理系统(Package Manager Service, PMS)中类之间的关系。" 128072033,15877780,C++编程:日期计算与选举统计,"['c++', '算法', '开发语言']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

start-scan:

@startuml
participant SystemServer as SS
participant PackageManagerService as PKMS
participant ParallelPackageParser as P_PP
participant PackageParser as PP

==PKMS START and scan apk==
SS -> SS: run
SS -> SS: startBootstrapServices
activate SS
SS -> PKMS : mPackageManagerService = PackageManagerService.main
activate PKMS 
PKMS -> PKMS: m = new PackageManagerService
	'construct call'
	activate PKMS #FF55FF
	==scan apk ==
	PKMS -> PKMS:scanDirTracedLI:dir
	loop for file in dir
		PKMS -> P_PP : parallelPackageParser.submit
		P_PP -> PP: PackageParser.Package pr = packageParser.parsePackage\n(scanFile, parseFlags, true) 
		
		alt if packageFile.isDirectory()
			PP -> PP: parsed = parseClusterPackage(packageFile, flags);
		else
			PP -> PP: parsed = parseMonolithicPackage(packageFile, flags);
			activate PP #FF55FF
			PP -> PP:parseBaseApk(apkFile, assets, flags)
			activate PP #FFFF55
				PP -> PP:parseBaseApkCommon
				PP->PP: parse the AndroidManifest.xml
			deactivate PP
			PP -> PP:return pkg;
			deactivate PP
		end
		PP->P_PP: return parsed
		
		P_PP -> P_PP:mQueue.put(pr)
		PKMS -> P_PP :ParallelPackageParser.ParseResult parseResult\n = parallelPackageParser.take
		note left
			get the parse result from the mQueue
		end note
		alt no error case
			PKMS -> PKMS: <b>scanPackageLI</b>(parseResult.pkg,parseResult.scanFile,```)
			activate PKMS #FFFF55
				PKMS -> PKMS:<b>scanPackageInternalLI</b>
				PKMS -> PKMS:check something about apk update
				PKMS -> PKMS:collectCertificatesLI
				note left
					verify the apk and collect certificates, 
					if verify ok: 
						collect certificates to Package.mCertificates
					if fail: 
						throw SignatureException/GeneralSecurityException/...
				end note
				PKMS -> PKMS:<b>scanPackageLI</b>(pkg, policyFlags,...)
				note left
					the another method of scanPackageLI
				end note
				PKMS -> PKMS:scanPackageDirtyLI
				alt if scanFlags & SCAN_CHECK_ONLY) != 0 
					
				else else: update this package info to <b>PKMS</b>
					PKMS -> PKMS:commitPackageSettings
					PKMS -> PKMS:<b>mPackages.put(pkg.applicationInfo.packageName, pkg)</b>
					note left
						Adds a scanned package to the system(mPackages). \nWhen this method is finish
						the package will be available\n for query, resolution, etc...
					end note
				end
				
			deactivate PKMS
		else else: if not system apk && invalid
			PKMS -> PKMS: removeCodePathLI(parseResult.scanFile)
		end
	end
		
	deactivate PKMS
PKMS -> PKMS: updatePermissionsLPw
note left: update if the apk can grant the permissions it request  
PKMS -> PKMS: ServiceManager.addService("package", m)
PKMS -> PKMS: pmn = m.new PackageManagerNative()
PKMS -> PKMS: ServiceManager.addService("package_native", pmn)

deactivate PKMS

SS -> SS: mPackageManager = mSystemContext.getPackageManager();

deactivate SS
@enduml

adb install by adb

@startuml
participant adb_pc
participant adbd
participant shell_adbd_sub_process as shell
participant Pm.java as pm
participant PackageInstaller as pi
participant PackageMangerService as pkms
participant PackageInstallerService as pis
participant PackageInstallerSession as piss

==PKMS adb install apk==
adbd -> adbd: fdevent_install(&(t->transport_fde), t->transport_socket,\n transport_socket_events, t);
note right
register the package callback:transport_socket_events
end note
adb_pc -->adbd:adb install d:/xxx.apk
adbd->adbd: transport_socket_events
activate adbd
	adbd->adbd:read_packet,handle_packet
	adbd->adbd:<font color=red>services.cpp</font> service_to_fd
	note right
	packet is : shell:pm 'install' '/data/local/tmp/app-clientchat.apk'
	end note
	adbd->adbd:strncmp(name, "shell",5)\n ==> ShellService(cmd, transport)
	adbd->adbd:	StartSubprocess(cmd,...)
	note right
		StartSubprocess will fork<font color=red> new process </font>
		cmd is:pm 'install' '/data/local/tmp/app-clientchat.apk' 
	end note
	adbd->shell:fork fork<font color=red>new process</font>
	shell->shell:execle(_PATH_BSHELL, _PATH_BSHELL, "-c", \ncommand_.c_str(), nullptr, cenv.data());
	note right
		replace the subprocess with shell 
	end note
	shell->pm: Pm.java main(arg[0] = install)
	pm->pm:runInstall
	activate pm
		
		note over pm #00FFFF:1.get the interface of IPackageManager/IPackageInstaller/ 
		pm->pm: <b>IPackageManager</b> mPm = IPackageManager.Stub.asInterface\n(ServiceManager.getService("package"));
		pm->pkms:<b>IPackageInstaller</b> mInstaller = mPm.getPackageInstaller();
		pkms->pm: return new PackageInstallerService(context, this);\n it convert to IPackageInstaller
		note left
			get the stub interface of packageManager and PackagerInstaller
		end note
		note over pm #00FFFF:2.set and adopt InstallParams
		pm->pm:init the InstallParams(params) with the args\n userId default is UserHandle.USER_ALL
		pm->pm:ApkLite baseApk = PackageParser.parseApkLite(file, 0);\nPackageLite pkgLite = new PackageLite(null, baseApk,null,...)
		pm->pm:params.sessionParams.setSize(get the file size)
		note over pm #00FFFF:3.create session 
		pm->pis:sessionId = createSession(params, installerPackageName, userId)
		pis->pis:createSessionInternal
		activate pm #FF5555
			pm->pis:int sessionId = <b>mInstaller.createSession</b>
			pis->pkms:enforceCrossUserPermission\n(callingUid, userId, true, true, "createSession")
			pis->pis:check and adopt the install params 
			pis->pis:<font color=red>sessionId</font> = allocateSessionIdLocked();
			pis->pis:session = new <font color=red>PackageInstallerSession</font>
			pis->pis:<font color=red>mSessions.put(sessionId, session)</font>;
			note left 
				map sessionId to PackageInstallerSession
			end note
			pis->pis:mCallbacks.notifySessionCreated\n(session.sessionId, session.userId);
			pis->pis:<b>callback</b>.onSessionCreated(sessionId)
			note left 
				call the callback function
				callback is registered by calling registerCallback
			end note
		/' 
		note over pm #FFFF00 :Pm.java
		note over pi #FFFF00 :PackageInstaller
		note over pkms #FFFF00: PackageMangerService
		note over pis #FFFF00 :PackageInstallerService
		note over piss #FFFF00 :PackageInstallerSession
		'/
		note over pm #00FFFF:4.write apk buffer to dest file 
		deactivate pm
		pm->pm:doWriteSession
		hnote left:Pm.java
		activate pm #FF55FF
			pm->pis:IPackageInstallerSession iPackageInstallerSession = <b>mInstaller.openSession(sessionId)</b>)
			hnote right:PackageInstallerService
			pis->pis:prepare mk dir and call \nmCallback.onSessionProgressChanged\nmCallback.onSessionPrepared
			pis->pm:return <b>IPackageInstallerSession</b> which map to session id
			pm->pm:<b>PackageInstaller.Session session</b>  = \nnew PackageInstaller.Session(<b>iPackageInstallerSession</b>)
			pm->pi:OutputStream out = session.openWrite(splitName, 0, sizeBytes)
			hnote right:PackageInstaller
			pi->piss:open dest file for writing: FileDescriptor targetFd = \nLibcore.os.open(target.getAbsolutePath(),O_CREAT | O_WRONLY, 0644);)
			hnote right:PackageInstallerSession
			piss->pi:return FileDescriptor for writing
			pi->pm:return OutputStream for writing
			ref over pm
			while(readnum = in.read(buffer)) != -1):
				out.write(buffer, 0, readnum);
				float fraction = ((float) readnum / (float) info.sizeBytes)
				<b>session.addProgress(fraction)</b>
			end ref
			pm->pm:session.fsync(out);
			pm->pm:close in out stream and session
		deactivate pm
		note over pm #00FFFF:5.comit session  
		pm->pm:doCommitSession(int sessionId, boolean logSuccess)
		activate pm #FF55FF
			pm->pm:LocalIntentReceiver receiver = new LocalIntentReceiver();
			pm->piss:session.<b>commit</b>(receiver.getIntentSender());
			pm->pm:Intent result = receiver.getResult();
			pm->pm:status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,\nPackageInstaller.STATUS_FAILURE);
			pm->pm:return new Pair<>(result.getStringExtra\n(PackageInstaller.EXTRA_PACKAGE_NAME), status);
		deactivate pm
	deactivate pm
	
	
deactivate adbd
@enduml

pms class relationship

@startuml

Settings "1" o-- "n" PackageSetting
Settings "1" o-- "n" BasePermission
PackageManagerService "1" o-- "1" Settings
PackageManagerService "1" o-- "n" PackageParser.Package


class PackageManagerService{
	Settings mSettings
	ArrayMap<String, PackageParser.Package> mPackages
}

class PackageParser.Package{
	+String packageName
	+String manifestPackageName
	+String[] splitNames
	+String volumeUuid
	+String codePath
	+String baseCodePath
	+String[] splitCodePaths;
	+int baseRevisionCode;
	+ApplicationInfo applicationInfo
	+ArrayList<Permission> permissions 
	+ArrayList<PermissionGroup> permissionGroups
	+ArrayList<Activity> activities
	+ArrayList<Activity> receivers
	+ArrayList<Provider> providers
	+ArrayList<Service> services
	+ArrayList<Instrumentation> instrumentation
	+ArrayList<String> requestedPermissions
	+ArrayList<String> protectedBroadcasts
	+Package parentPackage
	+String mSharedUserId;
	..all certificates of all the signers of a apk..
	+Certificate[][] mCertificates;
	..convert from certificates[][],convert [][] to []..
	+Signature[] mSignatures
	.. the permissions this pkg defined ..
	+ArrayList<Permission> permissions
	+...

}

class Settings{
/** Map from package name to settings */
ArrayMap<String, PackageSetting> mPackages
/** List of packages that installed other packages */
ArraySet<String> mInstallerPackages
ArrayMap<String, BasePermission> mPermissions
ArrayMap<String, BasePermission> mPermissionTrees
ArrayMap<String, SharedUserSetting> mSharedUsers
/**id > FIRST_APPLICATION_UID  10000, 
map from uid index to object like SharedUserSetting/PackageSetting*/
ArrayList<Object> mUserIds

}
note top:Holds information about dynamic settings



class BasePermission {
String name
String sourcePackage
PackageSettingBase packageSetting
int type:NORMAL/BUILTIN/DYNAMIC
int protectionLevel
PackageParser.Permission perm
PermissionInfo pendingInfo
/** UID that owns the definition of this permission */
int uid;
/** Additional GIDs given to apps granted this permission */
- int[] gids;

}
class PackageSetting extends PackageSettingBase{
int appId
PackageParser.Package pkg
SharedUserSetting sharedUser
}

abstract class PackageSettingBase extends SettingBase {
String name
String realName
String parentPackageName
List<String> childPackageNames
File codePath
String[] usesStaticLibraries
int[] usesStaticLibrariesVersions
String primaryCpuAbiString
String secondaryCpuAbiString
PackageSignatures signatures
PackageKeySetData keySetData
int installStatus
/** Package name of the app that installed this package */
String installerPackageName;
IntentFilterVerificationInfo verificationInfo;
}

class SettingBase{
}
@enduml


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值