when logging free space on /data, log /system and /cache as well

Report space free on system and cache so we can estimate bad block
statistics for devices in the field.
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 52e09ca..57af029 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -43,8 +43,8 @@
 /**
  * This class implements a service to monitor the amount of disk storage space
  * on the device. If the free storage on device is less than a tunable threshold value
- * (default is 10%. this value is a gservices parameter) a low memory notification is 
- * displayed to alert the user. If the user clicks on the low memory notification the 
+ * (default is 10%. this value is a gservices parameter) a low memory notification is
+ * displayed to alert the user. If the user clicks on the low memory notification the
  * Application Manager application gets launched to let the user free storage space.
  * Event log events:
  * A low memory event with the free storage on device in bytes  is logged to the event log
@@ -68,32 +68,35 @@
     private static final int EVENT_LOG_FREE_STORAGE_LEFT = 2746;
     private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
     private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
-    private long mFreeMem;
+    private long mFreeMem;  // on /data
     private long mLastReportedFreeMem;
     private long mLastReportedFreeMemTime;
     private boolean mLowMemFlag=false;
     private Context mContext;
     private ContentResolver mContentResolver;
-    long mBlkSize;
-    long mTotalMemory;
-    StatFs mFileStats;
-    private static final String DATA_PATH="/data";
-    long mThreadStartTime = -1;
-    boolean mClearSucceeded = false;
-    boolean mClearingCache;
+    private long mTotalMemory;  // on /data
+    private StatFs mDataFileStats;
+    private StatFs mSystemFileStats;
+    private StatFs mCacheFileStats;
+    private static final String DATA_PATH = "/data";
+    private static final String SYSTEM_PATH = "/system";
+    private static final String CACHE_PATH = "/cache";
+    private long mThreadStartTime = -1;
+    private boolean mClearSucceeded = false;
+    private boolean mClearingCache;
     private Intent mStorageLowIntent;
     private Intent mStorageOkIntent;
     private CachePackageDataObserver mClearCacheObserver;
     private static final int _TRUE = 1;
     private static final int _FALSE = 0;
-    
+
     /**
      * This string is used for ServiceManager access to this class.
      */
     static final String SERVICE = "devicestoragemonitor";
-    
+
     /**
-    * Handler that checks the amount of disk space on the device and sends a 
+    * Handler that checks the amount of disk space on the device and sends a
     * notification if the device runs low on disk space
     */
     Handler mHandler = new Handler() {
@@ -107,7 +110,7 @@
             checkMemory(msg.arg1 == _TRUE);
         }
     };
-    
+
     class CachePackageDataObserver extends IPackageDataObserver.Stub {
         public void onRemoveCompleted(String packageName, boolean succeeded) {
             mClearSucceeded = succeeded;
@@ -115,12 +118,17 @@
             if(localLOGV) Log.i(TAG, " Clear succeeded:"+mClearSucceeded
                     +", mClearingCache:"+mClearingCache+" Forcing memory check");
             postCheckMemoryMsg(false, 0);
-        }        
+        }
     }
