[DO NOT MERGE] Notify vold when to start fstrim.

Since using the discard option for mounting an Ext4 file system
could lead to unpredictable slowdowns of I/O we will explicitly
control when to perform fstrim, i.e. discard unused blocks of the
mounted volume. We are using the idle maintenance intents sent by
the system which specify a window that one can use to perform
expensive maintenance tasks while the user does not use the device.

This change is adding a broadcast receiver for the idle maintenance
start intent to the mount services which then notifies vold when to
start fstrim.

Since fstrim will be run on a daily basis we do not expect fstrim
to be too long, so it is not interruptible. We will implement
interruption only in case we see issues.

bug:8056794

Change-Id: I1438479d2956b61b82d3a130854376f7a144aaf3
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 2e0c977..c6aca2f 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -596,6 +596,26 @@
         }
     };
 
+    private final BroadcastReceiver mIdleMaintenanceReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            waitForReady();
+            String action = intent.getAction();
+            // Since fstrim will be run on a daily basis we do not expect
+            // fstrim to be too long, so it is not interruptible. We will
+            // implement interruption only in case we see issues.
+            if (Intent.ACTION_IDLE_MAINTENANCE_START.equals(action)) {
+                try {
+                    // This method runs on the handler thread,
+                    // so it is safe to directly call into vold.
+                    mConnector.execute("fstrim", "dotrim");
+                } catch (NativeDaemonConnectorException ndce) {
+                    Slog.e(TAG, "Failed to run fstrim!");
+                }
+            }
+        }
+    };
+
     private final class MountServiceBinderListener implements IBinder.DeathRecipient {
         final IMountServiceListener mListener;
 
@@ -1301,6 +1321,12 @@
                     mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE), null, mHandler);
         }
 
+        // Watch for idle maintenance changes
+        IntentFilter idleMaintenanceFilter = new IntentFilter();
+        idleMaintenanceFilter.addAction(Intent.ACTION_IDLE_MAINTENANCE_START);
+        mContext.registerReceiverAsUser(mIdleMaintenanceReceiver, UserHandle.ALL,
+                idleMaintenanceFilter, null, mHandler);
+
         // Add OBB Action Handler to MountService thread.
         mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper());