天天看點

Android源碼解析--DeviceStorageManagerService(DeviceStorageMonitorService)服務詳解

DiskStatsService和DeviceStorageMonitorService兩個服務都和系統内部存儲管理、監控有關。

這一篇繼續學習DeviceStorageMonitorService(以下簡稱DSMS)。

DeviceStorageMonitorService和DeviceStorageManagerService是一個東西,隻是在5.0以後,名字改為了DeviceStorageMonitorService。

DeviceStorageMonitorService服務的添加

在SystemServer程序中的添加此服務的代碼如下:

// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
...

mSystemServiceManager.startService(DeviceStorageMonitorService.class);
           

通過SystemServiceManager的startService方法啟動了DSMS,看一下這個startService方法做了什麼:

public SystemService startService(String className) {
    final Class<SystemService> serviceClass;
    try {
        serviceClass = (Class<SystemService>)Class.forName(className);
    }
...
    return startService(serviceClass);
}

public <T extends SystemService> T startService(Class<T> serviceClass) {
    ...
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance
	...
        // 注冊到ServiceManager中
        mServices.add(service);

        
        try {
            service.onStart();//啟動服務
        } 
...
}
           

其實就是用過反射擷取執行個體,然後将Service注冊添加到ServiceManager中, 最後調用了DSMS的onStart方法,那接下來就看看DSMS的構造方法 以及 onStart方法。

DeviceStorageMonitorService的構造方法

我們看看DSMS的構造方法裡都做了些什麼:

public DeviceStorageMonitorService(Context context) {
    super(context);
    mLastReportedFreeMemTime = 0;
    mResolver = context.getContentResolver();
    mIsBootImageOnDisk = isBootImageOnDisk();
    //create StatFs object
    mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath());//擷取data分區的資訊
	//擷取system分區的資訊
    mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath());
	//擷取cache分區的資訊
    mCacheFileStats = new StatFs(CACHE_PATH.getAbsolutePath());
    //擷取data分區的總大小
    mTotalMemory = (long)mDataFileStats.getBlockCount() *
                    mDataFileStats.getBlockSize();

	//建立intent, 分别通知存儲空間不足、存儲空間回複正常、
	//存儲空間已滿、存儲空間不滿等狀态	
    mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
    mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
    mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
    mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
    mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
}
           

可以看到,構造方法就是初始化一些資料,拿到内部儲存設備的一些資訊。

onStart方法啟動服務

代碼如下:

public void onStart() {
    // 緩存設定的門檻值
    final StorageManager sm = StorageManager.from(getContext());
    mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH);
    mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH);

    mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4;
    mMemCacheTrimToThreshold = mMemLowThreshold
            + ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2);
    mFreeMemAfterLastCacheClear = mTotalMemory;

	//檢查記憶體
    checkMemory(true);
    ...
}
           

也是對一部分值的初始化,然後主要調用了checkMemory方法檢查記憶體:

void checkMemory(boolean checkCache) {

    if(mClearingCache) {
       ...//如果正在清理存儲空間,則不作處理
    } else {
        restatDataDir();//重新計算三個分區的剩餘空間
      
        if (mFreeMem < mMemLowThreshold) {
			...
			 if(checkCache) {
           		 ...//如果剩餘空間低于mMemLowThreshold,那就先清理一次空間
            	 clearCache(); // 代碼 1111111

			else {
				//如果剩餘空間任不足,則發送廣播,并在狀态欄設定警告
				sendNotification();
                mLowMemFlag = true;
           ...
        } else {
            if (mLowMemFlag) {
                //存儲空間還夠用,則取消警告
                cancelNotification();
                mLowMemFlag = false;
            }
        }

        if (mFreeMem < mMemFullThreshold) {
            if (!mMemFullFlag) {
			//如果空間已滿,則發送存儲已滿的廣播
                sendFullNotification();

            }
        } 
//DEFAULT_CHECK_INTERVAL為一分鐘,每分鐘觸發一次檢查。
    postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
}
           

在上述 代碼11111中,我們看到,當存儲不足時,就會調用清理緩存clearCache方法。

clearCache方法

當空間不足,需要清理時, DSMS會調用clearCache, 這個方法内部會和PackageManagerService互動

private void clearCache() {
    if (mClearCacheObserver == null) {
        //建立一個Observe
        mClearCacheObserver = new CachePackageDataObserver();
    }
    mClearingCache = true;
    try {
	//調用PackageManagerService的清理存儲空間方法freeStorageAndNotify
        IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
                freeStorageAndNotify(null, mMemCacheTrimToThreshold, mClearCacheObserver);
    } catch (RemoteException e) {
	...
    }
}
           

packageManagerService添加在ServiceManager中時,名字就是“package”, 通過PackageManagerService的freeStorageAndNotify方法清理存儲, 這個會在後面分析PackageManagerService時繼續分析。

總結

DeviceStorageMonitorService 也比較簡單,沒有太多功能,本身沒有重載dump函數, 而DiskStatsService僅僅隻是重載了dump函數,不知道Google為什麼沒有将他們整合為一個Service。

參考《深入了解Android》