diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/ContextImpl.java | 11 | ||||
-rw-r--r-- | core/java/android/os/FileUtils.java | 3 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 3 | ||||
-rw-r--r-- | core/java/com/android/internal/backup/LocalTransport.java | 3 | ||||
-rw-r--r-- | core/java/com/android/internal/os/AtomicFile.java | 5 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 100 | ||||
-rw-r--r-- | core/java/com/android/internal/util/JournaledFile.java | 107 |
7 files changed, 179 insertions, 53 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4464ab9..f296f43 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2935,9 +2935,14 @@ class ContextImpl extends Context { private boolean writeFileLocked() { // Rename the current file so it may be used as a backup during the next read if (mFile.exists()) { - if (!mFile.renameTo(mBackupFile)) { - Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile); - return false; + if (!mBackupFile.exists()) { + if (!mFile.renameTo(mBackupFile)) { + Log.e(TAG, "Couldn't rename file " + mFile + + " to backup file " + mBackupFile); + return false; + } + } else { + mFile.delete(); } } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 4780cf3..a17b7fe 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -115,6 +115,9 @@ public class FileUtils */ public static boolean copyToFile(InputStream inputStream, File destFile) { try { + if (destFile.exists()) { + destFile.delete(); + } OutputStream out = new FileOutputStream(destFile); try { byte[] buffer = new byte[4096]; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 8311bdc..2b5489c 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -546,6 +546,9 @@ public class ViewDebug { recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces"); try { + if (recyclerDump.exists()) { + recyclerDump.delete(); + } final FileOutputStream file = new FileOutputStream(recyclerDump); final DataOutputStream out = new DataOutputStream(file); diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java index 9e4b606..b436363 100644 --- a/core/java/com/android/internal/backup/LocalTransport.java +++ b/core/java/com/android/internal/backup/LocalTransport.java @@ -105,6 +105,9 @@ public class LocalTransport extends IBackupTransport.Stub { + " key64=" + base64Key); if (dataSize >= 0) { + if (entityFile.exists()) { + entityFile.delete(); + } FileOutputStream entity = new FileOutputStream(entityFile); if (dataSize > bufSize) { diff --git a/core/java/com/android/internal/os/AtomicFile.java b/core/java/com/android/internal/os/AtomicFile.java index ca0345f..e675ef0 100644 --- a/core/java/com/android/internal/os/AtomicFile.java +++ b/core/java/com/android/internal/os/AtomicFile.java @@ -45,12 +45,13 @@ public class AtomicFile { public FileOutputStream startWrite() throws IOException { // Rename the current file so it may be used as a backup during the next read if (mBaseName.exists()) { - if (!mBaseName.renameTo(mBackupName)) { - mBackupName.delete(); + if (!mBackupName.exists()) { if (!mBaseName.renameTo(mBackupName)) { Log.w("AtomicFile", "Couldn't rename file " + mBaseName + " to backup file " + mBackupName); } + } else { + mBaseName.delete(); } } FileOutputStream str = null; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 71ccb3b..46769ce 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -16,6 +16,8 @@ package com.android.internal.os; +import com.android.internal.util.JournaledFile; + import android.bluetooth.BluetoothHeadset; import android.net.TrafficStats; import android.os.BatteryStats; @@ -30,6 +32,7 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.Slog; import android.util.SparseArray; import java.io.BufferedReader; @@ -57,7 +60,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 42; + private static final int VERSION = 43; // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks @@ -68,8 +71,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static int sNumSpeedSteps; - private final File mFile; - private final File mBackupFile; + private final JournaledFile mFile; /** * The statistics we have collected organized by uids. @@ -216,7 +218,7 @@ public final class BatteryStatsImpl extends BatteryStats { // For debugging public BatteryStatsImpl() { - mFile = mBackupFile = null; + mFile = null; } public static interface Unpluggable { @@ -2704,8 +2706,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(String filename) { - mFile = new File(filename); - mBackupFile = new File(filename + ".bak"); + mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); mStartCount++; mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { @@ -2736,7 +2737,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(Parcel p) { - mFile = mBackupFile = null; + mFile = null; readFromParcel(p); } @@ -2799,7 +2800,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (m == null) { // Not crashing might make board bringup easier. - Log.w(TAG, "Couldn't get kernel wake lock stats"); + Slog.w(TAG, "Couldn't get kernel wake lock stats"); return; } @@ -3047,26 +3048,19 @@ public final class BatteryStatsImpl extends BatteryStats { return u.getServiceStatsLocked(pkg, name); } + private static JournaledFile makeJournaledFile() { + final String base = "/data/system/device_policies.xml"; + return new JournaledFile(new File(base), new File(base + ".tmp")); + } + public void writeLocked() { - if ((mFile == null) || (mBackupFile == null)) { - Log.w("BatteryStats", "writeLocked: no file associated with this instance"); + if (mFile == null) { + Slog.w("BatteryStats", "writeLocked: no file associated with this instance"); return; } - // Keep the old file around until we know the new one has - // been successfully written. - if (mFile.exists()) { - if (mBackupFile.exists()) { - mBackupFile.delete(); - } - if (!mFile.renameTo(mBackupFile)) { - Log.w("BatteryStats", "Failed to back up file before writing new stats"); - return; - } - } - try { - FileOutputStream stream = new FileOutputStream(mFile); + FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite()); Parcel out = Parcel.obtain(); writeSummaryToParcel(out); stream.write(out.marshall()); @@ -3074,18 +3068,14 @@ public final class BatteryStatsImpl extends BatteryStats { stream.flush(); stream.close(); - mBackupFile.delete(); + mFile.commit(); mLastWriteTime = SystemClock.elapsedRealtime(); return; } catch (IOException e) { - Log.w("BatteryStats", "Error writing battery statistics", e); - } - if (mFile.exists()) { - if (!mFile.delete()) { - Log.w(TAG, "Failed to delete mangled file " + mFile); - } + Slog.w("BatteryStats", "Error writing battery statistics", e); } + mFile.rollback(); } static byte[] readFully(FileInputStream stream) throws java.io.IOException { @@ -3112,29 +3102,19 @@ public final class BatteryStatsImpl extends BatteryStats { } public void readLocked() { - if ((mFile == null) || (mBackupFile == null)) { - Log.w("BatteryStats", "readLocked: no file associated with this instance"); + if (mFile == null) { + Slog.w("BatteryStats", "readLocked: no file associated with this instance"); return; } mUidStats.clear(); - FileInputStream stream = null; - if (mBackupFile.exists()) { - try { - stream = new FileInputStream(mBackupFile); - } catch (java.io.IOException e) { - // We'll try for the normal settings file. - } - } - try { - if (stream == null) { - if (!mFile.exists()) { - return; - } - stream = new FileInputStream(mFile); + File file = mFile.chooseForRead(); + if (!file.exists()) { + return; } + FileInputStream stream = new FileInputStream(file); byte[] raw = readFully(stream); Parcel in = Parcel.obtain(); @@ -3144,7 +3124,7 @@ public final class BatteryStatsImpl extends BatteryStats { readSummaryFromParcel(in); } catch(java.io.IOException e) { - Log.e("BatteryStats", "Error reading battery statistics", e); + Slog.e("BatteryStats", "Error reading battery statistics", e); } } @@ -3155,7 +3135,7 @@ public final class BatteryStatsImpl extends BatteryStats { private void readSummaryFromParcel(Parcel in) { final int version = in.readInt(); if (version != VERSION) { - Log.w("BatteryStats", "readFromParcel: version got " + version + Slog.w("BatteryStats", "readFromParcel: version got " + version + ", expected " + VERSION + "; erasing old stats"); return; } @@ -3197,6 +3177,10 @@ public final class BatteryStatsImpl extends BatteryStats { mBluetoothOnTimer.readSummaryFromParcelLocked(in); int NKW = in.readInt(); + if (NKW > 10000) { + Slog.w(TAG, "File corrupt: too many kernel wake locks " + NKW); + return; + } for (int ikw = 0; ikw < NKW; ikw++) { if (in.readInt() != 0) { String kwltName = in.readString(); @@ -3207,6 +3191,10 @@ public final class BatteryStatsImpl extends BatteryStats { sNumSpeedSteps = in.readInt(); final int NU = in.readInt(); + if (NU > 10000) { + Slog.w(TAG, "File corrupt: too many uids " + NU); + return; + } for (int iu = 0; iu < NU; iu++) { int uid = in.readInt(); Uid u = new Uid(uid); @@ -3235,6 +3223,10 @@ public final class BatteryStatsImpl extends BatteryStats { } int NW = in.readInt(); + if (NW > 10000) { + Slog.w(TAG, "File corrupt: too many wake locks " + NW); + return; + } for (int iw = 0; iw < NW; iw++) { String wlName = in.readString(); if (in.readInt() != 0) { @@ -3249,6 +3241,10 @@ public final class BatteryStatsImpl extends BatteryStats { } int NP = in.readInt(); + if (NP > 10000) { + Slog.w(TAG, "File corrupt: too many sensors " + NP); + return; + } for (int is = 0; is < NP; is++) { int seNumber = in.readInt(); if (in.readInt() != 0) { @@ -3258,6 +3254,10 @@ public final class BatteryStatsImpl extends BatteryStats { } NP = in.readInt(); + if (NP > 10000) { + Slog.w(TAG, "File corrupt: too many processes " + NP); + return; + } for (int ip = 0; ip < NP; ip++) { String procName = in.readString(); Uid.Proc p = u.getProcessStatsLocked(procName); @@ -3270,6 +3270,10 @@ public final class BatteryStatsImpl extends BatteryStats { } NP = in.readInt(); + if (NP > 10000) { + Slog.w(TAG, "File corrupt: too many packages " + NP); + return; + } for (int ip = 0; ip < NP; ip++) { String pkgName = in.readString(); Uid.Pkg p = u.getPackageStatsLocked(pkgName); diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java new file mode 100644 index 0000000..af0c6c6 --- /dev/null +++ b/core/java/com/android/internal/util/JournaledFile.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import java.io.File; +import java.io.IOException; + +public class JournaledFile { + File mReal; + File mTemp; + boolean mWriting; + + public JournaledFile(File real, File temp) { + mReal = real; + mTemp = temp; + } + + /** Returns the file for you to read. + * @more + * Prefers the real file. If it doesn't exist, uses the temp one, and then copies + * it to the real one. If there is both a real file and a temp one, assumes that the + * temp one isn't fully written and deletes it. + */ + public File chooseForRead() { + File result; + if (mReal.exists()) { + result = mReal; + if (mTemp.exists()) { + mTemp.delete(); + } + } else if (mTemp.exists()) { + result = mTemp; + mTemp.renameTo(mReal); + } else { + return mReal; + } + return result; + } + + /** + * Returns a file for you to write. + * @more + * If a write is already happening, throws. In other words, you must provide your + * own locking. + * <p> + * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes. + */ + public File chooseForWrite() { + if (mWriting) { + throw new IllegalStateException("uncommitted write already in progress"); + } + if (!mReal.exists()) { + // If the real one doesn't exist, it's either because this is the first time + // or because something went wrong while copying them. In this case, we can't + // trust anything that's in temp. In order to have the chooseForRead code not + // use the temporary one until it's fully written, create an empty file + // for real, which will we'll shortly delete. + try { + mReal.createNewFile(); + } catch (IOException e) { + // Ignore + } + } + + if (mTemp.exists()) { + mTemp.delete(); + } + mWriting = true; + return mTemp; + } + + /** + * Commit changes. + */ + public void commit() { + if (!mWriting) { + throw new IllegalStateException("no file to commit"); + } + mWriting = false; + mTemp.renameTo(mReal); + } + + /** + * Roll back changes. + */ + public void rollback() { + if (!mWriting) { + throw new IllegalStateException("no file to roll back"); + } + mWriting = false; + mTemp.delete(); + } +} |