DeviceStorageMonitorService.java revision 62e1b4e9d41a01db423b5e4684ecf529ed46106d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007-2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Notification;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.NotificationManager;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.IPackageDataObserver;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.IPackageManager;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.StatFs;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties;
3643866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongkerimport android.provider.Settings;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
398a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4243866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * This class implements a service to monitor the amount of disk
4343866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * storage space on the device.  If the free storage on device is less
4443866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * than a tunable threshold value (a secure settings parameter;
4543866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * default 10%) a low memory notification is displayed to alert the
4643866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * user. If the user clicks on the low memory notification the
4743866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * Application Manager application gets launched to let the user free
4843866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * storage space.
4943866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker *
5043866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * Event log events: A low memory event with the free storage on
5143866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * device in bytes is logged to the event log when the device goes low
5243866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * on storage space.  The amount of free storage on the device is
5343866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * periodically logged to the event log. The log interval is a secure
5443866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * settings parameter with a default value of 12 hours.  When the free
5543866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * storage differential goes below a threshold (again a secure
5643866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * settings parameter with a default value of 2MB), the free memory is
5743866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker * logged to the event log.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass DeviceStorageMonitorService extends Binder {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "DeviceStorageMonitorService";
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DEBUG = false;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int DEVICE_MEMORY_WHAT = 1;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MONITOR_INTERVAL = 1; //in minutes
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOW_MEMORY_NOTIFICATION_ID = 1;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
67247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn    private static final int DEFAULT_THRESHOLD_MAX_BYTES = 500*1024*1024; // 500MB
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
71bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private static final int DEFAULT_FULL_THRESHOLD_BYTES = 1024*1024; // 1MB
723161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private long mFreeMem;  // on /data
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastReportedFreeMem;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastReportedFreeMemTime;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mLowMemFlag=false;
76bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private boolean mMemFullFlag=false;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContentResolver mContentResolver;
793161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private long mTotalMemory;  // on /data
803161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private StatFs mDataFileStats;
813161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private StatFs mSystemFileStats;
823161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private StatFs mCacheFileStats;
833161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private static final String DATA_PATH = "/data";
843161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private static final String SYSTEM_PATH = "/system";
853161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private static final String CACHE_PATH = "/cache";
863161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private long mThreadStartTime = -1;
873161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private boolean mClearSucceeded = false;
883161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    private boolean mClearingCache;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Intent mStorageLowIntent;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Intent mStorageOkIntent;
91bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private Intent mStorageFullIntent;
92bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private Intent mStorageNotFullIntent;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private CachePackageDataObserver mClearCacheObserver;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int _TRUE = 1;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int _FALSE = 0;
96bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private long mMemLowThreshold;
97bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private int mMemFullThreshold;
983161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This string is used for ServiceManager access to this class.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final String SERVICE = "devicestoragemonitor";
1033161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1053161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker    * Handler that checks the amount of disk space on the device and sends a
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * notification if the device runs low on disk space
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Handler mHandler = new Handler() {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
111bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby            //don't handle an invalid message
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (msg.what != DEVICE_MEMORY_WHAT) {
1138a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "Will not process invalid message");
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            checkMemory(msg.arg1 == _TRUE);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1193161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class CachePackageDataObserver extends IPackageDataObserver.Stub {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onRemoveCompleted(String packageName, boolean succeeded) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClearSucceeded = succeeded;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClearingCache = false;
1248a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if(localLOGV) Slog.i(TAG, " Clear succeeded:"+mClearSucceeded
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    +", mClearingCache:"+mClearingCache+" Forcing memory check");
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            postCheckMemoryMsg(false, 0);
1273161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1293161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final void restatDataDir() {
1313161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        try {
1323161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            mDataFileStats.restat(DATA_PATH);
1333161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            mFreeMem = (long) mDataFileStats.getAvailableBlocks() *
1343161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                mDataFileStats.getBlockSize();
1353161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        } catch (IllegalArgumentException e) {
1363161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            // use the old value of mFreeMem
1373161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Allow freemem to be overridden by debug.freemem for testing
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String debugFreeMem = SystemProperties.get("debug.freemem");
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!"".equals(debugFreeMem)) {
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFreeMem = Long.parseLong(debugFreeMem);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14343866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker        // Read the log interval from secure settings
14443866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker        long freeMemLogInterval = Settings.Secure.getLong(mContentResolver,
14543866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker                Settings.Secure.SYS_FREE_STORAGE_LOG_INTERVAL,
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //log the amount of free memory in event log
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long currTime = SystemClock.elapsedRealtime();
1493161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        if((mLastReportedFreeMemTime == 0) ||
1503161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker           (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastReportedFreeMemTime = currTime;
1523161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            long mFreeSystem = -1, mFreeCache = -1;
1533161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            try {
1543161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                mSystemFileStats.restat(SYSTEM_PATH);
1553161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                mFreeSystem = (long) mSystemFileStats.getAvailableBlocks() *
1563161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                    mSystemFileStats.getBlockSize();
1573161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            } catch (IllegalArgumentException e) {
1583161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                // ignore; report -1
1593161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            }
1603161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            try {
1613161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                mCacheFileStats.restat(CACHE_PATH);
1623161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                mFreeCache = (long) mCacheFileStats.getAvailableBlocks() *
1633161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                    mCacheFileStats.getBlockSize();
1643161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            } catch (IllegalArgumentException e) {
1653161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                // ignore; report -1
1663161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            }
1673161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            mCacheFileStats.restat(CACHE_PATH);
168ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.FREE_STORAGE_LEFT,
1693161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                                mFreeMem, mFreeSystem, mFreeCache);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17143866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker        // Read the reporting threshold from secure settings
17243866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker        long threshold = Settings.Secure.getLong(mContentResolver,
17343866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker                Settings.Secure.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If mFree changed significantly log the new value
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long delta = mFreeMem - mLastReportedFreeMem;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (delta > threshold || delta < -threshold) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastReportedFreeMem = mFreeMem;
179ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.FREE_STORAGE_CHANGED, mFreeMem);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1823161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final void clearCache() {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mClearCacheObserver == null) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Lazy instantiation
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClearCacheObserver = new CachePackageDataObserver();
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mClearingCache = true;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1908a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV) Slog.i(TAG, "Clearing cache");
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
192bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                    freeStorageAndNotify(mMemLowThreshold, mClearCacheObserver);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
1948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClearingCache = false;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClearSucceeded = false;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1993161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final void checkMemory(boolean checkCache) {
2013161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        //if the thread that was started to clear cache is still running do nothing till its
2023161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        //finished clearing cache. Ideally this flag could be modified by clearCache
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and should be accessed via a lock but even if it does this test will fail now and
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //hopefully the next time this flag will be set to the correct value.
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if(mClearingCache) {
2068a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if(localLOGV) Slog.i(TAG, "Thread already running just skip");
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //make sure the thread is not hung for too long
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long diffTime = System.currentTimeMillis() - mThreadStartTime;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if(diffTime > (10*60*1000)) {
2108a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Thread that clears cache file seems to run for ever");
2113161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker            }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            restatDataDir();
2148a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (localLOGV)  Slog.v(TAG, "freeMemory="+mFreeMem);
2153161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //post intent to NotificationManager to display icon if necessary
217bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby            if (mFreeMem < mMemLowThreshold) {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mLowMemFlag) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (checkCache) {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // See if clearing cache helps
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Note that clearing cache is asynchronous and so we do a
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // memory check again once the cache has been cleared.
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mThreadStartTime = System.currentTimeMillis();
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mClearSucceeded = false;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        clearCache();
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2278a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        Slog.i(TAG, "Running low on memory. Sending notification");
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sendNotification();
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mLowMemFlag = true;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
2328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (localLOGV) Slog.v(TAG, "Running low on memory " +
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "notification already sent. do nothing");
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mLowMemFlag) {
2378a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.i(TAG, "Memory available. Cancelling notification");
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cancelNotification();
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLowMemFlag = false;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
242bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby            if (mFreeMem < mMemFullThreshold) {
243bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                if (!mMemFullFlag) {
244bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                    sendFullNotification();
245bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                    mMemFullFlag = true;
246bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                }
247bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby            } else {
248bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                if (mMemFullFlag) {
249bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                    cancelFullNotification();
250bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                    mMemFullFlag = false;
251bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                }
252bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby            }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2548a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if(localLOGV) Slog.i(TAG, "Posting Message again");
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //keep posting messages to itself periodically
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2583161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void postCheckMemoryMsg(boolean clearCache, long delay) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Remove queued messages
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.removeMessages(DEVICE_MEMORY_WHAT);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT,
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                clearCache ?_TRUE : _FALSE, 0),
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delay);
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2663161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
2683161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker     * just query settings to retrieve the memory threshold.
26943866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker     * Preferred this over using a ContentObserver since Settings.Secure caches the value
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any way
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long getMemThreshold() {
273247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        long value = Settings.Secure.getInt(
2743161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                              mContentResolver,
27543866e0c48bb0effe8805afd62b253e50ca7d591Doug Zongker                              Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE,
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              DEFAULT_THRESHOLD_PERCENTAGE);
2778a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value);
278247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        value *= mTotalMemory;
279247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        long maxValue = Settings.Secure.getInt(
280247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                mContentResolver,
281247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES,
282247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn                DEFAULT_THRESHOLD_MAX_BYTES);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //evaluate threshold value
284247fe74c934cb3fba85aae7e051a8044f460fb11Dianne Hackborn        return value < maxValue ? value : maxValue;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
287bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    /*
288bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     * just query settings to retrieve the memory full threshold.
289bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     * Preferred this over using a ContentObserver since Settings.Secure caches the value
290bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     * any way
291bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     */
292bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private int getMemFullThreshold() {
293bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        int value = Settings.Secure.getInt(
294bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                              mContentResolver,
295bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                              Settings.Secure.SYS_STORAGE_FULL_THRESHOLD_BYTES,
296bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby                              DEFAULT_FULL_THRESHOLD_BYTES);
297bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        if(localLOGV) Slog.v(TAG, "Full Threshold Bytes="+value);
298bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        return value;
299bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    }
300bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * Constructor to run service. initializes the disk space threshold value
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * and posts an empty message to kickstart the process.
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public DeviceStorageMonitorService(Context context) {
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastReportedFreeMemTime = 0;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContentResolver = mContext.getContentResolver();
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //create StatFs object
3103161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        mDataFileStats = new StatFs(DATA_PATH);
3113161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        mSystemFileStats = new StatFs(SYSTEM_PATH);
3123161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        mCacheFileStats = new StatFs(CACHE_PATH);
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //initialize total storage on device
3143161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        mTotalMemory = ((long)mDataFileStats.getBlockCount() *
3153161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker                        mDataFileStats.getBlockSize())/100L;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
3174b3309211ed6f3532b44481945a4725143d50b8aJeff Hamilton        mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
3194b3309211ed6f3532b44481945a4725143d50b8aJeff Hamilton        mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
320bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
321bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
322bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
323bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
324bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        // cache storage thresholds
325bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mMemLowThreshold = getMemThreshold();
326bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mMemFullThreshold = getMemFullThreshold();
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMemory(true);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3293161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * This method sends a notification to NotificationManager to display
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * an error dialog indicating low disk space and launch the Installer
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * application
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final void sendNotification() {
3378a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if(localLOGV) Slog.i(TAG, "Sending low memory notification");
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //log the event to event log with the amount of free storage(in bytes) left on the device
339ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker        EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //  Pack up the values and broadcast them to everyone
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent lowMemIntent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lowMemIntent.putExtra("memory", mFreeMem);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3443161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker        NotificationManager mNotificationMgr =
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (NotificationManager)mContext.getSystemService(
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Context.NOTIFICATION_SERVICE);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CharSequence title = mContext.getText(
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.string.low_internal_storage_view_title);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CharSequence details = mContext.getText(
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.string.low_internal_storage_view_text);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent intent = PendingIntent.getActivity(mContext, 0,  lowMemIntent, 0);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Notification notification = new Notification();
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notification.tickerText = title;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notification.flags |= Notification.FLAG_NO_CLEAR;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notification.setLatestEventInfo(mContext, title, details, intent);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNotificationMgr.notify(LOW_MEMORY_NOTIFICATION_ID, notification);
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendStickyBroadcast(mStorageLowIntent);
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Cancels low storage notification and sends OK intent.
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final void cancelNotification() {
3658a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if(localLOGV) Slog.i(TAG, "Canceling low memory notification");
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NotificationManager mNotificationMgr =
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (NotificationManager)mContext.getSystemService(
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Context.NOTIFICATION_SERVICE);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //cancel notification since memory has been freed
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID);
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.removeStickyBroadcast(mStorageLowIntent);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(mStorageOkIntent);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3753161795b2353171bb0636fb3ea6dab7dec80a4f4Doug Zongker
376bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    /**
377bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     * Send a notification when storage is full.
378bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     */
379bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private final void sendFullNotification() {
380bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        if(localLOGV) Slog.i(TAG, "Sending memory full notification");
381bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mContext.sendStickyBroadcast(mStorageFullIntent);
382bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    }
383bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby
384bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    /**
385bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     * Cancels memory full notification and sends "not full" intent.
386bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby     */
387bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    private final void cancelFullNotification() {
388bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
389bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mContext.removeStickyBroadcast(mStorageFullIntent);
390bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby        mContext.sendBroadcast(mStorageNotFullIntent);
391bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby    }
392bb3716332321e22537a5015be13e2229fb9b90bcJake Hamby
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateMemory() {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int callingUid = getCallingUid();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if(callingUid != Process.SYSTEM_UID) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // force an early check
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        postCheckMemoryMsg(true, 0);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
40162e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root
40262e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    /**
40362e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * Callable from other things in the system service to obtain the low memory
40462e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * threshold.
40562e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     *
40662e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * @return low memory threshold in bytes
40762e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     */
40862e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    public long getMemoryLowThreshold() {
40962e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root        return mMemLowThreshold;
41062e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    }
41162e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root
41262e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    /**
41362e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * Callable from other things in the system process to check whether memory
41462e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * is low.
41562e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     *
41662e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     * @return true is memory is low
41762e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root     */
41862e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    public boolean isMemoryLow() {
41962e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root        return mLowMemFlag;
42062e1b4e9d41a01db423b5e4684ecf529ed46106dKenny Root    }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
422