一、前序
设备运行过程中,经常会碰到由于系统空间被消耗完而导致的问题,因此要确保为系统功能(如数据库同步)保留一定的空间。在功能机中一般是由文件系统模块预留,那么在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%,这个值可以自由设置)时将会向用户发送剩余空间不足的警告,让用户释放一些空间。下面就来看下这个服务:
二、DeviceStorageMonitorService服务
1、服务的启动
首先看一下该服务是如何被添加进来的。
在android/frameworks/base/services/java/com/android/server/SystemServer.java中使用ServiceManager. startService()来直接启动服务:
private void startOtherServices() {
......
mSystemServiceManager.startService(DeviceStorageMonitorService.class);
......
}
具体可以参考servicemanager模块处理流程。
2、服务工作流程
上文中 serviceserver启动了该服务,下面深入该应用看一下。
首先看下其构造函数:DeviceStorageMonitorService()
public DeviceStorageMonitorService(Context context) {
super(context);
mLastReportedFreeMemTime = 0;
mResolver = context.getContentResolver();
mIsBootImageOnDisk = isBootImageOnDisk();
//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 = (long)mDataFileStats.getBlockCount() *
mDataFileStats.getBlockSize();
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);
}
首先,获取了data、system和cache路径;
设置了几个存储变量,存放当前存储状态:mLastReportedFreeMemTime、mIsBootImageOnDisk、mTotalMemory。
最后设置了4个intent:
ACTION_DEVICE_STORAGE_LOW:用于通知存储空间不足;
ACTION_DEVICE_STORAGE_OK:通知存储空间回复正常;
ACTION_DEVICE_STORAGE_FULL:通知存储空间满;
ACTION_DEVICE_STORAGE_NOT_FULL:存储空间没满。
这里值得注意的是每个Intent都设置了FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT标志,因此这三个Intent只能由注册了的BroadcastReceiver接收。
接着我们就开始看onStart函数:
/**
* Initializes the disk space threshold value and posts an empty message to
* kickstart the process.
*/
@Override
public void onStart() {
// cache storage thresholds
final StorageManager sm = StorageManager.from(getContext());
mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH); //487M
mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH); //1M
Slog.i(TAG, "fsj [onStart]mMemLowThreshold:"+mMemLowThreshold+" mMemFullThreshold:"+mMemFullThreshold);
mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4; //366M
mMemCacheTrimToThreshold = mMemLowThreshold
+ ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2); //730M
mFreeMemAfterLastCacheClear = mTotalMemory;
checkMemory(true);
mCacheFileDeletedObserver = new CacheFileDeletedObserver();
mCacheFileDeletedObserver.startWatching();
publishBinderService(SERVICE, mRemoteService);
publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
}
这里首先主要创建并初始化了存储相关的阀值:
mMemLowThreshold、mMemFullThreshold、mMemCacheStartTrimThreshold、mMemCacheTrimToThreshold等。重点工作就在其中checkMemory中实施的,这里就来到了本文的重点:
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.
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 {
restatDataDir();
if (localLOGV) Slog.v(TAG, "freeMemory="+mFreeMem);
//post intent to NotificationManager to display icon if necessary
if (mFreeMem < mMemLowThreshold) {
if (checkCache) {
// We are allowed to clear cache files at this point to
// try to get down below the limit, because this is not
// the initial call after a cache clear has been attempted.
// In this case we will try a cache clear if our free
// space has gone below the cache clear limit.
if (mFreeMem < mMemCacheStartTrimThreshold) {
// We only clear the cache if the free storage has changed
// a significant amount since the last time.
//if ((mFreeMemAfterLastCacheClear-mFreeMem)
// >= ((mMemLowThreshold-mMemCacheStartTrimThreshold)/4)) {
//here just test:when mFreeMem<104857600(100M) begin clean cache!
if(mFreeMem<104857600){
// 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.
Slog.v(TAG, "fsj current freeMemory="+mFreeMem);
mThreadStartTime = System.currentTimeMillis();
mClearSucceeded = false;
clearCache();
}
}
} else {
// This is a call from after clearing the cache. Note
// the amount of free storage at this point.
mFreeMemAfterLastCacheClear = mFreeMem;
if (!mLowMemFlag) {
// We tried to clear the cache, but that didn't get us
// below the low storage limit. Tell the user.
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 {
mFreeMemAfterLastCacheClear = mFreeMem;
if (mLowMemFlag) {
Slog.i(TAG, "Memory available. Cancelling notification");
cancelNotification();
mLowMemFlag = false;
}
}
if (!mLowMemFlag && !mIsBootImageOnDisk) {
Slog.i(TAG, "No boot image on disk due to lack of space. Sending notification");
sendNotification();
}
if (mFreeMem < mMemFullThreshold) {
if (!mMemFullFlag) {
sendFullNotification();
mMemFullFlag = true;
}
} else {
if (mMemFullFlag) {
cancelFullNotification();
mMemFullFlag = false;
}
}
}
if(localLOGV) Slog.i(TAG, "Posting Message again [DEFAULT_CHECK_INTERVAL:"+DEFAULT_CHECK_INTERVAL+"]");
//keep posting messages to itself periodically
postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
}
这里进行该函数流程的大致梳理:
当mClearingCache标志为false时(第一次进行check的状态),会直接走到check主流程中去。
首先,restatDataDir():
获取当前剩余存储空间mFreeMem;
从prop项"debug.freemem"中获取debugFreeMem值,这里只用于debug调试用。我们可以在这里设置任意值来进行存储空间状态的测试。
从系统安全settings中获取剩余空间状态的log的时间间隔freeMemLogInterval;
如果时间间隔大于freeMemLogInterval,重新获取当前mFreeSystem和mFreeCache,并写入到log事件。
从系统安全settings中获取"上报剩余空间状态变动的阀值",如果当前剩余空间和上次上报的剩余空间相差绝对值大于了该阀值,则将当前剩余空间值覆盖为上次上报剩余空间值,并写入log事件。
其次,判断当前剩余空间mFreeMem 是否小于存储空间不足的阀值 mMemLowThreshold,如果小于,接下来会尝试清理cache:
继续判断当前剩余空间mFreeMem是否小于开始清理cache的阀值mMemCacheStartTrimThreshold,
如果小于,则会继续判断上次清理完cache后剩余的空间mFreeMemAfterLastCacheClear减去当前剩余空间mFreeMem是否不小于空间不足的阀值mMemLowThreshold减去开始清理cache的阀值mMemCacheStartTrimThreshold只差的1/4,
如果不小于,下面会直接进入cache的清理工作:
private void clearCache() {
if (mClearCacheObserver == null) {
// Lazy instantiation
mClearCacheObserver = new CachePackageDataObserver();
}
mClearingCache = true;
try {
if (localLOGV) Slog.i(TAG, "Clearing cache");
IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
freeStorageAndNotify(null, mMemCacheTrimToThreshold, mClearCacheObserver);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
mClearingCache = false;
mClearSucceeded = false;
}
}
这里首先会将cache正在清理标志mClearingCache值为true,然后获取PackageManager服务实例,通过该实例的freeStorageAndNotify函数,进行cache的清理工作。接下来我们来到PackageManagerService的freeStorageAndNotify函数中:
@Override
public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
final IPackageDataObserver observer) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_CACHE, null);
// Queue up an async operation since clearing cache may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
int retCode = -1;
synchronized (mInstallLock) {
retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
if (retCode < 0) {
Slog.w(TAG, "Couldn't clear application caches");
}
}
if (observer != null) {
try {
Slog.i(TAG, "fsj retCode="+retCode);
observer.onRemoveCompleted(null, (retCode >= 0));
} catch (RemoteException e) {
Slog.w(TAG, "RemoveException when invoking call back");
}
}
}
});
}
这里首先进行了CLEAR_APP_CACHE权限的check,如果没有的话,这里会直接抛出异常。
接下来通过自身的mHandler post了一个Runable线程。在该线程中,主要完成两件事:
1、通过installer去真正的释放缓存:mInstaller.freeCache(volumeUuid, freeStorageSize),这里具体细节在下文再议。
2、根据释放缓存的结果来回调空间监视器中的清理完成函数,以返回清理结果:
observer.onRemoveCompleted(null, (retCode >= 0));
到这里,一条freecache的线便走通了,接下来通过一副流程图来诠释整个monitor过程。
3、checkMemory流程图
1、源码流程
2、逻辑流程
三、辅助工具
在调试该模块时主要使用了如下几个工具:
1、dumpsys:通过该工具可以查看当前存储的状态信息,使用如下:
root@ :/ # dumpsys devicestoragemonitor
Current DeviceStorageMonitor state:
mFreeMem=51.45 MB mTotalMemory=4.76 GB
mFreeMemAfterLastCacheClear=51.45 MB
mLastReportedFreeMem=51.45 MB mLastReportedFreeMemTime=-2h55m14s144ms
mLowMemFlag=true mMemFullFlag=false
mIsBootImageOnDisk=true mClearSucceeded=false mClearingCache=false
mMemLowThreshold=487 MB mMemFullThreshold=1.00 MB
mMemCacheStartTrimThreshold=366 MB mMemCacheTrimToThreshold=730 MB
2、dd:如果需要将存储填满,有一种比较方便的方式可以使用该工具快速写文件:
root@ :/ #dd if=/dev/zero of=/data/bigfile
大约5分钟便可将5G的空间填满,且由于该指令实质上就是通过/dev/zero在data中创建里面内容全为0的bigfile文件,所以在使用rm指令删除的时候也十分省时。
3、
root@ :/ setprop debug.freemem xxxx
通过源码分析也可以得知,这里设置prop项debug.freemem为任意值,就可以调试该模块了,注意单位是字节。
四、问题实例分析
现象:当存储空间被填满后,设备会不停重启。
部分log如下:
06-16 14:14:53.378 15456 15456 E PackageManager: Unable to write package manager settings, current changes will be lost at reboot
06-16 14:14:53.378 15456 15456 E PackageManager: java.io.IOException: write failed: ENOSPC (No space left on device)
06-16 14:14:53.378 15456 15456 E PackageManager: at libcore.io.IoBridge.write(IoBridge.java:498)
06-16 14:14:53.378 15456 15456 E PackageManager: at java.io.FileOutputStream.write(FileOutputStream.java:186)
06-16 14:14:53.378 15456 15456 E PackageManager: at java.io.BufferedOutputStream.write(BufferedOutputStream.java:131)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.util.FastXmlSerializer.flushBytes(FastXmlSerializer.java:232)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.util.FastXmlSerializer.flush(FastXmlSerializer.java:253)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.util.FastXmlSerializer.append(FastXmlSerializer.java:92)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.util.FastXmlSerializer.escapeAndAppendString(FastXmlSerializer.java:145)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.util.FastXmlSerializer.attribute(FastXmlSerializer.java:176)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.pm.Settings.writePermissionLPr(Settings.java:2456)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.pm.Settings.writeLPr(Settings.java:2125)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:2325)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:1767)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:371)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.SystemServer.run(SystemServer.java:273)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.server.SystemServer.main(SystemServer.java:173)
06-16 14:14:53.378 15456 15456 E PackageManager: at java.lang.reflect.Method.invoke(Native Method)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:769)
06-16 14:14:53.378 15456 15456 E PackageManager: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:659)
06-16 14:14:53.378 15456 15456 E PackageManager: Caused by: android.system.ErrnoException: write failed: ENOSPC (No space left on device)
06-16 14:14:53.378 15456 15456 E PackageManager: at libcore.io.Posix.writeBytes(Native Method)
06-16 14:14:53.378 15456 15456 E PackageManager: at libcore.io.Posix.write(Posix.java:271)
06-16 14:14:53.378 15456 15456 E PackageManager: at libcore.io.BlockGuardOs.write(BlockGuardOs.jav[ 1144.913530@3] fb: osd[0] enable: 1 (Binder_3)
a:313)
06-16 14:14:53.378 15456[ 1144.940333@4] binder: 15456:15710 transaction failed 29189, size 4-0
[ 1144.945889@4] binder: send failed reply for transaction 498299, target dead
15456 E PackageManager: at libcore.io.IoBridge.write(IoBridge.java:493)
06-16 14:14:53.378 15456 15456 E PackageManager: ... 17 more
06-16 14:14:53.379 15456 15456 E AndroidRuntime: Error reporting WTF
06-16 14:14:53.379 15456 15456 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.app.IActivityManager.handleApplicationWtf(android.os.IBinder, java.lang.String, boolean, android.app.ApplicationErrorReport$CrashInfo)' on a null object reference
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.internal.os.RuntimeInit.wtf(RuntimeInit.java:348)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at android.util.Log$1.onTerribleFailure(Log.java:104)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at android.util.Log.wtf(Log.java:297)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at [ 1145.029659@2] ffs_data_put(): freeing
[ 1145.033949@6] dhd_pktfilter_offload_set: failed to add pktfilter 102 0 0 0 0xFFFFFF 0x01005E, retcode = -2
android.util.Slog.wtf(Slog.java:116)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.pm.Settings.writeLPr(Settings.java:2212)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.[ 1145.061789@7] dhd_set_suspend: Remove extra suspend setting
[ 1145.066209@2] ffs_data_put(): freeing
[ 1145.070162@2] adjust_gadget_wake_lock unlock
[ 1145.073544@2] android_work: did not send uevent (0 0 (null))
pm.PackageManagerService.<init>(PackageManagerService.java:2325)[ 1145.086973@2] read descriptors
[ 1145.088550@2] read descriptors
[ 1145.091676@2] read strings
[ 1145.094266@2] mtp_bind_config
[ 1145.097498@0] USB RESET
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:1767)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:371)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.run(SystemServer.java:273)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.main(SystemServer.java:173)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:769)
06-16 14:14:53.379 15456 15456 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:659)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: Original WTF:
06-16 14:14:53.380 15456 15456 E AndroidRuntime: android.util.Log$TerribleFailure: Unable to write package manage[ 1145.189063@3] type=1400 audit(1497593707.405:764): avc: denied { read } for pid=16321 comm="method.sogou.tv" name="anr" dev="mmcblk0p14" ino=273633 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:anr_data_file:s0 tclass=dir permissive=0
r settings, current changes will be lost at reboot
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at android.util.Log.wtf(Lo[ 1145.221555@1] BT_RADIO going: off
[ 1145.224043@1] BCM_BT: going OFF
g.java:291)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at android.util.Slog.wtf(Slog.java:116)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.pm.Settings.writeLPr(Settings.java:2212)
06-16 14:14:53.380 15456 15456 E Andro[ 1145.250567@2] BT_RADIO going: on
[ 1145.252418@2] BCM_BT: going ON
idRuntime: at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:2325)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:1767)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:371)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.run(SystemServer.java:273)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.SystemServer.main(SystemServer.java:173)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:769)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:659)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: Caused by: java.io.IOException: write failed: ENOSPC (No space left on device)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at libcore.io.IoBridge.write(IoBridge.java:498)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at java.io.FileOutputStream.write(FileOutputStream.java:1[ 1145.367248@3] type=1400 audit(1497593707.585:765): avc: denied { getattr } for pid=16360 comm="sh" path="/system/xbin/su" dev="mmcblk0p13" ino=1687 scontext=u:r:system_app:s0 tcontext=u:object_r:su_exec:s0 tclass=file permissive=0
[ 1145.386555@3] type=1400 audit(1497593707.605:766): avc: denied { getattr } for pid=16350 comm="BUGLY_THREAD" path="/sys/devices/d0074000.emmc/mmc_host/emmc/emmc:0001/cid" dev="sysfs" ino=14331 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs_xbmc:s0 tclass=file permissive=0
86)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at java.io.BufferedOutputStream.write(BufferedOutputStream.java:131)
06-[ 1145.424256@3] name_store() 971, name jjconfig, 8
[ 1145.426132@3] name_store() 981
16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.in[ 1145.435933@2] name: jjconfig, size 3
ternal.util.FastXmlSerializer.flushBytes(FastXmlSerializer.java:232)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.util.FastXmlSerializer.flush(FastXmlSerializer.java:253)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.util.FastXmlSerializer.append(FastXmlSerializer.java:92)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.util.FastXmlSerializer.escapeAndAppendString(FastXmlSerializer.java:145)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.internal.util.FastXmlSerializer.attribute(FastXmlSerializer.java:176)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.pm.Settings.writePermissionLPr(Settings.java:2456)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at com.android.server.pm.Settings.writeLPr(Settings.java:2125)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: ... 8 more
06-16 14:14:53.380 15456 15456 E AndroidRuntime: Caused by: android.system.ErrnoException: write failed: ENOSPC (No space left on device)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at libcore.io.Posix.writeBytes(Native Method)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at libcore.io.Posix.write(Posix.java:271)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at libcore.io.BlockGuardOs.write(BlockGuardOs.java:313)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: at libcore.io.IoBridge.write(IoBridge.java:493)
06-16 14:14:53.380 15456 15456 E AndroidRuntime: ... 17 more
06-16 14:14:53.384 15456 15456 I art : Starting a blocking GC Explicit
06-16 14:14:53.411 15456 15456 I art : Explicit concurrent mark sweep GC freed 21756(1434KB) AllocSpace objects, 1(20KB) LOS objects, 33% free, 5MB/8MB, paused 570us total 26.287ms
06-16 14:14:53.412 15456 15456 I SystemServer: User Service
06-16 14:14:53.413 15456 15570 D StrictMode: No activity manager; failed to Dropbox violation.
这里是由于内存空间不足引起packagemanager崩溃而造成的问题。