Tổng quan PackageManagerService
PackageManagerService (PMS) là dịch vụ hệ thống Android quản lý vòng đời ứng dụng bao gồm cài đặt, gỡ bỏ, cập nhật và kiểm soát quyền truy cập. Dịch vụ này xử lý phân tích APK, tối ưu DEX và quản lý metadata gói ứng dụng.
Khởi động và thiết lập PMS
SystemServer khởi tạo PMS trong giai đoạn bootstrap:
// SystemServer.java
class SystemServer {
void startBootstrapServices() {
Installer fileService = mServiceManager.startService(Installer.class);
// Tạo PMS
mPms = PackageManagerService.create(
mSystemContext,
fileService,
factoryTestMode
);
// Đăng ký service
ServiceManager.addService("package", mPms);
}
}
// PackageManagerService.java
class PackageManagerService {
static PackageManagerService create(Context ctx, Installer inst, boolean isTest) {
PackageManagerService instance = new PackageManagerService(ctx, inst, isTest);
// Quét thư mục hệ thống
scanSystemDirectory(new File(Environment.getRootDirectory(), "app"));
scanSystemDirectory(new File(Environment.getVendorDirectory(), "priv-app"));
// Ghi cấu hình
mSettings.saveConfiguration();
return instance;
}
}
Phân tích cấu trúc APK
PackageParser xử lý file APK để trích xuất metadata:
class PackageParser {
AppPackage parsePackage(File apkFile) throws ParseException {
AssetManager assets = createAssetManager(apkFile);
XmlResourceParser manifestParser = assets.openXml("AndroidManifest.xml");
AppPackage appPackage = new AppPackage();
// Đọc thông tin cơ bản
appPackage.id = readAttribute(manifestParser, "package");
appPackage.versionCode = readAttribute(manifestParser, "versionCode");
// Phân tích thành phần
while (manifestParser.next() != END_DOCUMENT) {
if (manifestParser.getName().equals("activity")) {
appPackage.activities.add(parseActivity(manifestParser));
}
// Xử lý service, receiver, provider
}
return appPackage;
}
ActivityInfo parseActivity(XmlResourceParser parser) {
ActivityInfo activity = new ActivityInfo();
activity.className = parser.getAttributeValue(null, "name");
activity.exported = Boolean.parseBoolean(
parser.getAttributeValue(null, "exported")
);
return activity;
}
}
Quy trình cài đặt ứng dụng
- PackageInstaller tạo phiên cài đặt
- Ghi dữ liệu APK vào thư mục tạm
- PMS xác minh chữ ký và quyền
- Quét và lưu trữ metadata
- Tối ưu hóa mã DEX
class PackageInstaller {
void install(File apkFile) {
SessionParams config = new SessionParams(MODE_FULL_INSTALL);
int sessionId = createSession(config);
Session session = openSession(sessionId);
try (OutputStream out = session.openWrite("base.apk")) {
Files.copy(apkFile.toPath(), out);
}
session.commit();
}
}
class PackageManagerService {
void processInstall(Session session) {
// Xác minh chữ ký
verifySignatures(session.getAppPackage());
// Quét package
AppPackage parsed = mPackageParser.scanPackage(session.getStageDir());
// Tối ưu DEX
mDexOptimizer.optimize(parsed);
// Cập nhật cơ sở dữ liệu
mSettings.addPackage(parsed);
}
}
Quản lý quyền ứng dụng
PMS kiểm tra và cấp quyền runtime:
class PackageManagerService {
int checkPermission(String permission, String appId, int userId) {
AppPermissionState state = mPermissions.get(appId);
return state.isGranted(permission, userId) ?
PERMISSION_GRANTED : PERMISSION_DENIED;
}
void grantRuntimePermission(String appId, String permission, int userId) {
mPermissions.get(appId).grant(permission, userId);
mSettings.saveRuntimePermissions();
}
}
class AppPermissionState {
private Map<String, Boolean> userPermissions = new HashMap<>();
void grant(String permission, int userId) {
userPermissions.put(permission + userId, true);
}
boolean isGranted(String permission, int userId) {
return userPermissions.getOrDefault(perPermission + userId, false);
}
}
Cơ chế lưu trữ PackageInfo
Thông tin gói được lưu trong packages.xml:
<packages>
<package
name="com.example.app"
path="/data/app/com.example.app"
version="101">
<permissions>
<item name="android.permission.CAMERA" granted="true"/>
</permissions>
</package>
</packages>
Tối ưu hóa DEX
class DexOptimizer {
void optimize(AppPackage appPackage) {
for (String instructionSet : getInstructionSets()) {
for (String dexPath : appPackage.getDexPaths()) {
mInstaller.dex2oat(
dexPath,
instructionSet,
appPackage.getOptimizationFilters()
);
}
}
}
}
Truy vấn thành phần ứng dụng
class ComponentQuery {
List<ResolveInfo> resolveIntent(Intent intent) {
return mComponentResolver.queryIntent(
intent,
intent.resolveType(),
MATCH_ALL_FLAGS
);
}
}
class MainActivity extends Activity {
void launchApp() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://example.com"));
List<ResolveInfo> apps = getPackageManager()
.queryIntentActivities(intent, 0);
// Hiển thị danh sách ứng dụng khả dụng
}
}
Ví dụ cài đặt ứng dụng nền
class BackgroundInstaller {
void silentInstall(File apkFile) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
SessionParams config = new SessionParams(SessionParams.MODE_FULL_INSTALL);
int sessionId = installer.createSession(config);
Session session = installer.openSession(sessionId);
try (OutputStream out = session.openWrite("app.apk")) {
Files.copy(apkFile.toPath(), out);
}
session.commit(createPendingIntent());
}
private PendingIntent createPendingIntent() {
Intent intent = new Intent(this, InstallReceiver.class);
return PendingIntent.getBroadcast(this, 0, intent, FLAG_UPDATE_CURRENT);
}
}
Công cụ gỡ lỗi và tối ưu
Sử dụng adb để kiểm tra trạng thái PMS:
# Liệt kê gói ứng dụng
adb shell pm list packages
# Kiểm tra thông tin gói cụ thể
adb shell dumpsys package com.example.app
# Xem trạng thái tối ưu DEX
adb shell dumpsys dexopt
Kỹ thuật tối ưu hiệu năng:
class PackageManagerHelper {
private LruCache<String, PackageInfo> cache = new LruCache<>(50);
PackageInfo getCachedInfo(String packageName) {
PackageInfo info = cache.get(packageName);
if (info == null) {
info = queryPackageInfo(packageName);
cache.put(packageName, info);
}
return info;
}
void registerUpdateListener() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
context.registerReceiver(new PackageChangeReceiver(), filter);
}
}