diff options
| author | 2014-11-26 10:34:45 +0000 | |
|---|---|---|
| committer | 2014-11-26 10:39:08 +0000 | |
| commit | 7377998dac67ce8d486e11b9bd2f159fe0ca501d (patch) | |
| tree | 00b4acd48899dd96171e285c1bf857028461cab6 | |
| parent | 9da0881ffbcdc566cc1bf60b817ab4f617d0049a (diff) | |
| parent | a42f7c1d4247a940258a04bae839dccb28219823 (diff) | |
resolved conflicts for merge of a42f7c1d to lmp-sprout-dev
Change-Id: I8e53c9d7e0014b4ffc621c561b737aa2dae5460c
| -rw-r--r-- | core/java/android/os/storage/IMountService.java | 63 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 7 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 3 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java | 52 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 45 |
6 files changed, 171 insertions, 0 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index cf407f401844..116110eba74d 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -856,6 +856,38 @@ public interface IMountService extends IInterface { } return _result; } + + @Override + public long lastMaintenance() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + long _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_lastMaintenance, _data, _reply, 0); + _reply.readException(); + _result = _reply.readLong(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public void runMaintenance() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_runMaintenance, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return; + } } private static final String DESCRIPTOR = "IMountService"; @@ -942,6 +974,10 @@ public interface IMountService extends IInterface { static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40; + static final int TRANSACTION_lastMaintenance = IBinder.FIRST_CALL_TRANSACTION + 41; + + static final int TRANSACTION_runMaintenance = IBinder.FIRST_CALL_TRANSACTION + 42; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1347,6 +1383,19 @@ public interface IMountService extends IInterface { reply.writeInt(resultCode); return true; } + case TRANSACTION_lastMaintenance: { + data.enforceInterface(DESCRIPTOR); + long lastMaintenance = lastMaintenance(); + reply.writeNoException(); + reply.writeLong(lastMaintenance); + return true; + } + case TRANSACTION_runMaintenance: { + data.enforceInterface(DESCRIPTOR); + runMaintenance(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1617,4 +1666,18 @@ public interface IMountService extends IInterface { public String getField(String field) throws RemoteException; public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException; + + /** + * Report the time of the last maintenance operation such as fstrim. + * @return Timestamp of the last maintenance operation, in the + * System.currentTimeMillis() time base + * @throws RemoteException + */ + public long lastMaintenance() throws RemoteException; + + /** + * Kick off an immediate maintenance operation + * @throws RemoteException + */ + public void runMaintenance() throws RemoteException; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b1c338ee1cdd..fbfd53e38369 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5550,6 +5550,13 @@ public final class Settings { public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs"; /** + * Time since last fstrim (milliseconds) after which we force one to happen + * during device startup. If unset, the default is 3 days. + * @hide + */ + public static final String FSTRIM_MANDATORY_INTERVAL = "fstrim_mandatory_interval"; + + /** * The interval in milliseconds at which to check packet counts on the * mobile data interface when screen is on, to detect possible data * connection problems. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 81615e6df5fc..46d1cbd5a3db 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3516,6 +3516,9 @@ <!-- [CHAR LIMIT=40] Title of dialog that is shown when system is starting. --> <string name="android_start_title">Android is starting\u2026</string> + <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog when doing an fstrim. --> + <string name="android_upgrading_fstrim">Optimizing storage.</string> + <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. --> <string name="android_upgrading_apk">Optimizing app <xliff:g id="number" example="123">%1$d</xliff:g> of diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1cd1d96fd363..84c655e4a41c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1659,6 +1659,7 @@ <java-symbol type="string" name="aerr_application" /> <java-symbol type="string" name="aerr_process" /> <java-symbol type="string" name="aerr_title" /> + <java-symbol type="string" name="android_upgrading_fstrim" /> <java-symbol type="string" name="android_upgrading_apk" /> <java-symbol type="string" name="android_upgrading_complete" /> <java-symbol type="string" name="android_upgrading_starting_apps" /> diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index e400fb67c0c7..6c981c00504f 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -83,6 +83,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.math.BigInteger; @@ -90,7 +91,9 @@ import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -359,6 +362,11 @@ class MountService extends IMountService.Stub // Used in the ObbActionHandler private IMediaContainerService mContainerService = null; + // Last fstrim operation tracking + private static final String LAST_FSTRIM_FILE = "last-fstrim"; + private final File mLastMaintenanceFile; + private long mLastMaintenance; + // Handler messages private static final int H_UNMOUNT_PM_UPDATE = 1; private static final int H_UNMOUNT_PM_DONE = 2; @@ -536,6 +544,15 @@ class MountService extends IMountService.Stub case H_FSTRIM: { waitForReady(); Slog.i(TAG, "Running fstrim idle maintenance"); + + // Remember when we kicked it off + try { + mLastMaintenance = System.currentTimeMillis(); + mLastMaintenanceFile.setLastModified(mLastMaintenance); + } catch (Exception e) { + Slog.e(TAG, "Unable to record last fstrim!"); + } + try { // This method must be run on the main (handler) thread, // so it is safe to directly call into vold. @@ -544,6 +561,7 @@ class MountService extends IMountService.Stub } catch (NativeDaemonConnectorException ndce) { Slog.e(TAG, "Failed to run fstrim!"); } + // invoke the completion callback, if any Runnable callback = (Runnable) msg.obj; if (callback != null) { @@ -699,6 +717,18 @@ class MountService extends IMountService.Stub mHandler.sendMessage(mHandler.obtainMessage(H_FSTRIM, callback)); } + // Binder entry point for kicking off an immediate fstrim + @Override + public void runMaintenance() { + validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); + runIdleMaintenance(null); + } + + @Override + public long lastMaintenance() { + return mLastMaintenance; + } + private void doShareUnshareVolume(String path, String method, boolean enable) { // TODO: Add support for multiple share methods if (!method.equals("ums")) { @@ -1477,6 +1507,22 @@ class MountService extends IMountService.Stub // Add OBB Action Handler to MountService thread. mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper()); + // Initialize the last-fstrim tracking if necessary + File dataDir = Environment.getDataDirectory(); + File systemDir = new File(dataDir, "system"); + mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE); + if (!mLastMaintenanceFile.exists()) { + // Not setting mLastMaintenance here means that we will force an + // fstrim during reboot following the OTA that installs this code. + try { + (new FileOutputStream(mLastMaintenanceFile)).close(); + } catch (IOException e) { + Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath()); + } + } else { + mLastMaintenance = mLastMaintenanceFile.lastModified(); + } + /* * Create the connection to vold with a maximum queue of twice the * amount of containers we'd ever expect to have. This keeps an @@ -3075,6 +3121,12 @@ class MountService extends IMountService.Stub pw.increaseIndent(); mConnector.dump(fd, pw, args); pw.decreaseIndent(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + pw.println(); + pw.print("Last maintenance: "); + pw.println(sdf.format(new Date(mLastMaintenance))); } /** {@inheritDoc} */ diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2b6ea5d23b75..ab1819e3fc7e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -138,6 +138,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Environment.UserEnvironment; +import android.os.storage.IMountService; import android.os.storage.StorageManager; import android.os.Debug; import android.os.FileUtils; @@ -161,6 +162,7 @@ import android.system.ErrnoException; import android.system.Os; import android.system.StructStat; import android.text.TextUtils; +import android.text.format.DateUtils; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DisplayMetrics; @@ -280,6 +282,18 @@ public class PackageManagerService extends IPackageManager.Stub { private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes /** + * Wall-clock timeout (in milliseconds) after which we *require* that an fstrim + * be run on this device. We use the value in the Settings.Global.MANDATORY_FSTRIM_INTERVAL + * settings entry if available, otherwise we use the hardcoded default. If it's been + * more than this long since the last fstrim, we force one during the boot sequence. + * + * This backstops other fstrim scheduling: if the device is alive at midnight+idle, + * one gets run at the next available charging+idle time. This final mandatory + * no-fstrim check kicks in only of the other scheduling criteria is never met. + */ + private static final long DEFAULT_MANDATORY_FSTRIM_INTERVAL = 3 * DateUtils.DAY_IN_MILLIS; + + /** * Whether verification is enabled by default. */ private static final boolean DEFAULT_VERIFY_ENABLE = true; @@ -4513,6 +4527,37 @@ public class PackageManagerService extends IPackageManager.Stub { public void performBootDexOpt() { enforceSystemOrRoot("Only the system can request dexopt be performed"); + // Before everything else, see whether we need to fstrim. + try { + IMountService ms = PackageHelper.getMountService(); + if (ms != null) { + final long interval = android.provider.Settings.Global.getLong( + mContext.getContentResolver(), + android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL, + DEFAULT_MANDATORY_FSTRIM_INTERVAL); + if (interval > 0) { + final long timeSinceLast = System.currentTimeMillis() - ms.lastMaintenance(); + if (timeSinceLast > interval) { + Slog.w(TAG, "No disk maintenance in " + timeSinceLast + + "; running immediately"); + if (!isFirstBoot()) { + try { + ActivityManagerNative.getDefault().showBootMessage( + mContext.getResources().getString( + R.string.android_upgrading_fstrim), true); + } catch (RemoteException e) { + } + } + ms.runMaintenance(); + } + } + } else { + Slog.e(TAG, "Mount service unavailable!"); + } + } catch (RemoteException e) { + // Can't happen; MountService is local + } + final HashSet<PackageParser.Package> pkgs; synchronized (mPackages) { pkgs = mDeferredDexOpt; |