1、trim是什么?
一条ATA指令,由操作系统发送给SSD主控制器,告诉它哪些数据占有的地址是“无效的”。 其实就是操作系统将一部分的控制权交给了SSD主控制器,让操作系统与SSD主控制器有一个互动。因为闪存需要先擦除才能再次写入数据,要得到空闲的闪存空间,SSD必须复制所有“有效”页到新的“空白页”里,并且擦除旧块,即垃圾回收;避免了在操作系统要重新写入数据时, SSD才会知道哪些地址是无效的情况。这样就可以在适当的时机做最好的优化。 简而言之,这是一种能够让闪存长期工作后,也能维持高速度的技术。不少人长期使用安卓机后表示,安卓怎么就越用越卡,无论怎么刷系统清数据也没法回到刚买时的流畅度。这往往是由于长期使用后,闪存的垃圾回收效率大大降低,使得安卓机的I/O性能大跌造成的。安卓4.3支持Trim技术,能够大幅提升闪存垃圾回收效率,让闪存始终保持接近原始状态的高速度。 这样做既提高了“硬盘速度”, 同时也延长了SSD的使用寿命,垃圾回收!!!
2.trim触发条件?
1.开机触发一次
2.每日凌晨3点触发trim,不过这个要在充电状态,或者电量不低于80%条件下.
1.凌晨3点触发trim
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
//系统准备好就会创建fstrim计划.
735 private void handleSystemReady() {
736 initIfReadyAndConnected();
737 resetIfReadyAndConnected();
738
739 // 开始计划日常fstrim操作
740 MountServiceIdler.scheduleIdlePass(mContext);
741
742 ......
753 }
JobScheduler是Android L(API21)新增的特性,该框架将在执行作业(也就是JobInfo)时智能化,并尽可能地批量并推迟JobInfo,从而节省电量。Android8.0及以上建议使用JobScheduler来启动服务。
JobScheduler是作业发布器,它的任务是分发设置作业JobInfo。JobInfo是作业包装体,它包含了任务执行的条件、开始时间、截止时间、具体任务、需要传递的参数等信息。JobService是JobInfo中的参数,它们是条件到了真正执行具体任务。
JobInfo通过Builder模式JobInfo.Builder创建实例,JobInfo.Builder可以设置多个参数,其中作业启动条件必须限制一个。
/**
96 * Schedule the idle job that will ping the mount service
97 */
98 public static void scheduleIdlePass(Context context) {
99 JobScheduler tm = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
100 //获取凌晨3点的时间
101 Calendar calendar = tomorrowMidnight();
//获取到凌晨3点还差的秒数.
102 final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis();
103
104 JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
105 builder.setRequiresDeviceIdle(true); //如果设置为true,请确保在设备处于活动使用状态时不会运行此作业。
106 builder.setRequiresCharging(true); //指定要运行此作业,设备必须正在充电
107 builder.setMinimumLatency(timeToMidnight);//延迟到指定作业时间。
108 tm.schedule(builder.build()); //发布作业.
109 }
//满足触发时间会在MountServiceIdler里执行onStartJob.
xref: /frameworks/base/services/core/java/com/android/server/MountServiceIdler.java
56 @Override
57 public boolean onStartJob(JobParameters params) {
58 // First have the activity manager do its idle maintenance. (Yes this job
59 // is really more than just mount, some day it should be renamed to be system
60 // idleer).
61 try {
//执行空闲维护,主要发送开始维护广播?
62 ActivityManager.getService().performIdleMaintenance();
63 } catch (RemoteException e) {
64 }
65 // The mount service will run an fstrim operation asynchronously
66 // on a designated separate thread, so we provide it with a callback
67 // that lets us cleanly end our idle timeslice. It's safe to call
68 // finishIdle() from any thread.
//获取StorageManagerService的静态实例
70 StorageManagerService ms = StorageManagerService.sSelf;
71 if (ms != null) {
72 synchronized (mFinishCallback) {
73 mStarted = true;
74 }
//调用StorageManagerService里方法,并传入回调函数mFinishCallback.
75 ms.runIdleMaint(mFinishCallback);
76 }
77 return ms != null;
78 }
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
1890 void runIdleMaint(Runnable callback) {
1891 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1892
1893 try {
//通过binder机制调用vold服务里面的runIdleMaint.
1894 mVold.runIdleMaint(new IVoldTaskListener.Stub() {
1895 @Override
1896 public void onStatus(int status, PersistableBundle extras) {
1897 // Not currently used
1898 }
1899 @Override
1900 public void onFinished(int status, PersistableBundle extras) {
1901 if (callback != null) {
//当清理结束,获取一个handler,并发送下一个执行任务.会回调到MountServiceIdler里mFinishCallback
1902 BackgroundThread.getHandler().post(callback);
1903 }
1904 }
1905 });
1906 } catch (Exception e) {
1907 Slog.wtf(TAG, e);
1908 }
1909 }
//组织下一次作业清理任务.
private Runnable mFinishCallback = new Runnable() {
42 @Override
43 public void run() {
44 Slog.i(TAG, "Got mount service completion callback");
45 synchronized (mFinishCallback) {
46 if (mStarted) {
47 jobFinished(mJobParams, false);
48 mStarted = false;
49 }
50 }
51 // ... and try again tomorrow
52 scheduleIdlePass(MountServiceIdler.this);
53 }
54 };
xref: /system/vold/VoldNativeService.cpp
481binder::Status VoldNativeService::runIdleMaint(
482 const android::sp& listener) {
483 ENFORCE_UID(AID_SYSTEM);
484 ACQUIRE_LOCK;
485 //运行空闲维护
486 std::thread([=]() {
487 android::vold::RunIdleMaint(listener);
488 }).detach();
489 return ok();
490}
//调用vold里面的IdleMaint进行磁盘整理.这里面涉及很底层的东西还是比较难理解的,但是从命名来看,还是能够看的出大概处理流程的.
xref: /system/vold/IdleMaint.cpp
310int RunIdleMaint(const android::sp& listener) {
311 std::unique_lock lk(cv_m);
312 if (idle_maint_stat != IdleMaintStats::kStopped) {
313 LOG(DEBUG) << "idle maintenance is already running";
314 if (listener) {
315 android::os::PersistableBundle extras;
316 listener->onFinished(0, extras);
317 }
318 return android::OK;
319 }
320 idle_maint_stat = IdleMaintStats::kRunning;
321 lk.unlock();
322
323 LOG(DEBUG) << "idle maintenance started";
324
325 acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
326
327 std::list paths;
328 addFromFstab(&paths, PathTypes::kBlkDevice);
329 addFromVolumeManager(&paths, PathTypes::kBlkDevice);
330
331 startGc(paths);
332
333 bool gc_aborted = waitForGc(paths);
334
335 stopGc(paths);
336
337 lk.lock();
338 idle_maint_stat = IdleMaintStats::kStopped;
339 lk.unlock();
340
341 cv_stop.notify_one();
342
343 if (!gc_aborted) {
344 Trim(nullptr);
345 runDevGc();
346 }
347
348 if (listener) {
349 android::os::PersistableBundle extras;
//调用回调通知清理结束
350 listener->onFinished(0, extras);
351 }
352
353 LOG(DEBUG) << "idle maintenance completed";
354
355 release_wake_lock(kWakeLock);
356
357 return android::OK;
358}
2.开机fstrim
xref: /frameworks/base/services/java/com/android/server/SystemServer.java
//开机的时候在SystemServer启动服务调用PackageManagerService的performFstrimIfNeeded进行磁盘整理.
private void startOtherServices() {
1010 traceBeginAndSlog("PerformFstrimIfNeeded");
1011 try {
1012 mPackageManagerService.performFstrimIfNeeded();
1013 } catch (Throwable e) {
1014 reportWtf("performing fstrim", e);
1015 }
1016 traceEnd();
}
xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
8928 @Override
8929 public void performFstrimIfNeeded() {
8930 enforceSystemOrRoot("Only the system can request fstrim");
8931
8932 // Before everything else, see whether we need to fstrim.
8933 try {
8934 IStorageManager sm = PackageHelper.getStorageManager();
8935 if (sm != null) {
8936 boolean doTrim = false;
8937 final long interval = android.provider.Settings.Global.getLong(
8938 mContext.getContentResolver(),
8939 android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
8940 DEFAULT_MANDATORY_FSTRIM_INTERVAL);
8941 if (interval > 0) {
8942 final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
8943 if (timeSinceLast > interval) {
8944 doTrim = true;
8945 Slog.w(TAG, "No disk maintenance in " + timeSinceLast
8946 + "; running immediately");
8947 }
8948 }
8949 if (doTrim) {
8950 final boolean dexOptDialogShown;
8951 synchronized (mPackages) {
8952 dexOptDialogShown = mDexOptDialogShown;
8953 }
8954 if (!isFirstBoot() && dexOptDialogShown) {
8955 try {
8956 ActivityManager.getService().showBootMessage(
8957 mContext.getResources().getString(
8958 R.string.android_upgrading_fstrim), true);
8959 } catch (RemoteException e) {
8960 }
8961 }
//调用StorageManagerService的runMaintenance进行磁盘整理.
8962 sm.runMaintenance();
8963 }
8964 } else {
8965 Slog.e(TAG, "storageManager service unavailable!");
8966 }
8967 } catch (RemoteException e) {
8968 // Can't happen; StorageManagerService is local
8969 }
8970 }
//StorageManagerService中发送磁盘整理的消息
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
947 void runIdleMaintenance(Runnable callback) {
948 mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback));
949 }
950
951 // Binder entry point for kicking off an immediate fstrim
952 @Override
953 public void runMaintenance() {
954 enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
955 runIdleMaintenance(null);
956 }
//在handler中调用fstrim
case H_FSTRIM: {
576 Slog.i(TAG, "Running fstrim idle maintenance");
577
578 // Remember when we kicked it off
579 try {
580 mLastMaintenance = System.currentTimeMillis();
581 mLastMaintenanceFile.setLastModified(mLastMaintenance);
582 } catch (Exception e) {
583 Slog.e(TAG, "Unable to record last fstrim!");
584 }
585
586 // TODO: Reintroduce shouldBenchmark() test
587 fstrim(0, null);
588
589 // invoke the completion callback, if any
590 // TODO: fstrim is non-blocking, so remove this useless callback
591 Runnable callback = (Runnable) msg.obj;
592 if (callback != null) {
593 callback.run();
594 }
595 break;
596 }
//通过binder机制调用vold中的fstrim,同时实现VoldTaskListener,当vold处理完会通知到这里.
1849 @Override
1850 public void fstrim(int flags, IVoldTaskListener listener) {
1851 enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
1852
1853 try {
1854 mVold.fstrim(flags, new IVoldTaskListener.Stub() {
1855 @Override
1856 public void onStatus(int status, PersistableBundle extras) {
1857 dispatchOnStatus(listener, status, extras);
1858
1859 // Ignore trim failures
1860 if (status != 0) return;
1861
1862 final String path = extras.getString("path");
1863 final long bytes = extras.getLong("bytes");
1864 final long time = extras.getLong("time");
1865
1866 final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
1867 dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
1868
1869 synchronized (mLock) {
1870 final VolumeRecord rec = findRecordForPath(path);
1871 if (rec != null) {
1872 rec.lastTrimMillis = System.currentTimeMillis();
1873 writeSettingsLocked();
1874 }
1875 }
1876 }
1877
1878 @Override
1879 public void onFinished(int status, PersistableBundle extras) {
1880 dispatchOnFinished(listener, status, extras);
1881
1882 // TODO: benchmark when desired
1883 }
1884 });
1885 } catch (RemoteException e) {
1886 throw e.rethrowAsRuntimeException();
1887 }
1888 }
xref: /system/vold/VoldNativeService.cpp
470binder::Status VoldNativeService::fstrim(int32_t fstrimFlags,
471 const android::sp& listener) {
472 ENFORCE_UID(AID_SYSTEM);
473 ACQUIRE_LOCK;
474
475 std::thread([=]() {
476 android::vold::Trim(listener);
477 }).detach();
478 return ok();
479}
//vold中主要做trim的函数,涉及也是比较底层,比较难理解,大家自己看代码琢磨吧.
xref: /system/vold/IdleMaint.cpp
143void Trim(const android::sp& listener) {
144 acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
145
146 // Collect both fstab and vold volumes
147 std::list paths;
148 addFromFstab(&paths, PathTypes::kMountPoint);
149 addFromVolumeManager(&paths, PathTypes::kMountPoint);
150
151 for (const auto& path : paths) {
152 LOG(DEBUG) << "Starting trim of " << path;
153
154 android::os::PersistableBundle extras;
155 extras.putString(String16("path"), String16(path.c_str()));
156
157 int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
158 if (fd < 0) {
159 PLOG(WARNING) << "Failed to open " << path;
160 if (listener) {
161 listener->onStatus(-1, extras);
162 }
163 continue;
164 }
165
166 struct fstrim_range range;
167 memset(&range, 0, sizeof(range));
168 range.len = ULLONG_MAX;
169
170 nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
171 if (ioctl(fd, FITRIM, &range)) {
172 PLOG(WARNING) << "Trim failed on " << path;
173 if (listener) {
174 listener->onStatus(-1, extras);
175 }
176 } else {
177 nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
178 LOG(INFO) << "Trimmed " << range.len << " bytes on " << path
179 << " in " << nanoseconds_to_milliseconds(time) << "ms";
180 extras.putLong(String16("bytes"), range.len);
181 extras.putLong(String16("time"), time);
182 if (listener) {
183 listener->onStatus(0, extras);
184 }
185 }
186 close(fd);
187 }
188 //trim结束通知回调finish.
189 if (listener) {
190 android::os::PersistableBundle extras;
191 listener->onFinished(0, extras);
192 }
193
194 release_wake_lock(kWakeLock);
195}
以上就是安卓磁盘整理相关代码,希望对大家有点帮忙吧,继续学习..
参考:
https://blog.csdn.net/su1987582/article/details/48729401
https://blog.csdn.net/u013795543/article/details/80861953