Cơ chế quản lý ứng dụng Android với PackageManagerService

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

  1. PackageInstaller tạo phiên cài đặt
  2. Ghi dữ liệu APK vào thư mục tạm
  3. PMS xác minh chữ ký và quyền
  4. Quét và lưu trữ metadata
  5. 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);
    }
}

Thẻ: PackageManagerService APK AndroidManifest DEX PackageInstaller

Đăng vào ngày 4 tháng 7 lúc 09:13