1818
1919import com .android .server .EventLogTags ;
2020import com .android .server .SystemService ;
21+ import com .android .server .pm .PackageManagerService ;
2122
2223import android .app .Notification ;
2324import android .app .NotificationManager ;
5152import java .io .FileDescriptor ;
5253import java .io .PrintWriter ;
5354
55+ import dalvik .system .VMRuntime ;
56+
5457/**
5558 * This class implements a service to monitor the amount of disk
5659 * storage space on the device. If the free storage on device is less
@@ -89,6 +92,7 @@ public class DeviceStorageMonitorService extends SystemService {
8992 private long mLastReportedFreeMemTime ;
9093 boolean mLowMemFlag =false ;
9194 private boolean mMemFullFlag =false ;
95+ private final boolean mIsBootImageOnDisk ;
9296 private final ContentResolver mResolver ;
9397 private final long mTotalMemory ; // on /data
9498 private final StatFs mDataFileStats ;
@@ -285,6 +289,10 @@ void checkMemory(boolean checkCache) {
285289 mLowMemFlag = false ;
286290 }
287291 }
292+ if (!mLowMemFlag && !mIsBootImageOnDisk ) {
293+ Slog .i (TAG , "No boot image on disk due to lack of space. Sending notification" );
294+ sendNotification ();
295+ }
288296 if (mFreeMem < mMemFullThreshold ) {
289297 if (!mMemFullFlag ) {
290298 sendFullNotification ();
@@ -314,6 +322,7 @@ public DeviceStorageMonitorService(Context context) {
314322 super (context );
315323 mLastReportedFreeMemTime = 0 ;
316324 mResolver = context .getContentResolver ();
325+ mIsBootImageOnDisk = isBootImageOnDisk ();
317326 //create StatFs object
318327 mDataFileStats = new StatFs (DATA_PATH .getAbsolutePath ());
319328 mSystemFileStats = new StatFs (SYSTEM_PATH .getAbsolutePath ());
@@ -331,6 +340,15 @@ public DeviceStorageMonitorService(Context context) {
331340 mStorageNotFullIntent .addFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
332341 }
333342
343+ private static boolean isBootImageOnDisk () {
344+ for (String instructionSet : PackageManagerService .getAllDexCodeInstructionSets ()) {
345+ if (!VMRuntime .isBootClassPathOnDisk (instructionSet )) {
346+ return false ;
347+ }
348+ }
349+ return true ;
350+ }
351+
334352 /**
335353 * Initializes the disk space threshold value and posts an empty message to
336354 * kickstart the process.
@@ -364,7 +382,7 @@ public void checkMemory() {
364382
365383 @ Override
366384 public boolean isMemoryLow () {
367- return mLowMemFlag ;
385+ return mLowMemFlag || ! mIsBootImageOnDisk ;
368386 }
369387
370388 @ Override
@@ -409,6 +427,7 @@ void dumpImpl(PrintWriter pw) {
409427
410428 pw .print (" mLowMemFlag=" ); pw .print (mLowMemFlag );
411429 pw .print (" mMemFullFlag=" ); pw .println (mMemFullFlag );
430+ pw .print (" mIsBootImageOnDisk=" ); pw .print (mIsBootImageOnDisk );
412431
413432 pw .print (" mClearSucceeded=" ); pw .print (mClearSucceeded );
414433 pw .print (" mClearingCache=" ); pw .println (mClearingCache );
@@ -445,19 +464,25 @@ private void sendNotification() {
445464 Context .NOTIFICATION_SERVICE );
446465 CharSequence title = context .getText (
447466 com .android .internal .R .string .low_internal_storage_view_title );
448- CharSequence details = context .getText (
449- com .android .internal .R .string .low_internal_storage_view_text );
467+ CharSequence details = context .getText (mIsBootImageOnDisk
468+ ? com .android .internal .R .string .low_internal_storage_view_text
469+ : com .android .internal .R .string .low_internal_storage_view_text_no_boot );
450470 PendingIntent intent = PendingIntent .getActivityAsUser (context , 0 , lowMemIntent , 0 ,
451471 null , UserHandle .CURRENT );
452- Notification notification = new Notification ();
453- notification .icon = com .android .internal .R .drawable .stat_notify_disk_full ;
454- notification .tickerText = title ;
472+ Notification notification = new Notification .Builder (context )
473+ .setSmallIcon (com .android .internal .R .drawable .stat_notify_disk_full )
474+ .setTicker (title )
475+ .setColor (context .getResources ().getColor (
476+ com .android .internal .R .color .system_notification_accent_color ))
477+ .setContentTitle (title )
478+ .setContentText (details )
479+ .setContentIntent (intent )
480+ .setStyle (new Notification .BigTextStyle ()
481+ .bigText (details ))
482+ .setVisibility (Notification .VISIBILITY_PUBLIC )
483+ .setCategory (Notification .CATEGORY_SYSTEM )
484+ .build ();
455485 notification .flags |= Notification .FLAG_NO_CLEAR ;
456- notification .color = context .getResources ().getColor (
457- com .android .internal .R .color .system_notification_accent_color );
458- notification .setLatestEventInfo (context , title , details , intent );
459- notification .visibility = Notification .VISIBILITY_PUBLIC ;
460- notification .category = Notification .CATEGORY_SYSTEM ;
461486 mNotificationMgr .notifyAsUser (null , LOW_MEMORY_NOTIFICATION_ID , notification ,
462487 UserHandle .ALL );
463488 context .sendStickyBroadcastAsUser (mStorageLowIntent , UserHandle .ALL );
0 commit comments