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.java56    @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.cpp481binder::Status VoldNativeService::runIdleMaint(
482        const android::sp<android::os::IVoldTaskListener>& 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.cpp310int RunIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
311    std::unique_lock<std::mutex> 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<std::string> 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中调用fstrimcase 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<android::os::IVoldTaskListener>& 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<android::os::IVoldTaskListener>& listener) {
144    acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
145
146    // Collect both fstab and vold volumes
147    std::list<std::string> 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

安卓9.0trim相关源码分析相关推荐

  1. Ansroid系统(262)---MTK安卓sim卡相关源码分析

    MTK安卓sim卡相关源码分析 原文地址:http://m.blog.csdn.net/article/details?id=50039589 最近由于一个sim卡相关的需求,就去了解了一下Andro ...

  2. MTK安卓sim卡相关源码分析

    最近由于一个sim卡相关的需求,就去了解了一下Android Sim卡相关的一些代码.在此记录一下. 简要说一下需求吧,需要在插拔卡的时候弹出对话框,提供界面让用户选择开启默认卡数据链接或者转移到另一 ...

  3. 【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | 任务检查 | 任务执行 )

    文章目录 一.回调 StateChangedListener 接口 二.JobHandler 处理 ( 任务检查 ) 三.maybeRunPendingJobsH 方法 四.assignJobsToC ...

  4. kafka-分区重分配及相关源码分析

    tips:本文源码对应的kafka版本是2.3.1,源码分支2.3 分区重分配及相关源码分析 简单示例 kafka消费者分区重分配 消费者分区重分配简介 分区重分配的策略 RangeAssignor ...

  5. freeRTOS滴答时钟相关源码分析

    最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营[第2期]7 ...

  6. 【Android 电量优化】JobScheduler 相关源码分析 ( ConnectivityController 底层源码分析 | 构造函数 | 追踪任务更新 | 注册接收者监听连接变化 )

    文章目录 一.ConnectivityController 连接控制器引入 二.ConnectivityController 构造方法解析 ( 注册接收者 ) 三.mConnectivityRecei ...

  7. 【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )

    文章目录 一.JobScheduler 提交任务 schedule 方法源码分析 二.schedule(JobInfo job, int uId) 方法 三.scheduleAsPackage 方法 ...

  8. 详述 Spring MVC 启动流程及相关源码分析

    文章目录 Web 应用部署初始化过程(Web Application Deployement) Spring MVC 启动过程 Listener 的初始化过程 Filter 的初始化 Servlet ...

  9. Vue中的methods配置项中的箭头函数this指向及相关源码分析

    之前在使用Vue时遇到一个问题,我们知道在Vue的methods中定义函数时,要想使用到Vue实例或者组件实例的this时,我们就不能使用箭头函数定义方法,因为箭头函数中的this是在函数定义时生成的 ...

最新文章

  1. python利用自动识别写模块_Python 利用pytesser模块识别图像文字
  2. Cell颠覆性发现:中脑神经元的新作用
  3. python数据组织存在维度吗_用Python将统计数据不存在的记录按维度对应指标补齐...
  4. JavaScript中匿名函数的作用和用法
  5. 计算机课件制作技能,经济论文写作PPT制作有哪些技巧?
  6. Linux中磁盘还有空间,但创建文件时提示空间不足
  7. 不要讨厌HATEOAS Part Deux:HATEOAS的春天
  8. width:100vh与min-height:calc(100vh + 51px)
  9. Magento教程 15:Magento 批次修改产品资料
  10. Android项目跑不起来,本机的android虚拟机跑不起android小项目
  11. 酷开网络首推“无界空间”,酷开系统8正式发布!
  12. React学习笔记2017-12-31
  13. 如何在 Project 里设置(创建)里程碑
  14. C语言课程设计学生考勤管理系统
  15. Python-C语言语法解析:pycparser模块
  16. [网站优化实战]公共CDN库/Nginx启用Gzip/全站CDN加速
  17. (转)不看绝对后悔的Linux三剑客之awk实战精讲
  18. linux监控网络流量命令,Linux网络流量实时监控ifstat iftop命令详解
  19. 《互联网时代》第二集·浪潮
  20. matlab 截断共轭梯度法,最优化作业 共轭梯度法 matlab代码

热门文章

  1. 非靶代谢组学数据预处理XCMS+IPO
  2. OpenGL for Windows NT及其程序设计
  3. 计算机启动不能马上联网,电脑开机不能立马联网要等几分钟怎么办? 爱问知识人...
  4. linux socks5 源码,在Linux中用RPM来安装SOCKS5
  5. Win8.1 中 配置Tomcat7
  6. 计算机回收站设置大小,win7旗舰版系统修改回收站容量大小的设置方法【图文】...
  7. keil5环境下生成bin文件
  8. jperf服务器报告文档,iperf使用
  9. 下载、安装Wireshark
  10. 导包:org.hamcrest.Matchers.equalTo报错解决方法