在负责文件系统模块的过程中,经常会碰到由于系统空间被消耗完而导致的问题,因此要确保为系统功能(如数据库同步)保留一定的空间。在功能机中一般是由文件系统模块预留,那么在Android系统是怎样对设备存储空间进行管理和监控的呢?  如果你在使用Android手机时有过把memory填满或者即将填满的经历,也许你会注意到在这种情况下手机的Notifications栏会有“Storage space running out”的通知。当点开该通知你会发现Setting-->Storage settings –>Device memory 下会有如下提示:Not enough storage space.  这个服务的实现是在android/framework/base/services/java/com/android/server/DeviceStorageMonitorService.java。DeviceStorageMonitorService类实现了一个监控设备上存储空间的服务。如果设备的剩余存储空间小于某一个阀值(默认是存储空间的10%,这个值可以设置)时将会向用户发送剩余空间不足的警告,让用户释放一些空间。  下面就分析一下这个类。首先看一下该服务是如何被添加进来的。在android/frameworks/base/services/java/com/android/server/SystemServer.java中使用ServiceManager.addService()来添加系统服务:     在SystemServer中添加DSMS服务:    
              
         
                               
                      try {              
    Slog.i(TAG, "Device Storage Monitor");               
    ServiceManager.addService(DeviceStorageMonitorService.SERVICE,               
            new DeviceStorageMonitorService(context));               
} catch (Throwable e) {               
    reportWtf("starting DeviceStorageMonitor service", e);               
}         
        
     DSMS的构造函数的代码如下:      DSMS服务的构造函数:    
           1                
     
                               
                          /**              
    * Constructor to run service. initializes the disk space threshold value               
    * and posts an empty message to kickstart the process.               
    */               
    public DeviceStorageMonitorService(Context context) {               
        mLastReportedFreeMemTime = 0;               
        mContext = context;               
        mContentResolver = mContext.getContentResolver();               
        //create StatFs object               
        mDataFileStats = new StatFs(DATA_PATH); //获取Data分区信息;               
        mSystemFileStats = new StatFs(SYSTEM_PATH); //获取System分区信息;               
        mCacheFileStats = new StatFs(CACHE_PATH); //获取Cache分区信息;               
        //initialize total storage on device               
        // 初始化设备总空间信息               
        // mTotalMemory 用于保存Data分区总空间;               
        mTotalMemory = ((long)mDataFileStats.getBlockCount() *               
                        mDataFileStats.getBlockSize())/100L;               
        /*               
        创建3个Intent,分别用于通知存储空间不足(ACTION_DEVICE_STORAGE_LOW)、               
        存储空间回复正常(ACTION_DEVICE_STORAGE_OK)和存储空间满(ACTION_DEVICE_STORAGE_FULL)。               
        由于每个Intent都设置了FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT标志,因此这三个Intent只               
        能由注册了的BroadcastReceiver接收。               
        */               
        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);               
        // cache storage thresholds               
        /*               
        查询Seetings数据库中sys_storage_threshod_percentage的值,默认是10,即当DATA_PATH               
        目录下剩余空间少于其总空间的10%时,认为空间不足(ACTION_DEVICE_STORAGE_LOW)。               
        */               
        mMemLowThreshold = getMemThreshold();               
        /*               
        查询Settings数据库中的sys_storage_full_threshold_bytes的值,默认是1MB,即当DATA_PATH               
        目录下剩余空间小于等于1M时,任务空间已满,剩余的部分是保留给系统使用的。               
        */               
        mMemFullThreshold = getMemFullThreshold();               
        /*               
        开始检查,存储空间;               
        */               
        checkMemory(true);               
    }         
        
  下面再来看一下checkMemory()方法的实现。     checkMemory()方法:    
           1                
2      
         
                               
                      private final void checkMemory(boolean checkCache) {              
    //if the thread that was started to clear cache is still running do nothing till its               
    //finished clearing cache. Ideally this flag could be modified by clearCache               
    // and should be accessed via a lock but even if it does this test will fail now and               
    //hopefully the next time this flag will be set to the correct value.               
    //如果线程正在清除缓存CACHE_PATH ,那么不进行空间检查。               
    if(mClearingCache) {               
        if(localLOGV) Slog.i(TAG, "Thread already running just skip");               
        //make sure the thread is not hung for too long               
        long diffTime = System.currentTimeMillis() - mThreadStartTime;               
        if(diffTime > (10*60*1000)) {               
            Slog.w(TAG, "Thread that clears cache file seems to run for ever");               
        }               
    } else {               
        //重新计算3个分区的剩余空间大小;               
        restatDataDir();               
        if (localLOGV)  Slog.v(TAG, "freeMemory="+mFreeMem);               

        //post intent to NotificationManager to display icon if necessary               
        ////如果剩余空间低于mMemLowThreshold,先做一次缓存清理;               
        if (mFreeMem < mMemLowThreshold) {               
            if (!mLowMemFlag) {               
                if (checkCache) {               
                    // See if clearing cache helps               
                    // Note that clearing cache is asynchronous and so we do a               
                    // memory check again once the cache has been cleared.               
                    //首先清除缓存               
                    mThreadStartTime = System.currentTimeMillis();               
                    mClearSucceeded = false;               
                    clearCache();               
                } else {               
                    //如果空间仍然低于mMemLowThreshold,发送广播并在状态来设置一个               
                    //警告通知;               
                    Slog.i(TAG, "Running low on memory. Sending notification");               
                    sendNotification();               
                    mLowMemFlag = true;               
                }               
            } else {               
                if (localLOGV) Slog.v(TAG, "Running low on memory " +               
                        "notification already sent. do nothing");               
            }               
        } else {               
            if (mLowMemFlag) {               
                //剩余空间不小于mMemLowThreshold,且已经设置了mLowMemFlag,则               
                //取消空间不足广播。               
                Slog.i(TAG, "Memory available. Cancelling notification");               
                cancelNotification();               
                mLowMemFlag = false;               
            }               
        }               
        if (mFreeMem < mMemFullThreshold) {               
            //如果空间已满,则发送空间已满的广播;               
            if (!mMemFullFlag) {               
                sendFullNotification();               
                mMemFullFlag = true;               
            }               
        } else {               
            if (mMemFullFlag) {               
                //空间不满且已经发送了空间已满的广播,则在此取消。               
                cancelFullNotification();               
                mMemFullFlag = false;               
            }               
        }               
    }               
    if(localLOGV) Slog.i(TAG, "Posting Message again");               
    //keep posting messages to itself periodically               
    //DEFAULT_CHECK_INTERVAL为1分钟,即每1分钟会触发一次检查  
    postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);               
}