summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/SystemServiceRegistry.java4
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java34
-rw-r--r--core/java/android/content/Intent.java21
-rw-r--r--core/java/android/content/res/ColorStateList.java80
-rw-r--r--core/java/android/content/res/Resources.java17
-rw-r--r--core/java/android/hardware/fingerprint/Fingerprint.aidl (renamed from core/java/android/service/fingerprint/Fingerprint.aidl)2
-rw-r--r--core/java/android/hardware/fingerprint/Fingerprint.java (renamed from core/java/android/service/fingerprint/Fingerprint.java)2
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java (renamed from core/java/android/service/fingerprint/FingerprintManager.java)4
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintUtils.java (renamed from core/java/android/service/fingerprint/FingerprintUtils.java)2
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl (renamed from core/java/android/service/fingerprint/IFingerprintService.aidl)6
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl (renamed from core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl)2
-rw-r--r--core/java/android/net/Uri.java12
-rw-r--r--core/java/android/os/BatteryStats.java10
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/text/DynamicLayout.java13
-rw-r--r--core/java/android/text/Layout.java28
-rw-r--r--core/java/android/text/StaticLayout.java91
-rw-r--r--core/java/android/view/ViewGroup.java4
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java2
-rw-r--r--core/java/android/widget/DayPickerView.java4
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java6
-rw-r--r--core/java/android/widget/SimpleMonthView.java94
-rw-r--r--core/java/android/widget/TextView.java116
-rw-r--r--core/java/android/widget/TimePickerClockDelegate.java14
24 files changed, 408 insertions, 168 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index a0f40f6..b3aa6be 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -99,8 +99,8 @@ import android.os.Vibrator;
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
-import android.service.fingerprint.FingerprintManager;
-import android.service.fingerprint.IFingerprintService;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintService;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
import android.telecom.TelecomManager;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index be26eac..edb768d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
@@ -206,6 +207,23 @@ public final class BluetoothAdapter {
"android.bluetooth.adapter.action.REQUEST_ENABLE";
/**
+ * Activity Action: Show a system activity that allows user to enable BLE scans even when
+ * Bluetooth is turned off.<p>
+ *
+ * Notification of result of this activity is posted using
+ * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
+ * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
+ * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
+ * error occurred.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
+ "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
+
+ /**
* Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
* has changed.
* <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
@@ -916,6 +934,22 @@ public final class BluetoothAdapter {
}
/**
+ * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
+ *
+ * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
+ * fetch scan results even when Bluetooth is turned off.<p>
+ *
+ * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isBleScanAlwaysAvailable() {
+ // TODO: implement after Settings UI change.
+ return false;
+ }
+
+ /**
* Returns whether peripheral mode is supported.
*
* @hide
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7a99a79..514802e9 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1041,6 +1041,18 @@ public class Intent implements Parcelable, Cloneable {
*/
public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
/**
+ * Activity action: Activate the current SIM card. If SIM cards do not require activation,
+ * sending this intent is a no-op.
+ * <p>Input: No data should be specified. get*Extra may have an optional
+ * {@link #EXTRA_SIM_ACTIVATION_RESPONSE} field containing a PendingIntent through which to
+ * send the activation result.
+ * <p>Output: nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SIM_ACTIVATION_REQUEST =
+ "android.intent.action.SIM_ACTIVATION_REQUEST";
+ /**
* Activity Action: Send a message to someone specified by the data.
* <p>Input: {@link #getData} is URI describing the target.
* <p>Output: nothing.
@@ -3620,6 +3632,15 @@ public class Intent implements Parcelable, Cloneable {
/** {@hide} */
public static final String EXTRA_REASON = "android.intent.extra.REASON";
+ /**
+ * Optional {@link android.app.PendingIntent} extra used to deliver the result of the SIM
+ * activation request.
+ * TODO: Add information about the structure and response data used with the pending intent.
+ * @hide
+ */
+ public static final String EXTRA_SIM_ACTIVATION_RESPONSE =
+ "android.intent.extra.SIM_ACTIVATION_RESPONSE";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 7d8dff3..fdafb04 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -71,10 +71,15 @@ import java.util.Arrays;
*/
public class ColorStateList implements Parcelable {
private static final String TAG = "ColorStateList";
+
private static final int DEFAULT_COLOR = Color.RED;
private static final int[][] EMPTY = new int[][] { new int[0] };
- private static final SparseArray<WeakReference<ColorStateList>> sCache =
- new SparseArray<WeakReference<ColorStateList>>();
+
+ /** Thread-safe cache of single-color ColorStateLists. */
+ private static final SparseArray<WeakReference<ColorStateList>> sCache = new SparseArray<>();
+
+ /** Lazily-created factory for this color state list. */
+ private ColorStateListFactory mFactory;
private int[][] mThemeAttrs;
private int mChangingConfigurations;
@@ -125,7 +130,7 @@ public class ColorStateList implements Parcelable {
}
final ColorStateList csl = new ColorStateList(EMPTY, new int[] { color });
- sCache.put(color, new WeakReference<ColorStateList>(csl));
+ sCache.put(color, new WeakReference<>(csl));
return csl;
}
}
@@ -141,11 +146,13 @@ public class ColorStateList implements Parcelable {
*/
private ColorStateList(ColorStateList orig) {
if (orig != null) {
+ mChangingConfigurations = orig.mChangingConfigurations;
mStateSpecs = orig.mStateSpecs;
mDefaultColor = orig.mDefaultColor;
mIsOpaque = orig.mIsOpaque;
- // Deep copy, this may change due to theming.
+ // Deep copy, these may change due to applyTheme().
+ mThemeAttrs = orig.mThemeAttrs.clone();
mColors = orig.mColors.clone();
}
}
@@ -329,6 +336,7 @@ public class ColorStateList implements Parcelable {
* attributes.
*
* @return whether a theme can be applied to this color state list
+ * @hide only for resource preloading
*/
public boolean canApplyTheme() {
return mThemeAttrs != null;
@@ -336,10 +344,15 @@ public class ColorStateList implements Parcelable {
/**
* Applies a theme to this color state list.
+ * <p>
+ * <strong>Note:</strong> Applying a theme may affect the changing
+ * configuration parameters of this color state list. After calling this
+ * method, any dependent configurations must be updated by obtaining the
+ * new configuration mask from {@link #getChangingConfigurations()}.
*
* @param t the theme to apply
*/
- public void applyTheme(Theme t) {
+ private void applyTheme(Theme t) {
if (mThemeAttrs == null) {
return;
}
@@ -376,6 +389,38 @@ public class ColorStateList implements Parcelable {
onColorsChanged();
}
+ /**
+ * Returns an appropriately themed color state list.
+ *
+ * @param t the theme to apply
+ * @return a copy of the color state list with the theme applied, or the
+ * color state list itself if there were no unresolved theme
+ * attributes
+ * @hide only for resource preloading
+ */
+ public ColorStateList obtainForTheme(Theme t) {
+ if (t == null || !canApplyTheme()) {
+ return this;
+ }
+
+ final ColorStateList clone = new ColorStateList(this);
+ clone.applyTheme(t);
+ return clone;
+ }
+
+ /**
+ * Returns a mask of the configuration parameters for which this color
+ * state list may change, requiring that it be re-created.
+ *
+ * @return a mask of the changing configuration parameters, as defined by
+ * {@link android.content.pm.ActivityInfo}
+ *
+ * @see android.content.pm.ActivityInfo
+ */
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+
private int modulateColorAlpha(int baseColor, float alphaMod) {
if (alphaMod == 1.0f) {
return baseColor;
@@ -383,8 +428,7 @@ public class ColorStateList implements Parcelable {
final int baseAlpha = Color.alpha(baseColor);
final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
- final int color = (baseColor & 0xFFFFFF) | (alpha << 24);
- return color;
+ return (baseColor & 0xFFFFFF) | (alpha << 24);
}
/**
@@ -534,14 +578,18 @@ public class ColorStateList implements Parcelable {
}
/**
- * @return A factory that can create new instances of this ColorStateList.
+ * @return a factory that can create new instances of this ColorStateList
+ * @hide only for resource preloading
*/
- ColorStateListFactory getFactory() {
- return new ColorStateListFactory(this);
+ public ConstantState<ColorStateList> getConstantState() {
+ if (mFactory != null) {
+ mFactory = new ColorStateListFactory(this);
+ }
+ return mFactory;
}
- static class ColorStateListFactory extends ConstantState<ColorStateList> {
- final ColorStateList mSrc;
+ private static class ColorStateListFactory extends ConstantState<ColorStateList> {
+ private final ColorStateList mSrc;
public ColorStateListFactory(ColorStateList src) {
mSrc = src;
@@ -559,13 +607,7 @@ public class ColorStateList implements Parcelable {
@Override
public ColorStateList newInstance(Resources res, Theme theme) {
- if (theme == null || !mSrc.canApplyTheme()) {
- return mSrc;
- }
-
- final ColorStateList clone = new ColorStateList(mSrc);
- clone.applyTheme(theme);
- return clone;
+ return mSrc.obtainForTheme(theme);
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 44018ff..7ce3721 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -41,7 +41,6 @@ import android.annotation.RawRes;
import android.annotation.StringRes;
import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
-import android.content.res.ColorStateList.ColorStateListFactory;
import android.graphics.Movie;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -112,8 +111,8 @@ public class Resources {
private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
= new LongSparseArray<>();
- private static final LongSparseArray<ColorStateListFactory> sPreloadedColorStateLists
- = new LongSparseArray<>();
+ private static final LongSparseArray<android.content.res.ConstantState<ColorStateList>>
+ sPreloadedColorStateLists = new LongSparseArray<>();
// Pool of TypedArrays targeted to this Resources object.
final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
@@ -2667,7 +2666,8 @@ public class Resources {
// Handle inline color definitions.
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- final ColorStateListFactory factory = sPreloadedColorStateLists.get(key);
+ final android.content.res.ConstantState<ColorStateList> factory =
+ sPreloadedColorStateLists.get(key);
if (factory != null) {
return factory.newInstance();
}
@@ -2677,7 +2677,7 @@ public class Resources {
if (mPreloading) {
if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
"color")) {
- sPreloadedColorStateLists.put(key, csl.getFactory());
+ sPreloadedColorStateLists.put(key, csl.getConstantState());
}
}
@@ -2691,7 +2691,8 @@ public class Resources {
return csl;
}
- final ColorStateListFactory factory = sPreloadedColorStateLists.get(key);
+ final android.content.res.ConstantState<ColorStateList> factory =
+ sPreloadedColorStateLists.get(key);
if (factory != null) {
csl = factory.newInstance(this, theme);
}
@@ -2704,10 +2705,10 @@ public class Resources {
if (mPreloading) {
if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
"color")) {
- sPreloadedColorStateLists.put(key, csl.getFactory());
+ sPreloadedColorStateLists.put(key, csl.getConstantState());
}
} else {
- cache.put(key, theme, csl.getFactory());
+ cache.put(key, theme, csl.getConstantState());
}
}
diff --git a/core/java/android/service/fingerprint/Fingerprint.aidl b/core/java/android/hardware/fingerprint/Fingerprint.aidl
index c9fd989..4743354 100644
--- a/core/java/android/service/fingerprint/Fingerprint.aidl
+++ b/core/java/android/hardware/fingerprint/Fingerprint.aidl
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
// @hide
parcelable Fingerprint;
diff --git a/core/java/android/service/fingerprint/Fingerprint.java b/core/java/android/hardware/fingerprint/Fingerprint.java
index 37552eb..c307634 100644
--- a/core/java/android/service/fingerprint/Fingerprint.java
+++ b/core/java/android/hardware/fingerprint/Fingerprint.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index bb90e40..e3572a2 100644
--- a/core/java/android/service/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
import android.app.ActivityManagerNative;
import android.content.ContentResolver;
@@ -28,7 +28,7 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
import android.util.Log;
import android.util.Slog;
diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/hardware/fingerprint/FingerprintUtils.java
index 62acbb9..ae3d4a4 100644
--- a/core/java/android/service/fingerprint/FingerprintUtils.java
+++ b/core/java/android/hardware/fingerprint/FingerprintUtils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
import android.content.ContentResolver;
import android.provider.Settings;
diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index e5d3ad4..c5a45e2 100644
--- a/core/java/android/service/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
import android.os.Bundle;
-import android.service.fingerprint.IFingerprintServiceReceiver;
-import android.service.fingerprint.Fingerprint;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.Fingerprint;
import java.util.List;
/**
diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
index f025064..e82395f 100644
--- a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.fingerprint;
+package android.hardware.fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index bf3d9aa..f305b2a 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -366,7 +366,6 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
public String toSafeString() {
String scheme = getScheme();
String ssp = getSchemeSpecificPart();
- String authority = null;
if (scheme != null) {
if (scheme.equalsIgnoreCase("tel") || scheme.equalsIgnoreCase("sip")
|| scheme.equalsIgnoreCase("sms") || scheme.equalsIgnoreCase("smsto")
@@ -385,9 +384,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
}
}
return builder.toString();
- } else if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
- ssp = null;
- authority = "//" + getAuthority() + "/...";
+ } else if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")
+ || scheme.equalsIgnoreCase("ftp")) {
+ ssp = "//" + ((getHost() != null) ? getHost() : "")
+ + ((getPort() != -1) ? (":" + getPort()) : "")
+ + "/...";
}
}
// Not a sensitive scheme, but let's still be conservative about
@@ -401,9 +402,6 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
if (ssp != null) {
builder.append(ssp);
}
- if (authority != null) {
- builder.append(authority);
- }
return builder.toString();
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8b3ecae..508fdee 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4415,7 +4415,7 @@ public abstract class BatteryStats implements Parcelable {
if (!checkin) {
pw.println(header);
}
- String[] lineArgs = new String[4];
+ String[] lineArgs = new String[5];
for (int i=0; i<count; i++) {
long duration = steps.getDurationAt(i);
int level = steps.getLevelAt(i);
@@ -4430,7 +4430,7 @@ public abstract class BatteryStats implements Parcelable {
case Display.STATE_ON: lineArgs[2] = "s+"; break;
case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
- default: lineArgs[1] = "?"; break;
+ default: lineArgs[2] = "?"; break;
}
} else {
lineArgs[2] = "";
@@ -4441,9 +4441,9 @@ public abstract class BatteryStats implements Parcelable {
lineArgs[3] = "";
}
if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
- lineArgs[3] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
+ lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
} else {
- lineArgs[3] = "";
+ lineArgs[4] = "";
}
dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
} else {
@@ -4459,7 +4459,7 @@ public abstract class BatteryStats implements Parcelable {
case Display.STATE_ON: pw.print("screen-on"); break;
case Display.STATE_DOZE: pw.print("screen-doze"); break;
case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
- default: lineArgs[1] = "screen-?"; break;
+ default: pw.print("screen-?"); break;
}
haveModes = true;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8e5d245..f79ef35 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6375,6 +6375,14 @@ public final class Settings {
"wifi_scan_always_enabled";
/**
+ * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
+ * connectivity.
+ * @hide
+ */
+ public static final String BLE_SCAN_ALWAYS_AVAILABLE =
+ "ble_scan_always_enabled";
+
+ /**
* Used to save the Wifi_ON state prior to tethering.
* This state will be checked to restore Wifi after
* the user turns off tethering.
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 7d2e1ef..239b386 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -79,7 +79,8 @@ public class DynamicLayout extends Layout
boolean includepad,
TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
- spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+ spacingmult, spacingadd, includepad, StaticLayout.BREAK_STRATEGY_SIMPLE,
+ ellipsize, ellipsizedWidth);
}
/**
@@ -95,7 +96,7 @@ public class DynamicLayout extends Layout
TextPaint paint,
int width, Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
- boolean includepad,
+ boolean includepad, int breakStrategy,
TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
super((ellipsize == null)
? display
@@ -120,6 +121,7 @@ public class DynamicLayout extends Layout
mObjects = new PackedObjectVector<Directions>(1);
mIncludePad = includepad;
+ mBreakStrategy = breakStrategy;
/*
* This is annoying, but we can't refer to the layout until
@@ -279,10 +281,9 @@ public class DynamicLayout extends Layout
sBuilder = null;
}
- // TODO: make sure reflowed is properly initialized
if (reflowed == null) {
reflowed = new StaticLayout(null);
- b = StaticLayout.Builder.obtain();
+ b = StaticLayout.Builder.obtain(text, where, where + after, getWidth());
}
b.setText(text, where, where + after)
@@ -292,7 +293,8 @@ public class DynamicLayout extends Layout
.setSpacingMult(getSpacingMultiplier())
.setSpacingAdd(getSpacingAdd())
.setEllipsizedWidth(mEllipsizedWidth)
- .setEllipsize(mEllipsizeAt);
+ .setEllipsize(mEllipsizeAt)
+ .setBreakStrategy(mBreakStrategy);
reflowed.generate(b, false, true);
int n = reflowed.getLineCount();
@@ -717,6 +719,7 @@ public class DynamicLayout extends Layout
private boolean mEllipsize;
private int mEllipsizedWidth;
private TextUtils.TruncateAt mEllipsizeAt;
+ private int mBreakStrategy;
private PackedIntVector mInts;
private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 22abb18..16ae5e2 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -16,6 +16,7 @@
package android.text;
+import android.annotation.IntDef;
import android.emoji.EmojiFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -33,6 +34,8 @@ import android.text.style.TabStopSpan;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/**
@@ -43,6 +46,31 @@ import java.util.Arrays;
* For text that will not change, use a {@link StaticLayout}.
*/
public abstract class Layout {
+ /** @hide */
+ @IntDef({BREAK_STRATEGY_SIMPLE, BREAK_STRATEGY_HIGH_QUALITY, BREAK_STRATEGY_BALANCED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BreakStrategy {}
+
+ /**
+ * Value for break strategy indicating simple line breaking. Automatic hyphens are not added
+ * (though soft hyphens are respected), and modifying text generally doesn't affect the layout
+ * before it (which yields a more consistent user experience when editing), but layout may not
+ * be the highest quality.
+ */
+ public static final int BREAK_STRATEGY_SIMPLE = 0;
+
+ /**
+ * Value for break strategy indicating high quality line breaking, including automatic
+ * hyphenation and doing whole-paragraph optimization of line breaks.
+ */
+ public static final int BREAK_STRATEGY_HIGH_QUALITY = 1;
+
+ /**
+ * Value for break strategy indicating balanced line breaking. The breaks are chosen to
+ * make all lines as close to the same length as possible, including automatic hyphenation.
+ */
+ public static final int BREAK_STRATEGY_BALANCED = 2;
+
private static final ParagraphStyle[] NO_PARA_SPANS =
ArrayUtils.emptyArray(ParagraphStyle.class);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 4174df0..2bcb352 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -23,6 +23,7 @@ import android.text.style.LineHeightSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.TabStopSpan;
import android.util.Log;
+import android.util.Pools.SynchronizedPool;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
@@ -56,28 +57,23 @@ public class StaticLayout extends Layout {
mNativePtr = nNewBuilder();
}
- static Builder obtain() {
- Builder b = null;
- synchronized (sLock) {
- for (int i = 0; i < sCached.length; i++) {
- if (sCached[i] != null) {
- b = sCached[i];
- sCached[i] = null;
- break;
- }
- }
- }
+ public static Builder obtain(CharSequence source, int start, int end, int width) {
+ Builder b = sPool.acquire();
if (b == null) {
b = new Builder();
}
// set default initial values
- b.mWidth = 0;
+ b.mText = source;
+ b.mStart = start;
+ b.mEnd = end;
+ b.mWidth = width;
+ b.mAlignment = Alignment.ALIGN_NORMAL;
b.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
b.mSpacingMult = 1.0f;
b.mSpacingAdd = 0.0f;
b.mIncludePad = true;
- b.mEllipsizedWidth = 0;
+ b.mEllipsizedWidth = width;
b.mEllipsize = null;
b.mMaxLines = Integer.MAX_VALUE;
@@ -85,18 +81,11 @@ public class StaticLayout extends Layout {
return b;
}
- static void recycle(Builder b) {
+ private static void recycle(Builder b) {
b.mPaint = null;
b.mText = null;
MeasuredText.recycle(b.mMeasuredText);
- synchronized (sLock) {
- for (int i = 0; i < sCached.length; i++) {
- if (sCached[i] == null) {
- sCached[i] = b;
- break;
- }
- }
- }
+ sPool.release(b);
}
// release any expensive state
@@ -129,6 +118,11 @@ public class StaticLayout extends Layout {
return this;
}
+ public Builder setAlignment(Alignment alignment) {
+ mAlignment = alignment;
+ return this;
+ }
+
public Builder setTextDir(TextDirectionHeuristic textDir) {
mTextDir = textDir;
return this;
@@ -166,6 +160,11 @@ public class StaticLayout extends Layout {
return this;
}
+ public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
+ mBreakStrategy = breakStrategy;
+ return this;
+ }
+
/**
* Measurement and break iteration is done in native code. The protocol for using
* the native code is as follows.
@@ -207,10 +206,8 @@ public class StaticLayout extends Layout {
}
public StaticLayout build() {
- // TODO: can optimize based on whether ellipsis is needed
- StaticLayout result = new StaticLayout(mText);
- result.generate(this, this.mIncludePad, this.mIncludePad);
- recycle(this);
+ StaticLayout result = new StaticLayout(this);
+ Builder.recycle(this);
return result;
}
@@ -230,6 +227,7 @@ public class StaticLayout extends Layout {
int mEnd;
TextPaint mPaint;
int mWidth;
+ Alignment mAlignment;
TextDirectionHeuristic mTextDir;
float mSpacingMult;
float mSpacingAdd;
@@ -237,6 +235,7 @@ public class StaticLayout extends Layout {
int mEllipsizedWidth;
TextUtils.TruncateAt mEllipsize;
int mMaxLines;
+ int mBreakStrategy;
Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
@@ -245,8 +244,7 @@ public class StaticLayout extends Layout {
Locale mLocale;
- private static final Object sLock = new Object();
- private static final Builder[] sCached = new Builder[3];
+ private static final SynchronizedPool<Builder> sPool = new SynchronizedPool<Builder>(3);
}
public StaticLayout(CharSequence source, TextPaint paint,
@@ -316,10 +314,9 @@ public class StaticLayout extends Layout {
: new Ellipsizer(source),
paint, outerwidth, align, textDir, spacingmult, spacingadd);
- Builder b = Builder.obtain();
- b.setText(source, bufstart, bufend)
+ Builder b = Builder.obtain(source, bufstart, bufend, outerwidth)
.setPaint(paint)
- .setWidth(outerwidth)
+ .setAlignment(align)
.setTextDir(textDir)
.setSpacingMult(spacingmult)
.setSpacingAdd(spacingadd)
@@ -366,6 +363,35 @@ public class StaticLayout extends Layout {
mLines = new int[mLineDirections.length];
}
+ private StaticLayout(Builder b) {
+ super((b.mEllipsize == null)
+ ? b.mText
+ : (b.mText instanceof Spanned)
+ ? new SpannedEllipsizer(b.mText)
+ : new Ellipsizer(b.mText),
+ b.mPaint, b.mWidth, b.mAlignment, b.mSpacingMult, b.mSpacingAdd);
+
+ if (b.mEllipsize != null) {
+ Ellipsizer e = (Ellipsizer) getText();
+
+ e.mLayout = this;
+ e.mWidth = b.mEllipsizedWidth;
+ e.mMethod = b.mEllipsize;
+ mEllipsizedWidth = b.mEllipsizedWidth;
+
+ mColumns = COLUMNS_ELLIPSIZE;
+ } else {
+ mColumns = COLUMNS_NORMAL;
+ mEllipsizedWidth = b.mWidth;
+ }
+
+ mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+ mLines = new int[mLineDirections.length];
+ mMaximumVisibleLineCount = b.mMaxLines;
+
+ generate(b, b.mIncludePad, b.mIncludePad);
+ }
+
/* package */ void generate(Builder b, boolean includepad, boolean trackpad) {
CharSequence source = b.mText;
int bufStart = b.mStart;
@@ -477,10 +503,9 @@ public class StaticLayout extends Layout {
}
}
- int breakStrategy = 0; // 0 = kBreakStrategy_Greedy
nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
firstWidth, firstWidthLineCount, restWidth,
- variableTabStops, TAB_INCREMENT, breakStrategy);
+ variableTabStops, TAB_INCREMENT, b.mBreakStrategy);
// measurement has to be done before performing line breaking
// but we don't want to recompute fontmetrics or span ranges the
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 87f3e94..31c3fe8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5727,12 +5727,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
- resultSize = 0;
+ resultSize = size;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
- resultSize = 0;
+ resultSize = size;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 77082b0..ec527d5 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1562,7 +1562,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Sets whether this node is visible to the user.
+ * Gets whether this node is visible to the user.
*
* @return Whether the node is visible to the user.
*/
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index e2f8efc..ec2528f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -187,7 +187,6 @@ class DayPickerView extends ViewPager {
* @param setSelected whether to set the specified day as selected
*/
private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
- // Set the selected day
if (setSelected) {
mSelectedDay.setTimeInMillis(timeInMillis);
}
@@ -196,6 +195,9 @@ class DayPickerView extends ViewPager {
if (position != getCurrentItem()) {
setCurrentItem(position, animate);
}
+
+ mTempCalendar.setTimeInMillis(timeInMillis);
+ mAdapter.setSelectedDay(mTempCalendar);
}
public long getDate() {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 349f3f0..a50941b 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -815,12 +815,12 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
mContext = context;
mIntent = intent;
- mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1);
-
- mLayoutInflater = LayoutInflater.from(context);
if (mIntent == null) {
throw new IllegalArgumentException("Non-null Intent must be specified.");
}
+
+ mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1);
+ mLayoutInflater = LayoutInflater.from(context);
mRequestedViews = new RemoteViewsFrameLayoutRefSet();
// Strip the previously injected app widget id from service intent
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 3fb096c..d9f1f0e 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -80,11 +80,12 @@ class SimpleMonthView extends View {
private final SimpleDateFormat mTitleFormatter;
private final SimpleDateFormat mDayOfWeekFormatter;
- private final int mMonthHeight;
- private final int mDayOfWeekHeight;
- private final int mDayHeight;
- private final int mCellWidth;
- private final int mDaySelectorRadius;
+ // Desired dimensions.
+ private final int mDesiredMonthHeight;
+ private final int mDesiredDayOfWeekHeight;
+ private final int mDesiredDayHeight;
+ private final int mDesiredCellWidth;
+ private final int mDesiredDaySelectorRadius;
// Next/previous drawables.
private final Drawable mPrevDrawable;
@@ -99,6 +100,13 @@ class SimpleMonthView extends View {
private int mMonth;
private int mYear;
+ // Dimensions as laid out.
+ private int mMonthHeight;
+ private int mDayOfWeekHeight;
+ private int mDayHeight;
+ private int mCellWidth;
+ private int mDaySelectorRadius;
+
private int mPaddedWidth;
private int mPaddedHeight;
@@ -158,11 +166,11 @@ class SimpleMonthView extends View {
super(context, attrs, defStyleAttr, defStyleRes);
final Resources res = context.getResources();
- mMonthHeight = res.getDimensionPixelSize(R.dimen.date_picker_month_height);
- mDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
- mDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
- mCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
- mDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
+ mDesiredMonthHeight = res.getDimensionPixelSize(R.dimen.date_picker_month_height);
+ mDesiredDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
+ mDesiredDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
+ mDesiredCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
+ mDesiredDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
mPrevDrawable = context.getDrawable(R.drawable.ic_chevron_left);
mNextDrawable = context.getDrawable(R.drawable.ic_chevron_right);
@@ -400,7 +408,7 @@ class SimpleMonthView extends View {
final TextPaint p = mDayOfWeekPaint;
final int headerHeight = mMonthHeight;
final int rowHeight = mDayOfWeekHeight;
- final int colWidth = mPaddedWidth / DAYS_IN_WEEK;
+ final int colWidth = mCellWidth;
// Text is vertically centered within the day of week height.
final float halfLineHeight = (p.ascent() + p.descent()) / 2f;
@@ -426,7 +434,7 @@ class SimpleMonthView extends View {
final TextPaint p = mDayPaint;
final int headerHeight = mMonthHeight + mDayOfWeekHeight;
final int rowHeight = mDayHeight;
- final int colWidth = mPaddedWidth / DAYS_IN_WEEK;
+ final int colWidth = mCellWidth;
// Text is vertically centered within the row height.
final float halfLineHeight = (p.ascent() + p.descent()) / 2f;
@@ -627,9 +635,9 @@ class SimpleMonthView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int preferredHeight = mDayHeight * mNumWeeks + mDayOfWeekHeight + mMonthHeight
- + getPaddingTop() + getPaddingBottom();
- final int preferredWidth = mCellWidth * DAYS_IN_WEEK
+ final int preferredHeight = mDesiredDayHeight * mNumWeeks + mDesiredDayOfWeekHeight
+ + mDesiredMonthHeight + getPaddingTop() + getPaddingBottom();
+ final int preferredWidth = mDesiredCellWidth * DAYS_IN_WEEK
+ getPaddingStart() + getPaddingEnd();
final int resolvedWidth = resolveSize(preferredWidth, widthMeasureSpec);
final int resolvedHeight = resolveSize(preferredHeight, heightMeasureSpec);
@@ -637,16 +645,46 @@ class SimpleMonthView extends View {
}
@Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- final int paddedLeft = getPaddingLeft();
- final int paddedTop = getPaddingTop();
- final int paddedRight = w - getPaddingRight();
- final int paddedBottom = h - getPaddingBottom();
- mPaddedWidth = paddedRight - paddedLeft;
- mPaddedHeight = paddedBottom - paddedTop;
-
- final int monthHeight = mMonthHeight;
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (!changed) {
+ return;
+ }
+
+ // Let's initialize a completely reasonable number of variables.
+ final int w = right - left;
+ final int h = bottom - top;
+ final int paddingLeft = getPaddingLeft();
+ final int paddingTop = getPaddingTop();
+ final int paddingRight = getPaddingRight();
+ final int paddingBottom = getPaddingBottom();
+ final int paddedRight = w - paddingRight;
+ final int paddedBottom = h - paddingBottom;
+ final int paddedWidth = paddedRight - paddingLeft;
+ final int paddedHeight = paddedBottom - paddingTop;
+ if (paddedWidth == mPaddedWidth || paddedHeight == mPaddedHeight) {
+ return;
+ }
+
+ mPaddedWidth = paddedWidth;
+ mPaddedHeight = paddedHeight;
+
+ // We may have been laid out smaller than our preferred size. If so,
+ // scale all dimensions to fit.
+ final int measuredPaddedHeight = getMeasuredHeight() - paddingTop - paddingBottom;
+ final float scaleH = paddedHeight / (float) measuredPaddedHeight;
+ final int monthHeight = (int) (mDesiredMonthHeight * scaleH);
final int cellWidth = mPaddedWidth / DAYS_IN_WEEK;
+ mMonthHeight = monthHeight;
+ mDayOfWeekHeight = (int) (mDesiredDayOfWeekHeight * scaleH);
+ mDayHeight = (int) (mDesiredDayHeight * scaleH);
+ mCellWidth = cellWidth;
+
+ // Compute the largest day selector radius that's still within the clip
+ // bounds and desired selector radius.
+ final int maxSelectorWidth = cellWidth / 2 + Math.min(paddingLeft, paddingRight);
+ final int maxSelectorHeight = mDayHeight / 2 + paddingBottom;
+ mDaySelectorRadius = Math.min(mDesiredDaySelectorRadius,
+ Math.min(maxSelectorWidth, maxSelectorHeight));
// Vertically center the previous/next drawables within the month
// header, horizontally center within the day cell, then expand the
@@ -660,7 +698,7 @@ class SimpleMonthView extends View {
// Button bounds don't include padding, but hit area does.
prevDrawable.setBounds(iconLeft, iconTop, iconLeft + dW, iconTop + dH);
- mPrevHitArea.set(0, 0, paddedLeft + cellWidth, paddedTop + monthHeight);
+ mPrevHitArea.set(0, 0, paddingLeft + cellWidth, paddingTop + monthHeight);
}
final Drawable nextDrawable = mNextDrawable;
@@ -668,11 +706,11 @@ class SimpleMonthView extends View {
final int dW = nextDrawable.getIntrinsicWidth();
final int dH = nextDrawable.getIntrinsicHeight();
final int iconTop = (monthHeight - dH) / 2;
- final int iconRight = mPaddedWidth - (cellWidth - dW) / 2;
+ final int iconRight = paddedWidth - (cellWidth - dW) / 2;
// Button bounds don't include padding, but hit area does.
nextDrawable.setBounds(iconRight - dW, iconTop, iconRight, iconTop + dH);
- mNextHitArea.set(paddedRight - cellWidth, 0, w, paddedTop + monthHeight);
+ mNextHitArea.set(paddedRight - cellWidth, 0, w, paddingTop + monthHeight);
}
// Invalidate cached accessibility information.
@@ -753,7 +791,7 @@ class SimpleMonthView extends View {
// Compute left edge.
final int col = index % DAYS_IN_WEEK;
- final int colWidth = mPaddedWidth / DAYS_IN_WEEK;
+ final int colWidth = mCellWidth;
final int left = getPaddingLeft() + col * colWidth;
// Compute top edge.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 718ef93..2723080 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -543,6 +543,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private float mSpacingMult = 1.0f;
private float mSpacingAdd = 0.0f;
+ private int mBreakStrategy;
+
private int mMaximum = Integer.MAX_VALUE;
private int mMaxMode = LINES;
private int mMinimum = 0;
@@ -680,6 +682,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean elegant = false;
float letterSpacing = 0;
String fontFeatureSettings = null;
+ mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
final Resources.Theme theme = context.getTheme();
@@ -1133,6 +1136,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case com.android.internal.R.styleable.TextView_fontFeatureSettings:
fontFeatureSettings = a.getString(attr);
break;
+
+ case com.android.internal.R.styleable.TextView_breakStrategy:
+ mBreakStrategy = a.getInt(attr, Layout.BREAK_STRATEGY_SIMPLE);
}
}
a.recycle();
@@ -2960,6 +2966,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Sets the break strategy for breaking paragraphs into lines. The default value for
+ * TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for
+ * EditText is {@link Layout#BREAK_STRATEGY_SIMPLE}, the latter to avoid the
+ * text "dancing" when being edited.
+ *
+ * @attr ref android.R.styleable#TextView_breakStrategy
+ * @see #getBreakStrategy()
+ */
+ public void setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
+ mBreakStrategy = breakStrategy;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
+ }
+
+ /**
+ * @return the currently set break strategy.
+ *
+ * @attr ref android.R.styleable#TextView_breakStrategy
+ * @see #setBreakStrategy(int)
+ */
+ @Layout.BreakStrategy
+ public int getBreakStrategy() {
+ return mBreakStrategy;
+ }
+
+ /**
* Sets font feature settings. The format is the same as the CSS
* font-feature-settings attribute:
* http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
@@ -6492,27 +6527,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
hintBoring, mIncludePad, mEllipsize,
ellipsisWidth);
}
- } else if (shouldEllipsize) {
- mHintLayout = new StaticLayout(mHint,
- 0, mHint.length(),
- mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
}
- } else if (shouldEllipsize) {
- mHintLayout = new StaticLayout(mHint,
- 0, mHint.length(),
- mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
+ }
+ // TODO: code duplication with makeSingleLayout()
+ if (mHintLayout == null) {
+ StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,
+ mHint.length(), hintWidth)
+ .setPaint(mTextPaint)
+ .setAlignment(alignment)
+ .setTextDir(mTextDir)
+ .setSpacingMult(mSpacingMult)
+ .setSpacingAdd(mSpacingAdd)
+ .setIncludePad(mIncludePad)
+ .setBreakStrategy(mBreakStrategy);
+ if (shouldEllipsize) {
+ builder.setEllipsize(mEllipsize)
+ .setEllipsizedWidth(ellipsisWidth)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ }
+ mHintLayout = builder.build();
}
}
@@ -6544,9 +6577,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Layout result = null;
if (mText instanceof Spannable) {
result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
- alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, getKeyListener() == null ? effectiveEllipsize : null,
- ellipsisWidth);
+ alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, mBreakStrategy,
+ getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
} else {
if (boring == UNKNOWN_BORING) {
boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
@@ -6583,29 +6615,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boring, mIncludePad, effectiveEllipsize,
ellipsisWidth);
}
- } else if (shouldEllipsize) {
- result = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, wantWidth, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, effectiveEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- result = new StaticLayout(mTransformed, mTextPaint,
- wantWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
}
- } else if (shouldEllipsize) {
- result = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, wantWidth, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, effectiveEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- result = new StaticLayout(mTransformed, mTextPaint,
- wantWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
}
}
+ if (result == null) {
+ StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
+ 0, mTransformed.length(), wantWidth)
+ .setPaint(mTextPaint)
+ .setAlignment(alignment)
+ .setTextDir(mTextDir)
+ .setSpacingMult(mSpacingMult)
+ .setSpacingAdd(mSpacingAdd)
+ .setIncludePad(mIncludePad)
+ .setBreakStrategy(mBreakStrategy);
+ if (shouldEllipsize) {
+ builder.setEllipsize(effectiveEllipsize)
+ .setEllipsizedWidth(ellipsisWidth)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ }
+ // TODO: explore always setting maxLines
+ result = builder.build();
+ }
return result;
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index c58d5cb..2365b48 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -25,8 +25,10 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
+import android.text.style.TtsSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.util.StateSet;
@@ -155,13 +157,16 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
mHourView.setMinWidth(computeStableWidth(mHourView, 24));
mMinuteView.setMinWidth(computeStableWidth(mMinuteView, 60));
+ final SpannableStringBuilder amLabel = new SpannableStringBuilder()
+ .append(amPmStrings[0], new TtsSpan.VerbatimBuilder(amPmStrings[0]).build(), 0);
+
// Set up AM/PM labels.
mAmPmLayout = mainView.findViewById(R.id.ampm_layout);
mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
- mAmLabel.setText(amPmStrings[0]);
+ mAmLabel.setText(obtainVerbatim(amPmStrings[0]));
mAmLabel.setOnClickListener(mClickListener);
mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
- mPmLabel.setText(amPmStrings[1]);
+ mPmLabel.setText(obtainVerbatim(amPmStrings[1]));
mPmLabel.setOnClickListener(mClickListener);
// For the sake of backwards compatibility, attempt to extract the text
@@ -220,6 +225,11 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
}
+ private static final CharSequence obtainVerbatim(String text) {
+ return new SpannableStringBuilder().append(text,
+ new TtsSpan.VerbatimBuilder(text).build(), 0);
+ }
+
/**
* The legacy text color might have been poorly defined. Ensures that it
* has an appropriate activated state, using the selected state if one