-    
+
     private final void restatDataDir() {
-        mFileStats.restat(DATA_PATH);
-        mFreeMem = mFileStats.getAvailableBlocks()*mBlkSize;
+        try {
+            mDataFileStats.restat(DATA_PATH);
+            mFreeMem = (long) mDataFileStats.getAvailableBlocks() *
+                mDataFileStats.getBlockSize();
+        } catch (IllegalArgumentException e) {
+            // use the old value of mFreeMem
+        }
         // Allow freemem to be overridden by debug.freemem for testing
         String debugFreeMem = SystemProperties.get("debug.freemem");
         if (!"".equals(debugFreeMem)) {
@@ -132,10 +140,27 @@
                 DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000;
         //log the amount of free memory in event log
         long currTime = SystemClock.elapsedRealtime();
-        if((mLastReportedFreeMemTime == 0) || 
-                (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) {
+        if((mLastReportedFreeMemTime == 0) ||
+           (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) {
             mLastReportedFreeMemTime = currTime;
-            EventLog.writeEvent(EVENT_LOG_FREE_STORAGE_LEFT, mFreeMem);
+            long mFreeSystem = -1, mFreeCache = -1;
+            try {
+                mSystemFileStats.restat(SYSTEM_PATH);
+                mFreeSystem = (long) mSystemFileStats.getAvailableBlocks() *
+                    mSystemFileStats.getBlockSize();
+            } catch (IllegalArgumentException e) {
+                // ignore; report -1
+            }
+            try {
+                mCacheFileStats.restat(CACHE_PATH);
+                mFreeCache = (long) mCacheFileStats.getAvailableBlocks() *
+                    mCacheFileStats.getBlockSize();
+            } catch (IllegalArgumentException e) {
+                // ignore; report -1
+            }
+            mCacheFileStats.restat(CACHE_PATH);
+            EventLog.writeEvent(EVENT_LOG_FREE_STORAGE_LEFT,
+                                mFreeMem, mFreeSystem, mFreeCache);
         }
         // Read the reporting threshold from Gservices
         long threshold = Gservices.getLong(mContentResolver,
@@ -148,7 +173,7 @@
             EventLog.writeEvent(EVENT_LOG_STORAGE_BELOW_THRESHOLD, mFreeMem);
         }
     }
-    
+
     private final void clearCache() {
         if (mClearCacheObserver == null) {
             // Lazy instantiation
@@ -165,10 +190,10 @@
             mClearSucceeded = false;
         }
     }
-    
+
     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 
+        //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.
         if(mClearingCache) {
@@ -177,11 +202,11 @@
             long diffTime = System.currentTimeMillis() - mThreadStartTime;
             if(diffTime > (10*60*1000)) {
                 Log.w(TAG, "Thread that clears cache file seems to run for ever");
-            } 
+            }
         } else {
             restatDataDir();
             if (localLOGV)  Log.v(TAG, "freeMemory="+mFreeMem);
-            
+
             //post intent to NotificationManager to display icon if necessary
             long memThreshold = getMemThreshold();
             if (mFreeMem < memThreshold) {
@@ -214,7 +239,7 @@
         //keep posting messages to itself periodically
         postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
     }
-    
+
     private void postCheckMemoryMsg(boolean clearCache, long delay) {
         // Remove queued messages
         mHandler.removeMessages(DEVICE_MEMORY_WHAT);
@@ -222,16 +247,16 @@
                 clearCache ?_TRUE : _FALSE, 0),
                 delay);
     }
-    
+
     /*
-     * just query settings to retrieve the memory threshold. 
+     * just query settings to retrieve the memory threshold.
      * Preferred this over using a ContentObserver since Settings.Gservices caches the value
      * any way
      */
     private long getMemThreshold() {
         int value = Settings.Gservices.getInt(
-                              mContentResolver, 
-                              Settings.Gservices.SYS_STORAGE_THRESHOLD_PERCENTAGE, 
+                              mContentResolver,
+                              Settings.Gservices.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                               DEFAULT_THRESHOLD_PERCENTAGE);
         if(localLOGV) Log.v(TAG, "Threshold Percentage="+value);
         //evaluate threshold value
@@ -247,16 +272,17 @@
         mContext = context;
         mContentResolver = mContext.getContentResolver();
         //create StatFs object
-        mFileStats = new StatFs(DATA_PATH);
-        //initialize block size
-        mBlkSize = mFileStats.getBlockSize();
+        mDataFileStats = new StatFs(DATA_PATH);
+        mSystemFileStats = new StatFs(SYSTEM_PATH);
+        mCacheFileStats = new StatFs(CACHE_PATH);
         //initialize total storage on device
-        mTotalMemory = ((long)mFileStats.getBlockCount()*mBlkSize)/100L;
+        mTotalMemory = ((long)mDataFileStats.getBlockCount() *
+                        mDataFileStats.getBlockSize())/100L;
         mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
         mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
         checkMemory(true);
     }
-    
+
 
     /**
     * This method sends a notification to NotificationManager to display
@@ -271,7 +297,7 @@
         Intent lowMemIntent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE);
         lowMemIntent.putExtra("memory", mFreeMem);
         lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        NotificationManager mNotificationMgr = 
+        NotificationManager mNotificationMgr =
                 (NotificationManager)mContext.getSystemService(
                         Context.NOTIFICATION_SERVICE);
         CharSequence title = mContext.getText(
@@ -302,7 +328,7 @@
         mContext.removeStickyBroadcast(mStorageLowIntent);
         mContext.sendBroadcast(mStorageOkIntent);
     }
-    
+
     public void updateMemory() {
         int callingUid = getCallingUid();
         if(callingUid != Process.SYSTEM_UID) {