diff options
Diffstat (limited to 'core/java')
4 files changed, 69 insertions, 145 deletions
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java index ec79b3650cb2..3a63805defe0 100644 --- a/core/java/android/text/format/TimeFormatter.java +++ b/core/java/android/text/format/TimeFormatter.java @@ -22,8 +22,7 @@ package android.text.format; import android.content.res.Resources; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; +import java.nio.CharBuffer; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; @@ -31,15 +30,13 @@ import libcore.icu.LocaleData; import libcore.util.ZoneInfo; /** - * Formatting logic for {@link Time}. Contains a port of Bionic's broken strftime_tz to Java. The - * main issue with this implementation is the treatment of characters as ASCII, despite returning - * localized (UTF-16) strings from the LocaleData. + * Formatting logic for {@link Time}. Contains a port of Bionic's broken strftime_tz to Java. * * <p>This class is not thread safe. */ class TimeFormatter { - // An arbitrary value outside the range representable by a byte / ASCII character code. - private static final int FORCE_LOWER_CASE = 0x100; + // An arbitrary value outside the range representable by a char. + private static final int FORCE_LOWER_CASE = -1; private static final int SECSPERMIN = 60; private static final int MINSPERHOUR = 60; @@ -62,10 +59,9 @@ class TimeFormatter { private final String dateTimeFormat; private final String timeOnlyFormat; private final String dateOnlyFormat; - private final Locale locale; private StringBuilder outputBuilder; - private Formatter outputFormatter; + private Formatter numberFormatter; public TimeFormatter() { synchronized (TimeFormatter.class) { @@ -84,7 +80,6 @@ class TimeFormatter { this.dateTimeFormat = sDateTimeFormat; this.timeOnlyFormat = sTimeOnlyFormat; this.dateOnlyFormat = sDateOnlyFormat; - this.locale = locale; localeData = sLocaleData; } } @@ -97,19 +92,21 @@ class TimeFormatter { StringBuilder stringBuilder = new StringBuilder(); outputBuilder = stringBuilder; - outputFormatter = new Formatter(stringBuilder, locale); + // This uses the US locale because number localization is handled separately (see below) + // and locale sensitive strings are output directly using outputBuilder. + numberFormatter = new Formatter(stringBuilder, Locale.US); formatInternal(pattern, wallTime, zoneInfo); String result = stringBuilder.toString(); // This behavior is the source of a bug since some formats are defined as being - // in ASCII. Generally localization is very broken. + // in ASCII and not localized. if (localeData.zeroDigit != '0') { result = localizeDigits(result); } return result; } finally { outputBuilder = null; - outputFormatter = null; + numberFormatter = null; } } @@ -132,38 +129,30 @@ class TimeFormatter { * {@link #outputBuilder}. */ private void formatInternal(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) { - // Convert to ASCII bytes to be compatible with old implementation behavior. - byte[] bytes = pattern.getBytes(StandardCharsets.US_ASCII); - if (bytes.length == 0) { - return; - } - - ByteBuffer formatBuffer = ByteBuffer.wrap(bytes); + CharBuffer formatBuffer = CharBuffer.wrap(pattern); while (formatBuffer.remaining() > 0) { - boolean outputCurrentByte = true; - char currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position())); - if (currentByteAsChar == '%') { - outputCurrentByte = handleToken(formatBuffer, wallTime, zoneInfo); + boolean outputCurrentChar = true; + char currentChar = formatBuffer.get(formatBuffer.position()); + if (currentChar == '%') { + outputCurrentChar = handleToken(formatBuffer, wallTime, zoneInfo); } - if (outputCurrentByte) { - currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position())); - outputBuilder.append(currentByteAsChar); + if (outputCurrentChar) { + outputBuilder.append(formatBuffer.get(formatBuffer.position())); } - formatBuffer.position(formatBuffer.position() + 1); } } - private boolean handleToken(ByteBuffer formatBuffer, ZoneInfo.WallTime wallTime, + private boolean handleToken(CharBuffer formatBuffer, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) { - // The byte at formatBuffer.position() is expected to be '%' at this point. + // The char at formatBuffer.position() is expected to be '%' at this point. int modifier = 0; while (formatBuffer.remaining() > 1) { - // Increment the position then get the new current byte. + // Increment the position then get the new current char. formatBuffer.position(formatBuffer.position() + 1); - char currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position())); - switch (currentByteAsChar) { + char currentChar = formatBuffer.get(formatBuffer.position()); + switch (currentChar) { case 'A': modifyAndAppend((wallTime.getWeekDay() < 0 || wallTime.getWeekDay() >= DAYSPERWEEK) @@ -206,7 +195,7 @@ class TimeFormatter { formatInternal("%m/%d/%y", wallTime, zoneInfo); return false; case 'd': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), wallTime.getMonthDay()); return false; case 'E': @@ -218,46 +207,46 @@ class TimeFormatter { case '0': case '^': case '#': - modifier = currentByteAsChar; + modifier = currentChar; continue; case 'e': - outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), wallTime.getMonthDay()); return false; case 'F': formatInternal("%Y-%m-%d", wallTime, zoneInfo); return false; case 'H': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), wallTime.getHour()); return false; case 'I': int hour = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12; - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), hour); + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), hour); return false; case 'j': int yearDay = wallTime.getYearDay() + 1; - outputFormatter.format(getFormat(modifier, "%03d", "%3d", "%d", "%03d"), + numberFormatter.format(getFormat(modifier, "%03d", "%3d", "%d", "%03d"), yearDay); return false; case 'k': - outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), wallTime.getHour()); return false; case 'l': int n2 = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12; - outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), n2); + numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), n2); return false; case 'M': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), wallTime.getMinute()); return false; case 'm': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), wallTime.getMonth() + 1); return false; case 'n': - modifyAndAppend("\n", modifier); + outputBuilder.append('\n'); return false; case 'p': modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1] @@ -274,27 +263,27 @@ class TimeFormatter { formatInternal("%I:%M:%S %p", wallTime, zoneInfo); return false; case 'S': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), wallTime.getSecond()); return false; case 's': int timeInSeconds = wallTime.mktime(zoneInfo); - modifyAndAppend(Integer.toString(timeInSeconds), modifier); + outputBuilder.append(Integer.toString(timeInSeconds)); return false; case 'T': formatInternal("%H:%M:%S", wallTime, zoneInfo); return false; case 't': - modifyAndAppend("\t", modifier); + outputBuilder.append('\t'); return false; case 'U': - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), (wallTime.getYearDay() + DAYSPERWEEK - wallTime.getWeekDay()) / DAYSPERWEEK); return false; case 'u': int day = (wallTime.getWeekDay() == 0) ? DAYSPERWEEK : wallTime.getWeekDay(); - outputFormatter.format("%d", day); + numberFormatter.format("%d", day); return false; case 'V': /* ISO 8601 week number */ case 'G': /* ISO 8601 year (four digits) */ @@ -326,9 +315,9 @@ class TimeFormatter { --year; yday += isLeap(year) ? DAYSPERLYEAR : DAYSPERNYEAR; } - if (currentByteAsChar == 'V') { - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), w); - } else if (currentByteAsChar == 'g') { + if (currentChar == 'V') { + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), w); + } else if (currentChar == 'g') { outputYear(year, false, true, modifier); } else { outputYear(year, true, true, modifier); @@ -342,10 +331,10 @@ class TimeFormatter { int n = (wallTime.getYearDay() + DAYSPERWEEK - ( wallTime.getWeekDay() != 0 ? (wallTime.getWeekDay() - 1) : (DAYSPERWEEK - 1))) / DAYSPERWEEK; - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n); + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n); return false; case 'w': - outputFormatter.format("%d", wallTime.getWeekDay()); + numberFormatter.format("%d", wallTime.getWeekDay()); return false; case 'X': formatInternal(timeOnlyFormat, wallTime, zoneInfo); @@ -371,17 +360,17 @@ class TimeFormatter { return false; } int diff = wallTime.getGmtOffset(); - String sign; + char sign; if (diff < 0) { - sign = "-"; + sign = '-'; diff = -diff; } else { - sign = "+"; + sign = '+'; } - modifyAndAppend(sign, modifier); + outputBuilder.append(sign); diff /= SECSPERMIN; diff = (diff / MINSPERHOUR) * 100 + (diff % MINSPERHOUR); - outputFormatter.format(getFormat(modifier, "%04d", "%4d", "%d", "%04d"), diff); + numberFormatter.format(getFormat(modifier, "%04d", "%4d", "%d", "%04d"), diff); return false; } case '+': @@ -422,7 +411,6 @@ class TimeFormatter { break; default: outputBuilder.append(str); - } } @@ -443,14 +431,14 @@ class TimeFormatter { } if (outputTop) { if (lead == 0 && trail < 0) { - modifyAndAppend("-0", modifier); + outputBuilder.append("-0"); } else { - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), lead); + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), lead); } } if (outputBottom) { int n = ((trail < 0) ? -trail : trail); - outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n); + numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n); } } @@ -472,24 +460,24 @@ class TimeFormatter { } /** - * A broken implementation of {@link Character#isUpperCase(char)} that assumes ASCII in order to - * be compatible with the old native implementation. + * A broken implementation of {@link Character#isUpperCase(char)} that assumes ASCII codes in + * order to be compatible with the old native implementation. */ private static boolean brokenIsUpper(char toCheck) { return toCheck >= 'A' && toCheck <= 'Z'; } /** - * A broken implementation of {@link Character#isLowerCase(char)} that assumes ASCII in order to - * be compatible with the old native implementation. + * A broken implementation of {@link Character#isLowerCase(char)} that assumes ASCII codes in + * order to be compatible with the old native implementation. */ private static boolean brokenIsLower(char toCheck) { return toCheck >= 'a' && toCheck <= 'z'; } /** - * A broken implementation of {@link Character#toLowerCase(char)} that assumes ASCII in order to - * be compatible with the old native implementation. + * A broken implementation of {@link Character#toLowerCase(char)} that assumes ASCII codes in + * order to be compatible with the old native implementation. */ private static char brokenToLower(char input) { if (input >= 'A' && input <= 'Z') { @@ -499,8 +487,8 @@ class TimeFormatter { } /** - * A broken implementation of {@link Character#toUpperCase(char)} that assumes ASCII in order to - * be compatible with the old native implementation. + * A broken implementation of {@link Character#toUpperCase(char)} that assumes ASCII codes in + * order to be compatible with the old native implementation. */ private static char brokenToUpper(char input) { if (input >= 'a' && input <= 'z') { @@ -509,11 +497,4 @@ class TimeFormatter { return input; } - /** - * Safely convert a byte containing an ASCII character to a char, even for character codes - * > 127. - */ - private static char convertToChar(byte b) { - return (char) (b & 0xFF); - } } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index eb93745ac29d..012a6aa00a5c 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2378,7 +2378,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te lp.itemId = mAdapter.getItemId(position); } lp.viewType = mAdapter.getItemViewType(position); - child.setLayoutParams(lp); + if (lp != vlp) { + child.setLayoutParams(lp); + } } class ListItemAccessibilityDelegate extends AccessibilityDelegate { diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java index 6ed3bdcb9b90..fc213c563e8e 100644 --- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java +++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java @@ -25,6 +25,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.os.storage.StorageVolume; import android.util.Log; /** @@ -94,6 +95,10 @@ public class ExternalMediaFormatActivity extends AlertActivity implements Dialog if (which == POSITIVE_BUTTON) { Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY); intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); + // Transfer the storage volume to the new intent + final StorageVolume storageVolume = getIntent().getParcelableExtra( + StorageVolume.EXTRA_STORAGE_VOLUME); + intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, storageVolume); startService(intent); } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 051de6e5d1f8..87e8ebdb49b6 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -91,12 +91,6 @@ public class ZygoteInit { private static Resources mResources; /** - * The number of times that the main Zygote loop - * should run before calling gc() again. - */ - static final int GC_LOOP_COUNT = 10; - - /** * The name of a resource file that contains classes to preload. */ private static final String PRELOADED_CLASSES = "preloaded-classes"; @@ -293,11 +287,6 @@ public class ZygoteInit { float defaultUtilization = runtime.getTargetHeapUtilization(); runtime.setTargetHeapUtilization(0.8f); - // Start with a clean slate. - System.gc(); - runtime.runFinalizationSync(); - Debug.startAllocCounting(); - try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); @@ -316,15 +305,6 @@ public class ZygoteInit { Log.v(TAG, "Preloading " + line + "..."); } Class.forName(line); - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, - " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } count++; } catch (ClassNotFoundException e) { Log.w(TAG, "Class not found for preloading: " + line); @@ -354,8 +334,6 @@ public class ZygoteInit { // Fill in dex caches with classes, fields, and methods brought in by preloading. runtime.preloadDexCaches(); - Debug.stopAllocCounting(); - // Bring back root. We'll need it later. setEffectiveUser(ROOT_UID); setEffectiveGroup(ROOT_GID); @@ -373,10 +351,7 @@ public class ZygoteInit { private static void preloadResources() { final VMRuntime runtime = VMRuntime.getRuntime(); - Debug.startAllocCounting(); try { - System.gc(); - runtime.runFinalizationSync(); mResources = Resources.getSystem(); mResources.startPreloading(); if (PRELOAD_RESOURCES) { @@ -401,22 +376,12 @@ public class ZygoteInit { mResources.finishPreloading(); } catch (RuntimeException e) { Log.w(TAG, "Failure preloading resources", e); - } finally { - Debug.stopAllocCounting(); } } private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) { int N = ar.length(); for (int i=0; i<N; i++) { - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } int id = ar.getResourceId(i, 0); if (false) { Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); @@ -437,14 +402,6 @@ public class ZygoteInit { private static int preloadDrawables(VMRuntime runtime, TypedArray ar) { int N = ar.length(); for (int i=0; i<N; i++) { - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } int id = ar.getResourceId(i, 0); if (false) { Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); @@ -466,7 +423,7 @@ public class ZygoteInit { * softly- and final-reachable objects, along with any other garbage. * This is only useful just before a fork(). */ - /*package*/ static void gc() { + /*package*/ static void gcAndFinalize() { final VMRuntime runtime = VMRuntime.getRuntime(); /* runFinalizationSync() lets finalizers be called in Zygote, @@ -475,9 +432,6 @@ public class ZygoteInit { System.gc(); runtime.runFinalizationSync(); System.gc(); - runtime.runFinalizationSync(); - System.gc(); - runtime.runFinalizationSync(); } /** @@ -668,7 +622,7 @@ public class ZygoteInit { SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup - gc(); + gcAndFinalize(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. @@ -737,27 +691,9 @@ public class ZygoteInit { fds.add(sServerSocket.getFileDescriptor()); peers.add(null); - int loopCount = GC_LOOP_COUNT; while (true) { int index; - /* - * Call gc() before we block in select(). - * It's work that has to be done anyway, and it's better - * to avoid making every child do it. It will also - * madvise() any free memory as a side-effect. - * - * Don't call it every time, because walking the entire - * heap is a lot of overhead to free a few hundred bytes. - */ - if (loopCount <= 0) { - gc(); - loopCount = GC_LOOP_COUNT; - } else { - loopCount--; - } - - try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); |