Skip to content

Commit 59dfce8

Browse files
author
Fabrice Di Meglio
committed
Fix bug #6140391 Make RTL awareness as an opt-in into the AndroidManifest
- introduce "supportsRtl" as a new application attribute in the AndroidManifest - "supportsRtl" default value is FALSE (no RTL support) - adapt the View layoutDirection and textDirection logic to take care of "supportsRtl" value Change-Id: I5e4f9f576e14f35dedc6b0c29a7142c397f598e0
1 parent 4a52688 commit 59dfce8

File tree

7 files changed

+112
-63
lines changed

7 files changed

+112
-63
lines changed

api/current.txt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ package android {
596596
field public static final int layerType = 16843604; // 0x1010354
597597
field public static final int layout = 16842994; // 0x10100f2
598598
field public static final int layoutAnimation = 16842988; // 0x10100ec
599-
field public static final int layoutDirection = 16843689; // 0x10103a9
599+
field public static final int layoutDirection = 16843690; // 0x10103aa
600600
field public static final int layout_above = 16843140; // 0x1010184
601601
field public static final int layout_alignBaseline = 16843142; // 0x1010186
602602
field public static final int layout_alignBottom = 16843146; // 0x101018a
@@ -618,10 +618,10 @@ package android {
618618
field public static final int layout_height = 16842997; // 0x10100f5
619619
field public static final int layout_margin = 16842998; // 0x10100f6
620620
field public static final int layout_marginBottom = 16843002; // 0x10100fa
621-
field public static final int layout_marginEnd = 16843693; // 0x10103ad
621+
field public static final int layout_marginEnd = 16843694; // 0x10103ae
622622
field public static final int layout_marginLeft = 16842999; // 0x10100f7
623623
field public static final int layout_marginRight = 16843001; // 0x10100f9
624-
field public static final int layout_marginStart = 16843692; // 0x10103ac
624+
field public static final int layout_marginStart = 16843693; // 0x10103ad
625625
field public static final int layout_marginTop = 16843000; // 0x10100f8
626626
field public static final int layout_row = 16843643; // 0x101037b
627627
field public static final int layout_rowSpan = 16843644; // 0x101037c
@@ -717,10 +717,10 @@ package android {
717717
field public static final int packageNames = 16843649; // 0x1010381
718718
field public static final int padding = 16842965; // 0x10100d5
719719
field public static final int paddingBottom = 16842969; // 0x10100d9
720-
field public static final int paddingEnd = 16843691; // 0x10103ab
720+
field public static final int paddingEnd = 16843692; // 0x10103ac
721721
field public static final int paddingLeft = 16842966; // 0x10100d6
722722
field public static final int paddingRight = 16842968; // 0x10100d8
723-
field public static final int paddingStart = 16843690; // 0x10103aa
723+
field public static final int paddingStart = 16843691; // 0x10103ab
724724
field public static final int paddingTop = 16842967; // 0x10100d7
725725
field public static final int panelBackground = 16842846; // 0x101005e
726726
field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -931,6 +931,7 @@ package android {
931931
field public static final int summaryColumn = 16843426; // 0x10102a2
932932
field public static final int summaryOff = 16843248; // 0x10101f0
933933
field public static final int summaryOn = 16843247; // 0x10101ef
934+
field public static final int supportsRtl = 16843688; // 0x10103a8
934935
field public static final int supportsUploading = 16843419; // 0x101029b
935936
field public static final int switchMinWidth = 16843632; // 0x1010370
936937
field public static final int switchPadding = 16843633; // 0x1010371
@@ -1000,7 +1001,7 @@ package android {
10001001
field public static final int textColorTertiary = 16843282; // 0x1010212
10011002
field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
10021003
field public static final int textCursorDrawable = 16843618; // 0x1010362
1003-
field public static final int textDirection = 16843688; // 0x10103a8
1004+
field public static final int textDirection = 16843689; // 0x10103a9
10041005
field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
10051006
field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
10061007
field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -6131,6 +6132,7 @@ package android.content.pm {
61316132
field public static final int FLAG_STOPPED = 2097152; // 0x200000
61326133
field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
61336134
field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
6135+
field public static final int FLAG_SUPPORTS_RTL = 1073741824; // 0x40000000
61346136
field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
61356137
field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
61366138
field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000

core/java/android/content/pm/ApplicationInfo.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
290290
*/
291291
public static final int FLAG_STOPPED = 1<<21;
292292

293+
/**
294+
* Value for {@link #flags}: true when the application is willing to support
295+
* RTL (right to left). All activities will inherit this value.
296+
*
297+
* Set from the {@link android.R.attr#supportsRtl} attribute in the
298+
* activity's manifest.
299+
*
300+
* Default value is false (no support for RTL).
301+
*/
302+
public static final int FLAG_SUPPORTS_RTL = 1<<22;
303+
293304
/**
294305
* Value for {@link #flags}: Set to true if the application has been
295306
* installed using the forward lock option.
@@ -466,8 +477,17 @@ public void dump(Printer pw, String prefix) {
466477
if (uiOptions != 0) {
467478
pw.println(prefix + "uiOptions=0x" + Integer.toHexString(uiOptions));
468479
}
480+
pw.println(prefix + "supportsRtl=" + (hasRtlSupport() ? "true" : "false"));
469481
super.dumpBack(pw, prefix);
470482
}
483+
484+
/**
485+
* @return true if "supportsRtl" has been set to true in the AndroidManifest
486+
* @hide
487+
*/
488+
public boolean hasRtlSupport() {
489+
return (flags & FLAG_SUPPORTS_RTL) == FLAG_SUPPORTS_RTL;
490+
}
471491

472492
public static class DisplayNameComparator
473493
implements Comparator<ApplicationInfo> {

core/java/android/content/pm/PackageParser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,12 @@ private boolean parseApplication(Package owner, Resources res,
17611761
ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
17621762
}
17631763

1764+
if (sa.getBoolean(
1765+
com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
1766+
false /* default is no RTL support*/)) {
1767+
ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
1768+
}
1769+
17641770
String str;
17651771
str = sa.getNonConfigurationString(
17661772
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);

core/java/android/view/View.java

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9864,6 +9864,13 @@ void dispatchScreenStateChanged(int screenState) {
98649864
public void onScreenStateChanged(int screenState) {
98659865
}
98669866

9867+
/**
9868+
* Return true if the application tag in the AndroidManifest has set "supportRtl" to true
9869+
*/
9870+
private boolean hasRtlSupport() {
9871+
return mContext.getApplicationInfo().hasRtlSupport();
9872+
}
9873+
98679874
/**
98689875
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
98699876
* that the parent directionality can and will be resolved before its children.
@@ -9873,30 +9880,32 @@ public void resolveLayoutDirection() {
98739880
// Clear any previous layout direction resolution
98749881
mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
98759882

9876-
// Set resolved depending on layout direction
9877-
switch (getLayoutDirection()) {
9878-
case LAYOUT_DIRECTION_INHERIT:
9879-
// If this is root view, no need to look at parent's layout dir.
9880-
if (canResolveLayoutDirection()) {
9881-
ViewGroup viewGroup = ((ViewGroup) mParent);
9883+
if (hasRtlSupport()) {
9884+
// Set resolved depending on layout direction
9885+
switch (getLayoutDirection()) {
9886+
case LAYOUT_DIRECTION_INHERIT:
9887+
// If this is root view, no need to look at parent's layout dir.
9888+
if (canResolveLayoutDirection()) {
9889+
ViewGroup viewGroup = ((ViewGroup) mParent);
98829890

9883-
if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9891+
if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9892+
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9893+
}
9894+
} else {
9895+
// Nothing to do, LTR by default
9896+
}
9897+
break;
9898+
case LAYOUT_DIRECTION_RTL:
9899+
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9900+
break;
9901+
case LAYOUT_DIRECTION_LOCALE:
9902+
if(isLayoutDirectionRtl(Locale.getDefault())) {
98849903
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
98859904
}
9886-
} else {
9905+
break;
9906+
default:
98879907
// Nothing to do, LTR by default
9888-
}
9889-
break;
9890-
case LAYOUT_DIRECTION_RTL:
9891-
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9892-
break;
9893-
case LAYOUT_DIRECTION_LOCALE:
9894-
if(isLayoutDirectionRtl(Locale.getDefault())) {
9895-
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9896-
}
9897-
break;
9898-
default:
9899-
// Nothing to do, LTR by default
9908+
}
99009909
}
99019910

99029911
// Set to resolved
@@ -14603,44 +14612,49 @@ public void resolveTextDirection() {
1460314612
// Reset any previous text direction resolution
1460414613
mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
1460514614

14606-
// Set resolved text direction flag depending on text direction flag
14607-
final int textDirection = getTextDirection();
14608-
switch(textDirection) {
14609-
case TEXT_DIRECTION_INHERIT:
14610-
if (canResolveTextDirection()) {
14611-
ViewGroup viewGroup = ((ViewGroup) mParent);
14612-
14613-
// Set current resolved direction to the same value as the parent's one
14614-
final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
14615-
switch (parentResolvedDirection) {
14616-
case TEXT_DIRECTION_FIRST_STRONG:
14617-
case TEXT_DIRECTION_ANY_RTL:
14618-
case TEXT_DIRECTION_LTR:
14619-
case TEXT_DIRECTION_RTL:
14620-
case TEXT_DIRECTION_LOCALE:
14621-
mPrivateFlags2 |=
14622-
(parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
14623-
break;
14624-
default:
14625-
// Default resolved direction is "first strong" heuristic
14626-
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
14615+
if (hasRtlSupport()) {
14616+
// Set resolved text direction flag depending on text direction flag
14617+
final int textDirection = getTextDirection();
14618+
switch(textDirection) {
14619+
case TEXT_DIRECTION_INHERIT:
14620+
if (canResolveTextDirection()) {
14621+
ViewGroup viewGroup = ((ViewGroup) mParent);
14622+
14623+
// Set current resolved direction to the same value as the parent's one
14624+
final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
14625+
switch (parentResolvedDirection) {
14626+
case TEXT_DIRECTION_FIRST_STRONG:
14627+
case TEXT_DIRECTION_ANY_RTL:
14628+
case TEXT_DIRECTION_LTR:
14629+
case TEXT_DIRECTION_RTL:
14630+
case TEXT_DIRECTION_LOCALE:
14631+
mPrivateFlags2 |=
14632+
(parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
14633+
break;
14634+
default:
14635+
// Default resolved direction is "first strong" heuristic
14636+
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
14637+
}
14638+
} else {
14639+
// We cannot do the resolution if there is no parent, so use the default one
14640+
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
1462714641
}
14628-
} else {
14629-
// We cannot do the resolution if there is no parent, so use the default one
14642+
break;
14643+
case TEXT_DIRECTION_FIRST_STRONG:
14644+
case TEXT_DIRECTION_ANY_RTL:
14645+
case TEXT_DIRECTION_LTR:
14646+
case TEXT_DIRECTION_RTL:
14647+
case TEXT_DIRECTION_LOCALE:
14648+
// Resolved direction is the same as text direction
14649+
mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
14650+
break;
14651+
default:
14652+
// Default resolved direction is "first strong" heuristic
1463014653
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
14631-
}
14632-
break;
14633-
case TEXT_DIRECTION_FIRST_STRONG:
14634-
case TEXT_DIRECTION_ANY_RTL:
14635-
case TEXT_DIRECTION_LTR:
14636-
case TEXT_DIRECTION_RTL:
14637-
case TEXT_DIRECTION_LOCALE:
14638-
// Resolved direction is the same as text direction
14639-
mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
14640-
break;
14641-
default:
14642-
// Default resolved direction is "first strong" heuristic
14643-
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
14654+
}
14655+
} else {
14656+
// Default resolved direction is "first strong" heuristic
14657+
mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
1464414658
}
1464514659

1464614660
// Set to resolved

core/res/res/values/attrs_manifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,9 @@
843843
@hide -->
844844
<attr name="cantSaveState" format="boolean" />
845845
<attr name="uiOptions" />
846+
<!-- Declare that your application will be able to deal with RTL (right to left) layouts.
847+
If set to false (default value), your application will not care about RTL layouts. -->
848+
<attr name="supportsRtl" format="boolean" />
846849
</declare-styleable>
847850

848851
<!-- The <code>permission</code> tag declares a security permission that can be

core/res/res/values/public.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,6 +3545,8 @@
35453545
=============================================================== -->
35463546
<public type="attr" name="isolatedProcess" id="0x010103a7" />
35473547

3548+
<public type="attr" name="supportsRtl" id="0x010103a8" />
3549+
35483550
<public type="attr" name="textDirection"/>
35493551

35503552
<public type="attr" name="layoutDirection" />

tests/BiDiTests/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
android:versionCode="1"
2020
android:versionName="1.0">
2121

22-
<application android:label="BiDiTests" android:hardwareAccelerated="true">
22+
<application android:label="BiDiTests"
23+
android:hardwareAccelerated="true"
24+
android:supportsRtl="true" >
2325

2426
<activity android:name=".BiDiTestActivity"
2527
android:windowSoftInputMode="stateAlwaysHidden">

0 commit comments

Comments
 (0)