merge master to master_gl
diff --git a/Android.mk b/Android.mk
index f08f6d2..8c81b8e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -138,7 +138,6 @@
location/java/android/location/IGeocodeProvider.aidl \
location/java/android/location/IGpsStatusListener.aidl \
location/java/android/location/IGpsStatusProvider.aidl \
- location/java/android/location/ILocationCollector.aidl \
location/java/android/location/ILocationListener.aidl \
location/java/android/location/ILocationManager.aidl \
location/java/android/location/ILocationProvider.aidl \
diff --git a/NOTICE b/NOTICE
index 267a6aa..bb9c5f2 100644
--- a/NOTICE
+++ b/NOTICE
@@ -220,3 +220,54 @@
END OF TERMS AND CONDITIONS
+
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any
+source code published in the Unicode Standard or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY
+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA
+FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY
+ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF
+THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY,
+DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2008 Unicode, Inc. All rights reserved. Distributed
+under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software,
+and to permit persons to whom the Data Files or Software are furnished to
+do so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File
+or in the Software as well as in the documentation associated with the
+Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
diff --git a/api/current.xml b/api/current.xml
index d7d86dee..dde1b76 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -529,17 +529,6 @@
visibility="public"
>
</field>
-<field name="INSTALL_LOCATION_COLLECTOR"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.permission.INSTALL_LOCATION_COLLECTOR""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="INSTALL_LOCATION_PROVIDER"
type="java.lang.String"
transient="false"
@@ -870,17 +859,6 @@
visibility="public"
>
</field>
-<field name="SDCARD_WRITE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.permission.SDCARD_WRITE""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="SEND_SMS"
type="java.lang.String"
transient="false"
@@ -1046,6 +1024,17 @@
visibility="public"
>
</field>
+<field name="STOP_APP_SWITCHES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.permission.STOP_APP_SWITCHES""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SUBSCRIBED_FEEDS_READ"
type="java.lang.String"
transient="false"
@@ -1167,6 +1156,17 @@
visibility="public"
>
</field>
+<field name="WRITE_SDCARD"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.permission.WRITE_SDCARD""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="WRITE_SECURE_SETTINGS"
type="java.lang.String"
transient="false"
@@ -1409,7 +1409,7 @@
type="int"
transient="false"
volatile="false"
- value="17432583"
+ value="17432609"
static="true"
final="true"
deprecated="not deprecated"
@@ -1420,7 +1420,7 @@
type="int"
transient="false"
volatile="false"
- value="17432585"
+ value="17432611"
static="true"
final="true"
deprecated="not deprecated"
@@ -1431,7 +1431,7 @@
type="int"
transient="false"
volatile="false"
- value="17432586"
+ value="17432612"
static="true"
final="true"
deprecated="not deprecated"
@@ -1449,6 +1449,292 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432599"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432598"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432597"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432596"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432595"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432594"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432593"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432592"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432591"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432590"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432607"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432589"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432588"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432587"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432586"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432584"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432583"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432606"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432605"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432604"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432603"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432602"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432601"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432600"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="fade_in"
type="int"
transient="false"
@@ -1471,11 +1757,22 @@
visibility="public"
>
</field>
+<field name="linear_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432613"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="overshoot_interpolator"
type="int"
transient="false"
volatile="false"
- value="17432584"
+ value="17432610"
static="true"
final="true"
deprecated="not deprecated"
@@ -1521,6 +1818,138 @@
visibility="public"
>
</constructor>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235984"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235975"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235974"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235973"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235983"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235982"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235981"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235980"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235979"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235978"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235977"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17235976"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="emailAddressTypes"
type="int"
transient="false"
@@ -1608,7 +2037,7 @@
type="int"
transient="false"
volatile="false"
- value="16843380"
+ value="16843424"
static="true"
final="true"
deprecated="not deprecated"
@@ -2565,7 +2994,7 @@
type="int"
transient="false"
volatile="false"
- value="16843381"
+ value="16843425"
static="true"
final="true"
deprecated="not deprecated"
@@ -2880,6 +3309,490 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843423"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843414"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843413"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843412"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843411"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843409"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843408"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843407"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843406"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843405"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843422"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843404"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843403"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843402"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843401"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843400"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843399"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843398"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad27"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843397"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad28"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843396"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad29"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843395"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843421"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad30"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843394"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad31"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843393"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad32"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843392"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad33"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843391"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad34"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843390"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad35"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843389"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad36"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843388"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad37"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843387"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad38"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad39"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843420"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad40"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad41"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843383"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad42"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad43"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843381"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad44"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843380"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843419"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843418"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843417"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843416"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843415"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="drawSelectorOnTop"
type="int"
transient="false"
@@ -8590,6 +9503,347 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170480"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170471"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170470"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170469"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170468"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170467"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170466"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170465"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170464"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170463"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170462"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170479"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170461"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170460"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170459"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170458"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170457"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170456"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170455"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad27"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170454"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad28"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170453"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad29"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170452"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170478"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad30"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170451"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad31"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170450"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170477"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170476"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170475"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170474"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170473"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17170472"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="primary_text_dark"
type="int"
transient="false"
@@ -8772,6 +10026,160 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104912"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104903"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104902"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104901"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104899"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104911"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104910"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104909"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104908"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104907"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104906"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104905"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104904"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="thumbnail_height"
type="int"
transient="false"
@@ -9086,6 +10494,468 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301712"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301703"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301702"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301701"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301700"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301699"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301698"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301697"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301696"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301695"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301694"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301711"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301693"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301692"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301691"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301690"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301689"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301688"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301687"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad27"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301686"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad28"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301685"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad29"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301684"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301710"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad30"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301683"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad31"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301682"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad32"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301681"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad33"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301680"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad34"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301679"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad35"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301678"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad36"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301677"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad37"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301676"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad38"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301675"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad39"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301674"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301709"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad40"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301673"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad41"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301672"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad42"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301671"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301708"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301707"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301706"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301705"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301704"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="edit_text"
type="int"
transient="false"
@@ -10421,7 +12291,7 @@
type="int"
transient="false"
volatile="false"
- value="17302061"
+ value="17301713"
static="true"
final="true"
deprecated="not deprecated"
@@ -10432,7 +12302,7 @@
type="int"
transient="false"
volatile="false"
- value="17302062"
+ value="17301714"
static="true"
final="true"
deprecated="not deprecated"
@@ -10753,6 +12623,248 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908352"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908343"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908342"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908341"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908340"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908339"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908338"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908337"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908336"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908335"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908334"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908351"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908333"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908332"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908331"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908350"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908349"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908348"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908347"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908346"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908345"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908344"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="edit"
type="int"
transient="false"
@@ -11144,6 +13256,160 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694736"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694727"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694726"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694725"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694724"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694723"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694735"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694734"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694733"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694732"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694731"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694730"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694729"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="R.layout"
extends="java.lang.Object"
@@ -11183,6 +13449,149 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367063"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367060"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367071"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367070"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367069"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367068"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367067"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367066"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367065"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="expandable_list_content"
type="int"
transient="false"
@@ -11553,6 +13962,303 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039408"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039399"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039398"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039397"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039396"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039395"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039394"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039393"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039392"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039391"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039390"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039407"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039389"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039388"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039387"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039383"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad27"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039406"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039405"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039404"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039403"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039402"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039401"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039400"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="emptyPhoneNumber"
type="int"
transient="false"
@@ -12670,6 +15376,248 @@
visibility="public"
>
</field>
+<field name="donut_resource_pad1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973936"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973927"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973926"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973925"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973924"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973923"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973922"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973921"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973920"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973919"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973918"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973935"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973917"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973916"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973915"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973934"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973933"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973932"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973931"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973930"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973929"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="donut_resource_pad9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973928"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="R.xml"
extends="java.lang.Object"
@@ -25060,6 +28008,21 @@
visibility="public"
>
</constructor>
+<method name="applyBatch"
+ return="android.content.ContentProviderResult[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="operations" type="android.content.ContentProviderOperation[]">
+</parameter>
+<exception name="OperationApplicationException" type="android.content.OperationApplicationException">
+</exception>
+</method>
<method name="attachInfo"
return="void"
abstract="false"
@@ -25681,6 +28644,252 @@
</exception>
</method>
</class>
+<class name="ContentProviderOperation"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="apply"
+ return="android.content.ContentProviderResult"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="android.content.ContentProvider">
+</parameter>
+<parameter name="backRefs" type="android.content.ContentProviderResult[]">
+</parameter>
+<parameter name="numBackRefs" type="int">
+</parameter>
+<exception name="OperationApplicationException" type="android.content.OperationApplicationException">
+</exception>
+</method>
+<method name="newCountQuery"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="newDelete"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="newInsert"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="newUpdate"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="resolveSelectionArgsBackReferences"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="backRefs" type="android.content.ContentProviderResult[]">
+</parameter>
+<parameter name="numBackRefs" type="int">
+</parameter>
+</method>
+<method name="resolveValueBackReferences"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="backRefs" type="android.content.ContentProviderResult[]">
+</parameter>
+<parameter name="numBackRefs" type="int">
+</parameter>
+</method>
+</class>
+<class name="ContentProviderOperation.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="build"
+ return="android.content.ContentProviderOperation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="withExpectedCount"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="count" type="int">
+</parameter>
+</method>
+<method name="withSelection"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="withSelectionBackReferences"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="backReferences" type="java.util.Map<java.lang.Integer, java.lang.Integer>">
+</parameter>
+</method>
+<method name="withValueBackReferences"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="backReferences" type="android.content.ContentValues">
+</parameter>
+</method>
+<method name="withValues"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+</method>
+</class>
+<class name="ContentProviderResult"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ContentProviderResult"
+ type="android.content.ContentProviderResult"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</constructor>
+<constructor name="ContentProviderResult"
+ type="android.content.ContentProviderResult"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="count" type="int">
+</parameter>
+</constructor>
+<field name="count"
+ type="java.lang.Integer"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="uri"
+ type="android.net.Uri"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="ContentQueryMap"
extends="java.util.Observable"
abstract="false"
@@ -33581,6 +36790,55 @@
</parameter>
</method>
</class>
+<class name="OperationApplicationException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="OperationApplicationException"
+ type="android.content.OperationApplicationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="OperationApplicationException"
+ type="android.content.OperationApplicationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="OperationApplicationException"
+ type="android.content.OperationApplicationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="OperationApplicationException"
+ type="android.content.OperationApplicationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+</class>
<class name="ReceiverCallNotAllowedException"
extends="android.util.AndroidRuntimeException"
abstract="false"
@@ -34803,22 +38061,11 @@
visibility="public"
>
</field>
-<field name="FLAG_TARGETS_SDK"
- type="int"
- transient="false"
- volatile="false"
- value="256"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="FLAG_TEST_ONLY"
type="int"
transient="false"
volatile="false"
- value="512"
+ value="256"
static="true"
final="true"
deprecated="not deprecated"
@@ -34958,6 +38205,16 @@
visibility="public"
>
</field>
+<field name="targetSdkVersion"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="taskAffinity"
type="java.lang.String"
transient="false"
@@ -46111,6 +49368,1097 @@
</method>
</class>
</package>
+<package name="android.gesture"
+>
+<class name="Gesture"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="Gesture"
+ type="android.gesture.Gesture"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addStroke"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stroke" type="android.gesture.GestureStroke">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBoundingBox"
+ return="android.graphics.RectF"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getID"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLength"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStrokes"
+ return="java.util.ArrayList<android.gesture.GestureStroke>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStrokesCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toBitmap"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="toBitmap"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureLibrary"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureLibrary"
+ type="android.gesture.GestureLibrary"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="addGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="getGestureEntries"
+ return="java.util.Set<java.lang.String>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestures"
+ return="java.util.ArrayList<android.gesture.Gesture>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+</method>
+<method name="getOrientationStyle"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSequenceType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="recognize"
+ return="java.util.ArrayList<android.gesture.Prediction>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="removeEntry"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+</method>
+<method name="removeGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="save"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setOrientationStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="int">
+</parameter>
+</method>
+<method name="setSequenceType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
+<field name="ORIENTATION_INVARIANT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_SENSITIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEQUENCE_INVARIANT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEQUENCE_SENSITIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureOverlayView"
+ extends="android.view.View"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureOverlayView"
+ type="android.gesture.GestureOverlayView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="GestureOverlayView"
+ type="android.gesture.GestureOverlayView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="addOnGestureListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
+</parameter>
+</method>
+<method name="cancelFadingOut"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="clear"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fadeOut" type="boolean">
+</parameter>
+</method>
+<method name="getCurrentGesture"
+ return="android.gesture.Gesture"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentStroke"
+ return="java.util.ArrayList<android.gesture.GesturePoint>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUncertainGestureColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeOnGestureListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
+</parameter>
+</method>
+<method name="setCurrentGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="setGestureColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="setGestureDrawingColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="setUncertainGestureColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<field name="DEFAULT_GESTURE_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DEFAULT_UNCERTAIN_GESTURE_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="GestureOverlayView.OnGestureListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onGesture"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureEnded"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureStarted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+</interface>
+<class name="GesturePoint"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GesturePoint"
+ type="android.gesture.GesturePoint"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="t" type="long">
+</parameter>
+</constructor>
+<field name="timestamp"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureStroke"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureStroke"
+ type="android.gesture.GestureStroke"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="points" type="java.util.ArrayList<android.gesture.GesturePoint>">
+</parameter>
+</constructor>
+<method name="clearPath"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="computeOrientedBoundingBox"
+ return="android.gesture.OrientedBoundingBox"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="float">
+</parameter>
+<parameter name="height" type="float">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+</method>
+<field name="boundingBox"
+ type="android.graphics.RectF"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="length"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="points"
+ type="float[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="LetterRecognizer"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getLetterRecognizer"
+ return="android.gesture.LetterRecognizer"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+</method>
+<method name="recognize"
+ return="java.util.ArrayList<android.gesture.Prediction>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<field name="RECOGNIZER_LATIN_LOWERCASE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="OrientedBoundingBox"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="centerX"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="centerY"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="height"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="orientation"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="squareness"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="width"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Prediction"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="name"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="score"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="TouchThroughGestureListener"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.gesture.GestureOverlayView.OnGestureListener">
+</implements>
+<constructor name="TouchThroughGestureListener"
+ type="android.gesture.TouchThroughGestureListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="model" type="android.view.View">
+</parameter>
+</constructor>
+<constructor name="TouchThroughGestureListener"
+ type="android.gesture.TouchThroughGestureListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="model" type="android.view.View">
+</parameter>
+<parameter name="stealEvents" type="boolean">
+</parameter>
+</constructor>
+<method name="addOnGestureActionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.TouchThroughGestureListener.OnGesturePerformedListener">
+</parameter>
+</method>
+<method name="isGesturing"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureEnded"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="removeOnGestureActionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.TouchThroughGestureListener.OnGesturePerformedListener">
+</parameter>
+</method>
+<method name="setGestureType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
+<field name="MULTIPLE_STROKE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SINGLE_STROKE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="TouchThroughGestureListener.OnGesturePerformedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onGesturePerformed"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+</interface>
+</package>
<package name="android.graphics"
>
<class name="AvoidXfermode"
@@ -88642,6 +92990,16 @@
visibility="public"
>
</field>
+<field name="MANUFACTURER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="MODEL"
type="java.lang.String"
transient="false"
@@ -88819,6 +93177,28 @@
visibility="public"
>
</field>
+<field name="CUR_DEVELOPMENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DONUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="Bundle"
extends="java.lang.Object"
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index 96cc512..be78a62 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -42,6 +42,7 @@
LOCAL_SHARED_LIBRARIES:= \
libui \
libutils \
+ libbinder \
libcutils \
libmedia
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index 0d26d47..efae935 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -21,8 +21,8 @@
#include "FakeCamera.h"
#include <utils/threads.h>
#include <ui/CameraHardwareInterface.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
#include <utils/threads.h>
namespace android {
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index f85ea9f8..404512e 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -20,12 +20,12 @@
#define LOG_TAG "CameraService"
#include <utils/Log.h>
-#include <utils/IServiceManager.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
#include <utils/String16.h>
#include <utils/Errors.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
#include <ui/ICameraService.h>
#include <media/mediaplayer.h>
@@ -1052,8 +1052,6 @@
}
-#if DEBUG_HEAP_LEAKS
-
#define CHECK_INTERFACE(interface, data, reply) \
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
LOGW("Call incorrectly routed to " #interface); \
@@ -1085,6 +1083,7 @@
status_t err = BnCameraService::onTransact(code, data, reply, flags);
+#if DEBUG_HEAP_LEAKS
LOGD("+++ onTransact err %d code %d", err, code);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
@@ -1120,9 +1119,9 @@
break;
}
}
+#endif // DEBUG_HEAP_LEAKS
+
return err;
}
-#endif // DEBUG_HEAP_LEAKS
-
}; // namespace android
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 6752f26..a421fd3 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -58,10 +58,8 @@
void removeClient(const sp<ICameraClient>& cameraClient);
-#if DEBUG_HEAP_LEAKS
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
-#endif
private:
diff --git a/cmds/am/am b/cmds/am/am
index a5b13f9..c823634 100755
--- a/cmds/am/am
+++ b/cmds/am/am
@@ -3,5 +3,5 @@
#
base=/system
export CLASSPATH=$base/framework/am.jar
-exec app_process $base/bin com.android.commands.am.Am $*
+exec app_process $base/bin com.android.commands.am.Am "$@"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 6d4b455..88ad265 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -194,18 +194,17 @@
if (intent != null) {
System.out.println("Starting: " + intent);
try {
- intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// XXX should do something to determine the MIME type.
int res = mAm.startActivity(null, intent, intent.getType(),
null, 0, null, null, 0, false, mDebugOption);
switch (res) {
case IActivityManager.START_SUCCESS:
break;
- case IActivityManager.START_CLASS_NOT_FOUND:
- System.err.println("Error type 3");
- System.err.println("Error: Activity class " +
- intent.getComponent().toShortString()
- + " does not exist.");
+ case IActivityManager.START_SWITCHES_CANCELED:
+ System.err.println(
+ "Warning: Activity not started because the "
+ + " current activity is being kept for the user.");
break;
case IActivityManager.START_DELIVERED_TO_TOP:
System.err.println(
@@ -213,16 +212,6 @@
+ "been delivered to currently running "
+ "top-most instance.");
break;
- case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
- System.err.println(
- "Error: Activity not started, you requested to "
- + "both forward and receive its result");
- break;
- case IActivityManager.START_INTENT_NOT_RESOLVED:
- System.err.println(
- "Error: Activity not started, unable to "
- + "resolve " + intent.toString());
- break;
case IActivityManager.START_RETURN_INTENT_TO_CALLER:
System.err.println(
"Warning: Activity not started because intent "
@@ -233,6 +222,27 @@
"Warning: Activity not started, its current "
+ "task has been brought to the front");
break;
+ case IActivityManager.START_INTENT_NOT_RESOLVED:
+ System.err.println(
+ "Error: Activity not started, unable to "
+ + "resolve " + intent.toString());
+ break;
+ case IActivityManager.START_CLASS_NOT_FOUND:
+ System.err.println("Error type 3");
+ System.err.println("Error: Activity class " +
+ intent.getComponent().toShortString()
+ + " does not exist.");
+ break;
+ case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+ System.err.println(
+ "Error: Activity not started, you requested to "
+ + "both forward and receive its result");
+ break;
+ case IActivityManager.START_PERMISSION_DENIED:
+ System.err.println(
+ "Error: Activity not started, you do not "
+ + "have permission to access it.");
+ break;
default:
System.err.println(
"Error: Activity not started, unknown error "
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index d825d5a..7decf9a 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -7,8 +7,8 @@
#define LOG_TAG "appproc"
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
diff --git a/cmds/backup/Android.mk b/cmds/backup/Android.mk
new file mode 100644
index 0000000..508aec0
--- /dev/null
+++ b/cmds/backup/Android.mk
@@ -0,0 +1,15 @@
+# Copyright 2009 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= backup.cpp
+
+LOCAL_SHARED_LIBRARIES := libcutils libutils
+
+LOCAL_MODULE:= btool
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/backup/NOTICE b/cmds/backup/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/backup/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/cmds/backup/backup.cpp b/cmds/backup/backup.cpp
new file mode 100644
index 0000000..51ac943
--- /dev/null
+++ b/cmds/backup/backup.cpp
@@ -0,0 +1,122 @@
+
+#include <utils/backup_helpers.h>
+#include <utils/String8.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+using namespace android;
+
+#include <unistd.h>
+
+int
+usage(int argc, const char** argv)
+{
+ const char* p = argv[0];
+
+ fprintf(stderr, "%s: Backs up your data.\n"
+ "\n"
+ "usage: %s\n"
+ " Prints all of the data that can be backed up to stdout.\n"
+ "\n"
+ "usage: %s list FILE\n"
+ " Lists the backup entities in the file.\n"
+ "\n"
+ "usage: %s print NAME FILE\n"
+ " Prints the entity named NAME in FILE.\n",
+ p, p, p, p);
+ return 1;
+}
+
+int
+perform_full_backup()
+{
+ printf("this would have written all of your data to stdout\n");
+ return 0;
+}
+
+int
+perform_list(const char* filename)
+{
+ int err;
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "Error opening: %s\n", filename);
+ return 1;
+ }
+
+ BackupDataReader reader(fd);
+ int type;
+
+ while (reader.ReadNextHeader(&type) == 0) {
+ switch (type) {
+ case BACKUP_HEADER_APP_V1:
+ {
+ String8 packageName;
+ int cookie;
+ err = reader.ReadAppHeader(&packageName, &cookie);
+ if (err == 0) {
+ printf("App header: %s 0x%08x (%d)\n", packageName.string(), cookie, cookie);
+ } else {
+ printf("Error reading app header\n");
+ }
+ break;
+ }
+ case BACKUP_HEADER_ENTITY_V1:
+ {
+ String8 key;
+ size_t dataSize;
+ err = reader.ReadEntityHeader(&key, &dataSize);
+ if (err == 0) {
+ printf(" entity: %s (%d bytes)\n", key.string(), dataSize);
+ } else {
+ printf(" Error reading entity header\n");
+ }
+ break;
+ }
+ case BACKUP_FOOTER_APP_V1:
+ {
+ int cookie;
+ err = reader.ReadAppFooter(&cookie);
+ if (err == 0) {
+ printf(" App footer: 0x%08x (%d)\n", cookie, cookie);
+ } else {
+ printf(" Error reading entity header\n");
+ }
+ break;
+ }
+ default:
+ {
+ printf("Unknown chunk type: 0x%08x\n", type);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int perform_print(const char* entityname, const char* filename)
+{
+ printf("perform_print(%s, %s);", entityname, filename);
+ return 0;
+}
+
+int
+main(int argc, const char** argv)
+{
+ if (argc <= 1) {
+ return perform_full_backup();
+ }
+ if (argc == 3 && 0 == strcmp(argv[1], "list")) {
+ return perform_list(argv[2]);
+ }
+ if (argc == 4 && 0 == strcmp(argv[1], "print")) {
+ return perform_print(argv[2], argv[3]);
+ }
+ return usage(argc, argv);
+}
+
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
new file mode 100644
index 0000000..d31d81c
--- /dev/null
+++ b/cmds/bootanimation/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ bootanimation_main.cpp \
+ BootAnimation.cpp
+
+# need "-lrt" on Linux simulator to pick up clock_gettime
+ifeq ($(TARGET_SIMULATOR),true)
+ ifeq ($(HOST_OS),linux)
+ LOCAL_LDLIBS += -lrt
+ endif
+endif
+
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libui \
+ libcorecg \
+ libsgl \
+ libEGL \
+ libGLESv1_CM
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, corecg graphics)
+
+LOCAL_MODULE:= bootanimation
+
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
similarity index 93%
rename from libs/surfaceflinger/BootAnimation.cpp
rename to cmds/bootanimation/BootAnimation.cpp
index b45fe34..e2d01de 100644
--- a/libs/surfaceflinger/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <utils/misc.h>
+#include <binder/IPCThreadState.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
@@ -47,10 +48,9 @@
// ---------------------------------------------------------------------------
-BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) :
- Thread(false) {
- mSession = SurfaceComposerClient::clientForConnection(
- composer->createConnection()->asBinder());
+BootAnimation::BootAnimation() : Thread(false)
+{
+ mSession = new SurfaceComposerClient();
}
BootAnimation::~BootAnimation() {
@@ -129,7 +129,8 @@
// create the native surface
sp<SurfaceControl> control = session()->createSurface(
- getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
+ getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565,
+ ISurfaceComposer::eGPU);
session()->openTransaction();
control->setLayer(0x40000000);
session()->closeTransaction();
@@ -144,7 +145,10 @@
EGLConfig config;
EGLSurface surface;
EGLContext context;
+
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
surface = eglCreateWindowSurface(display, config, s.get(), NULL);
@@ -169,11 +173,6 @@
return NO_ERROR;
}
-void BootAnimation::requestExit() {
- mBarrier.open();
- Thread::requestExit();
-}
-
bool BootAnimation::threadLoop() {
bool r = android();
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -181,6 +180,8 @@
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
+ eglTerminate(mDisplay);
+ IPCThreadState::self()->stopProcess();
return r;
}
@@ -226,8 +227,10 @@
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
- eglSwapBuffers(mDisplay, mSurface);
-
+ EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
+ if (res == EGL_FALSE)
+ break;
+
// 12fps: don't animate too fast to preserve CPU
const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
if (sleepTime > 0)
diff --git a/libs/surfaceflinger/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
similarity index 91%
rename from libs/surfaceflinger/BootAnimation.h
rename to cmds/bootanimation/BootAnimation.h
index 0e35434..796077d 100644
--- a/libs/surfaceflinger/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -29,25 +29,21 @@
#include <EGL/egl.h>
#include <GLES/gl.h>
-#include "Barrier.h"
-
class SkBitmap;
namespace android {
class AssetManager;
-class EGLNativeWindowSurface;
// ---------------------------------------------------------------------------
class BootAnimation : public Thread
{
public:
- BootAnimation(const sp<ISurfaceComposer>& composer);
+ BootAnimation();
virtual ~BootAnimation();
const sp<SurfaceComposerClient>& session() const;
- virtual void requestExit();
private:
virtual bool threadLoop();
@@ -73,7 +69,6 @@
EGLDisplay mSurface;
sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface;
- Barrier mBarrier;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
new file mode 100644
index 0000000..346f156
--- /dev/null
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#define LOG_TAG "BootAnimation"
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <ui/ISurfaceComposer.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+# include <sys/resource.h>
+#endif
+
+#include "BootAnimation.h"
+
+using namespace android;
+
+// ---------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+#if defined(HAVE_PTHREADS)
+ setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
+#endif
+
+ sp<ProcessState> proc(ProcessState::self());
+ ProcessState::self()->startThreadPool();
+
+ // create the boot animation object
+ sp<BootAnimation> boot = new BootAnimation();
+
+ IPCThreadState::self()->joinThreadPool();
+ return 0;
+}
diff --git a/cmds/dumpsys/Android.mk b/cmds/dumpsys/Android.mk
index 0c623cc..42b1b73 100644
--- a/cmds/dumpsys/Android.mk
+++ b/cmds/dumpsys/Android.mk
@@ -5,7 +5,9 @@
dumpsys.cpp
LOCAL_SHARED_LIBRARIES := \
- libutils
+ libutils \
+ libbinder
+
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index a62fe55..945a690 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -6,9 +6,9 @@
#define LOG_TAG "dumpsys"
#include <utils/Log.h>
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <utils/Vector.h>
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
index 521eb2b..6a72d10 100644
--- a/cmds/runtime/Android.mk
+++ b/cmds/runtime/Android.mk
@@ -10,6 +10,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libbinder \
libandroid_runtime \
libcutils \
libui \
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
index 758a95c..b2bef07 100644
--- a/cmds/runtime/ServiceManager.cpp
+++ b/cmds/runtime/ServiceManager.cpp
@@ -9,9 +9,9 @@
#include <utils/Debug.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
#include <private/utils/Static.h>
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 1531a9e..718ea67 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -8,8 +8,8 @@
#include "SignalHandler.h"
#include <utils.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/zygote.h>
diff --git a/cmds/service/Android.mk b/cmds/service/Android.mk
index 8c5005c..275bbb2 100644
--- a/cmds/service/Android.mk
+++ b/cmds/service/Android.mk
@@ -4,8 +4,7 @@
LOCAL_SRC_FILES:= \
service.cpp
-LOCAL_SHARED_LIBRARIES := \
- libutils
+LOCAL_SHARED_LIBRARIES := libutils libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 859a9bf..32db83b 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -3,9 +3,9 @@
*
*/
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <getopt.h>
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index 37c3d94..bfa58a1 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SHARED_LIBRARIES := \
libsurfaceflinger \
+ libbinder \
libutils
LOCAL_C_INCLUDES := \
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 7c89578..d650721 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <SurfaceFlinger.h>
diff --git a/cmds/system_server/Android.mk b/cmds/system_server/Android.mk
index 0a684e8..ad537977 100644
--- a/cmds/system_server/Android.mk
+++ b/cmds/system_server/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libbinder \
libsystem_server
LOCAL_C_INCLUDES := \
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 580331a..1813d3e 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -20,6 +20,7 @@
libcameraservice \
libmediaplayerservice \
libutils \
+ libbinder \
libcutils
LOCAL_MODULE:= libsystem_server
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index 73b23e2..ea78461 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -8,9 +8,9 @@
#define LOG_TAG "sysproc"
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/TextOutput.h>
#include <utils/Log.h>
diff --git a/cmds/system_server/system_main.cpp b/cmds/system_server/system_main.cpp
index ca16e57..543f650 100644
--- a/cmds/system_server/system_main.cpp
+++ b/cmds/system_server/system_main.cpp
@@ -9,7 +9,7 @@
#define LOG_TAG "sysproc"
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 541f413..16f0a30 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -998,6 +998,20 @@
return true;
}
+ case STOP_APP_SWITCHES_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ stopAppSwitches();
+ reply.writeNoException();
+ return true;
+ }
+
+ case RESUME_APP_SWITCHES_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ resumeAppSwitches();
+ reply.writeNoException();
+ return true;
+ }
+
case PEEK_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Intent service = Intent.CREATOR.createFromParcel(data);
@@ -2182,5 +2196,25 @@
return res;
}
+ public void stopAppSwitches() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(STOP_APP_SWITCHES_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
+ public void resumeAppSwitches() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(RESUME_APP_SWITCHES_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
new file mode 100644
index 0000000..72cbff4
--- /dev/null
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2008 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 android.app;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.util.Printer;
+
+/**
+ * Describes an application error.
+ *
+ * A report has a type, which is one of
+ * <ul>
+ * <li> {@link #TYPE_CRASH} application crash. Information about the crash
+ * is stored in {@link #crashInfo}.
+ * <li> {@link #TYPE_ANR} application not responding. Information about the
+ * ANR is stored in {@link #anrInfo}.
+ * <li> {@link #TYPE_NONE} uninitialized instance of {@link ApplicationErrorReport}.
+ * </ul>
+ *
+ * @hide
+ */
+
+public class ApplicationErrorReport implements Parcelable {
+ /**
+ * Uninitialized error report.
+ */
+ public static final int TYPE_NONE = 0;
+
+ /**
+ * An error report about an application crash.
+ */
+ public static final int TYPE_CRASH = 1;
+
+ /**
+ * An error report about an application that's not responding.
+ */
+ public static final int TYPE_ANR = 2;
+
+ /**
+ * Type of this report. Can be one of {@link #TYPE_NONE},
+ * {@link #TYPE_CRASH} or {@link #TYPE_ANR}.
+ */
+ public int type;
+
+ /**
+ * Package name of the application.
+ */
+ public String packageName;
+
+ /**
+ * Package name of the application which installed the application this
+ * report pertains to.
+ * This identifies which Market the application came from.
+ */
+ public String installerPackageName;
+
+ /**
+ * Process name of the application.
+ */
+ public String processName;
+
+ /**
+ * Time at which the error occurred.
+ */
+ public long time;
+
+ /**
+ * If this report is of type {@link #TYPE_CRASH}, contains an instance
+ * of CrashInfo describing the crash; otherwise null.
+ */
+ public CrashInfo crashInfo;
+
+ /**
+ * If this report is of type {@link #TYPE_ANR}, contains an instance
+ * of AnrInfo describing the ANR; otherwise null.
+ */
+ public AnrInfo anrInfo;
+
+ /**
+ * Create an uninitialized instance of {@link ApplicationErrorReport}.
+ */
+ public ApplicationErrorReport() {
+ }
+
+ /**
+ * Create an instance of {@link ApplicationErrorReport} initialized from
+ * a parcel.
+ */
+ ApplicationErrorReport(Parcel in) {
+ type = in.readInt();
+ packageName = in.readString();
+ installerPackageName = in.readString();
+ processName = in.readString();
+ time = in.readLong();
+
+ switch (type) {
+ case TYPE_CRASH:
+ crashInfo = new CrashInfo(in);
+ break;
+ case TYPE_ANR:
+ anrInfo = new AnrInfo(in);
+ break;
+ }
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(type);
+ dest.writeString(packageName);
+ dest.writeString(installerPackageName);
+ dest.writeString(processName);
+ dest.writeLong(time);
+
+ switch (type) {
+ case TYPE_CRASH:
+ crashInfo.writeToParcel(dest, flags);
+ break;
+ case TYPE_ANR:
+ anrInfo.writeToParcel(dest, flags);
+ break;
+ }
+ }
+
+ /**
+ * Describes an application crash.
+ */
+ public static class CrashInfo {
+ /**
+ * Class name of the exception that caused the crash.
+ */
+ public String exceptionClassName;
+
+ /**
+ * File which the exception was thrown from.
+ */
+ public String throwFileName;
+
+ /**
+ * Class which the exception was thrown from.
+ */
+ public String throwClassName;
+
+ /**
+ * Method which the exception was thrown from.
+ */
+ public String throwMethodName;
+
+ /**
+ * Stack trace.
+ */
+ public String stackTrace;
+
+ /**
+ * Create an uninitialized instance of CrashInfo.
+ */
+ public CrashInfo() {
+ }
+
+ /**
+ * Create an instance of CrashInfo initialized from a Parcel.
+ */
+ public CrashInfo(Parcel in) {
+ exceptionClassName = in.readString();
+ throwFileName = in.readString();
+ throwClassName = in.readString();
+ throwMethodName = in.readString();
+ stackTrace = in.readString();
+ }
+
+ /**
+ * Save a CrashInfo instance to a parcel.
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(exceptionClassName);
+ dest.writeString(throwFileName);
+ dest.writeString(throwClassName);
+ dest.writeString(throwMethodName);
+ dest.writeString(stackTrace);
+ }
+
+ /**
+ * Dump a CrashInfo instance to a Printer.
+ */
+ public void dump(Printer pw, String prefix) {
+ pw.println(prefix + "exceptionClassName: " + exceptionClassName);
+ pw.println(prefix + "throwFileName: " + throwFileName);
+ pw.println(prefix + "throwClassName: " + throwClassName);
+ pw.println(prefix + "throwMethodName: " + throwMethodName);
+ pw.println(prefix + "stackTrace: " + stackTrace);
+ }
+ }
+
+ /**
+ * Describes an application not responding error.
+ */
+ public static class AnrInfo {
+ /**
+ * Activity name.
+ */
+ public String activity;
+
+ /**
+ * Description of the operation that timed out.
+ */
+ public String cause;
+
+ /**
+ * Additional info, including CPU stats.
+ */
+ public String info;
+
+ /**
+ * Create an uninitialized instance of AnrInfo.
+ */
+ public AnrInfo() {
+ }
+
+ /**
+ * Create an instance of AnrInfo initialized from a Parcel.
+ */
+ public AnrInfo(Parcel in) {
+ activity = in.readString();
+ cause = in.readString();
+ info = in.readString();
+ }
+
+ /**
+ * Save an AnrInfo instance to a parcel.
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(activity);
+ dest.writeString(cause);
+ dest.writeString(info);
+ }
+
+ /**
+ * Dump an AnrInfo instance to a Printer.
+ */
+ public void dump(Printer pw, String prefix) {
+ pw.println(prefix + "activity: " + activity);
+ pw.println(prefix + "cause: " + cause);
+ pw.println(prefix + "info: " + info);
+ }
+ }
+
+ public static final Parcelable.Creator<ApplicationErrorReport> CREATOR
+ = new Parcelable.Creator<ApplicationErrorReport>() {
+ public ApplicationErrorReport createFromParcel(Parcel source) {
+ return new ApplicationErrorReport(source);
+ }
+
+ public ApplicationErrorReport[] newArray(int size) {
+ return new ApplicationErrorReport[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Dump the report to a Printer.
+ */
+ public void dump(Printer pw, String prefix) {
+ pw.println(prefix + "type: " + type);
+ pw.println(prefix + "packageName: " + packageName);
+ pw.println(prefix + "installerPackageName: " + installerPackageName);
+ pw.println(prefix + "processName: " + processName);
+ pw.println(prefix + "time: " + time);
+
+ switch (type) {
+ case TYPE_CRASH:
+ crashInfo.dump(pw, prefix);
+ break;
+ case TYPE_ANR:
+ anrInfo.dump(pw, prefix);
+ break;
+ }
+ }
+}
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 863cbcc..78bbb4f 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -46,7 +46,6 @@
private final DatePicker mDatePicker;
private final OnDateSetListener mCallBack;
private final Calendar mCalendar;
- private final java.text.DateFormat mDateFormat;
private final java.text.DateFormat mTitleDateFormat;
private final String[] mWeekDays;
@@ -108,7 +107,6 @@
DateFormatSymbols symbols = new DateFormatSymbols();
mWeekDays = symbols.getShortWeekdays();
- mDateFormat = DateFormat.getMediumDateFormat(context);
mTitleDateFormat = java.text.DateFormat.
getDateInstance(java.text.DateFormat.FULL);
mCalendar = Calendar.getInstance();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 56b29c1..d15a154 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -44,9 +44,30 @@
* {@hide}
*/
public interface IActivityManager extends IInterface {
+ /**
+ * Returned by startActivity() if the start request was canceled because
+ * app switches are temporarily canceled to ensure the user's last request
+ * (such as pressing home) is performed.
+ */
+ public static final int START_SWITCHES_CANCELED = 4;
+ /**
+ * Returned by startActivity() if an activity wasn't really started, but
+ * the given Intent was given to the existing top activity.
+ */
public static final int START_DELIVERED_TO_TOP = 3;
+ /**
+ * Returned by startActivity() if an activity wasn't really started, but
+ * a task was simply brought to the foreground.
+ */
public static final int START_TASK_TO_FRONT = 2;
+ /**
+ * Returned by startActivity() if the caller asked that the Intent not
+ * be executed if it is the recipient, and that is indeed the case.
+ */
public static final int START_RETURN_INTENT_TO_CALLER = 1;
+ /**
+ * Activity was started successfully as normal.
+ */
public static final int START_SUCCESS = 0;
public static final int START_INTENT_NOT_RESOLVED = -1;
public static final int START_CLASS_NOT_FOUND = -2;
@@ -225,6 +246,9 @@
public boolean shutdown(int timeout) throws RemoteException;
+ public void stopAppSwitches() throws RemoteException;
+ public void resumeAppSwitches() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -371,4 +395,6 @@
int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84;
int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85;
int SHUTDOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+86;
+ int STOP_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+87;
+ int RESUME_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+88;
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 343380c..aaaf7bf 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -31,7 +31,13 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationProvider;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
@@ -103,6 +109,7 @@
private Button mGoButton;
private ImageButton mVoiceButton;
private View mSearchPlate;
+ private AnimationDrawable mWorkingSpinner;
// interaction with searchable application
private SearchableInfo mSearchable;
@@ -143,6 +150,15 @@
private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
new WeakHashMap<String, Drawable>();
+ // Objects we keep around for requesting location updates when the dialog is started
+ // (and canceling them when the dialog is stopped). We don't actually make use of the
+ // updates ourselves here, so the LocationListener is just a dummy which doesn't do
+ // anything. We only do this here so that other suggest providers which wish to provide
+ // location-based suggestions are more likely to get a good fresh location.
+ private LocationManager mLocationManager;
+ private LocationProvider mLocationProvider;
+ private LocationListener mDummyLocationListener;
+
/**
* Constructor - fires it up and makes it look like the search UI.
*
@@ -182,6 +198,8 @@
mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn);
mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn);
mSearchPlate = findViewById(com.android.internal.R.id.search_plate);
+ mWorkingSpinner = (AnimationDrawable) getContext().getResources().
+ getDrawable(com.android.internal.R.drawable.search_spinner);
// attach listeners
mSearchAutoComplete.addTextChangedListener(mTextWatcher);
@@ -217,6 +235,37 @@
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+
+ mLocationManager =
+ (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
+
+ if (mLocationManager != null) {
+ Criteria criteria = new Criteria();
+ criteria.setAccuracy(Criteria.ACCURACY_COARSE);
+
+ String providerName = mLocationManager.getBestProvider(criteria, true);
+
+ if (providerName != null) {
+ mLocationProvider = mLocationManager.getProvider(providerName);
+ }
+
+ // Just a dumb listener that doesn't do anything - requesting location updates here
+ // is only intended to give location-based suggestion providers the best chance
+ // of getting a good fresh location.
+ mDummyLocationListener = new LocationListener() {
+ public void onLocationChanged(Location location) {
+ }
+
+ public void onProviderDisabled(String provider) {
+ }
+
+ public void onProviderEnabled(String provider) {
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+ };
+ }
}
/**
@@ -239,7 +288,6 @@
return doShow(initialQuery, selectInitialQuery, componentName, appSearchData, globalSearch);
}
-
/**
* Called in response to a press of the hard search button in
* {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app
@@ -360,6 +408,8 @@
// receive broadcasts
getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter);
getContext().registerReceiver(mBroadcastReceiver, mPackageFilter);
+
+ startLocationUpdates();
}
/**
@@ -372,6 +422,8 @@
public void onStop() {
super.onStop();
+ stopLocationUpdates();
+
// TODO: Removing the listeners means that they never get called, since
// Dialog.dismissDialog() calls onStop() before sendDismissMessage().
setOnCancelListener(null);
@@ -396,6 +448,43 @@
}
/**
+ * Asks the LocationManager for location updates so that it goes and gets a fresh location
+ * if needed.
+ */
+ private void startLocationUpdates() {
+ if (mLocationManager != null && mLocationProvider != null) {
+ mLocationManager.requestLocationUpdates(mLocationProvider.getName(),
+ 0, 0, mDummyLocationListener, getContext().getMainLooper());
+ }
+
+ }
+
+ /**
+ * Makes sure to stop listening for location updates to save battery.
+ */
+ private void stopLocationUpdates() {
+ mLocationManager.removeUpdates(mDummyLocationListener);
+ }
+
+ /**
+ * Sets the search dialog to the 'working' state, which shows a working spinner in the
+ * right hand size of the text field.
+ *
+ * @param working true to show spinner, false to hide spinner
+ */
+ public void setWorking(boolean working) {
+ if (working) {
+ mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, mWorkingSpinner, null);
+ mWorkingSpinner.start();
+ } else {
+ mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, null, null);
+ mWorkingSpinner.stop();
+ }
+ }
+
+ /**
* Closes and gets rid of the suggestions adapter.
*/
private void closeSuggestionsAdapter() {
@@ -563,8 +652,8 @@
// attach the suggestions adapter, if suggestions are available
// The existence of a suggestions authority is the proxy for "suggestions available here"
if (mSearchable.getSuggestAuthority() != null) {
- mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable,
- mOutsideDrawablesCache);
+ mSuggestionsAdapter = new SuggestionsAdapter(getContext(), this, mSearchable,
+ mOutsideDrawablesCache, mGlobalSearchMode);
mSearchAutoComplete.setAdapter(mSuggestionsAdapter);
}
}
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 6a02fc9..2fe9a8d 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -25,6 +25,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.server.search.SearchableInfo;
import android.text.Html;
import android.text.TextUtils;
@@ -45,12 +46,18 @@
* @hide
*/
class SuggestionsAdapter extends ResourceCursorAdapter {
+ // The value used to query a cursor whether it is still expecting more input,
+ // so we can correctly display (or not display) the 'working' spinner in the search dialog.
+ public static final String IS_WORKING = "isWorking";
+
private static final boolean DBG = false;
private static final String LOG_TAG = "SuggestionsAdapter";
+ private SearchDialog mSearchDialog;
private SearchableInfo mSearchable;
private Context mProviderContext;
private WeakHashMap<String, Drawable> mOutsideDrawablesCache;
+ private boolean mGlobalSearchMode;
// Cached column indexes, updated when the cursor changes.
private int mFormatCol;
@@ -61,12 +68,13 @@
private int mIconBitmap1Col;
private int mIconBitmap2Col;
- public SuggestionsAdapter(Context context, SearchableInfo searchable,
- WeakHashMap<String, Drawable> outsideDrawablesCache) {
+ public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable,
+ WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) {
super(context,
com.android.internal.R.layout.search_dropdown_item_icons_2line,
null, // no initial cursor
true); // auto-requery
+ mSearchDialog = searchDialog;
mSearchable = searchable;
// set up provider resources (gives us icons, etc.)
@@ -74,6 +82,7 @@
mProviderContext = mSearchable.getProviderContext(mContext, activityContext);
mOutsideDrawablesCache = outsideDrawablesCache;
+ mGlobalSearchMode = globalSearchMode;
}
/**
@@ -118,6 +127,28 @@
mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP);
mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP);
}
+ updateWorking();
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ updateWorking();
+ }
+
+ /**
+ * Updates the search dialog according to the current working status of the cursor.
+ */
+ private void updateWorking() {
+ if (!mGlobalSearchMode || mCursor == null) return;
+
+ Bundle request = new Bundle();
+ request.putString(SearchManager.EXTRA_DATA_KEY, IS_WORKING);
+ Bundle response = mCursor.respond(request);
+ if (response.containsKey(IS_WORKING)) {
+ boolean isWorking = response.getBoolean(IS_WORKING);
+ mSearchDialog.setWorking(isWorking);
+ }
}
/**
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index 555494e..25ae15b 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -22,24 +22,30 @@
/** @hide */
public class BackupDataOutput {
- /* package */ FileDescriptor fd;
+ int mBackupWriter;
+ private Context mContext;
public static final int OP_UPDATE = 1;
public static final int OP_DELETE = 2;
public BackupDataOutput(Context context, FileDescriptor fd) {
- this.fd = fd;
+ mContext = context;
+ if (fd == null) throw new NullPointerException();
+ mBackupWriter = ctor(fd);
+ if (mBackupWriter == 0) {
+ throw new RuntimeException("Native initialization failed with fd=" + fd);
+ }
}
- public void close() {
- // do we close the fd?
+ protected void finalize() throws Throwable {
+ try {
+ dtor(mBackupWriter);
+ } finally {
+ super.finalize();
+ }
}
- public native void flush();
- public native void write(byte[] buffer);
- public native void write(int oneByte);
- public native void write(byte[] buffer, int offset, int count);
-
- public native void writeOperation(int op);
- public native void writeKey(String key);
+
+ private native static int ctor(FileDescriptor fd);
+ private native static void dtor(int mBackupWriter);
}
diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java
index 05159dc..ec16eb1 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -53,15 +53,12 @@
}
// oldStateFd can be null
FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
- if (data.fd == null) {
- throw new NullPointerException();
- }
FileDescriptor newStateFd = newState.getFileDescriptor();
if (newStateFd == null) {
throw new NullPointerException();
}
- int err = performBackup_native(basePath, oldStateFd, data.fd, newStateFd, files);
+ int err = performBackup_native(basePath, oldStateFd, data.mBackupWriter, newStateFd, files);
if (err != 0) {
throw new RuntimeException("Backup failed"); // TODO: more here
@@ -69,5 +66,5 @@
}
native private static int performBackup_native(String basePath, FileDescriptor oldState,
- FileDescriptor data, FileDescriptor newState, String[] files);
+ int data, FileDescriptor newState, String[] files);
}
diff --git a/core/java/android/bluetooth/Database.java b/core/java/android/bluetooth/Database.java
deleted file mode 100644
index fef641a..0000000
--- a/core/java/android/bluetooth/Database.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.bluetooth;
-
-import android.bluetooth.RfcommSocket;
-
-import android.util.Log;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * A low-level API to the Service Discovery Protocol (SDP) Database.
- *
- * Allows service records to be added to the local SDP database. Once added,
- * these services will be advertised to remote devices when they make SDP
- * queries on this device.
- *
- * Currently this API is a thin wrapper to the bluez SDP Database API. See:
- * http://wiki.bluez.org/wiki/Database
- * http://wiki.bluez.org/wiki/HOWTO/ManagingServiceRecords
- * @hide
- */
-public final class Database {
- private static Database mInstance;
-
- private static final String sLogName = "android.bluetooth.Database";
-
- /**
- * Class load time initialization
- */
- static {
- classInitNative();
- }
- private native static void classInitNative();
-
- /**
- * Private to enforce singleton property
- */
- private Database() {
- initializeNativeDataNative();
- }
- private native void initializeNativeDataNative();
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- /**
- * Singelton accessor
- * @return The singleton instance of Database
- */
- public static synchronized Database getInstance() {
- if (mInstance == null) {
- mInstance = new Database();
- }
- return mInstance;
- }
-
- /**
- * Advertise a service with an RfcommSocket.
- *
- * This adds the service the SDP Database with the following attributes
- * set: Service Name, Protocol Descriptor List, Service Class ID List
- * TODO: Construct a byte[] record directly, rather than via XML.
- * @param socket The rfcomm socket to advertise (by channel).
- * @param serviceName A short name for this service
- * @param uuid
- * Unique identifier for this service, by which clients
- * can search for your service
- * @return Handle to the new service record
- */
- public int advertiseRfcommService(RfcommSocket socket,
- String serviceName,
- UUID uuid) throws IOException {
- String xmlRecord =
- "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
- "<record>\n" +
- " <attribute id=\"0x0001\">\n" + // ServiceClassIDList
- " <sequence>\n" +
- " <uuid value=\""
- + uuid.toString() + // UUID for this service
- "\"/>\n" +
- " </sequence>\n" +
- " </attribute>\n" +
- " <attribute id=\"0x0004\">\n" + // ProtocolDescriptorList
- " <sequence>\n" +
- " <sequence>\n" +
- " <uuid value=\"0x0100\"/>\n" + // L2CAP
- " </sequence>\n" +
- " <sequence>\n" +
- " <uuid value=\"0x0003\"/>\n" + // RFCOMM
- " <uint8 value=\"" +
- socket.getPort() + // RFCOMM port
- "\" name=\"channel\"/>\n" +
- " </sequence>\n" +
- " </sequence>\n" +
- " </attribute>\n" +
- " <attribute id=\"0x0100\">\n" + // ServiceName
- " <text value=\"" + serviceName + "\"/>\n" +
- " </attribute>\n" +
- "</record>\n";
- Log.i(sLogName, xmlRecord);
- return addServiceRecordFromXml(xmlRecord);
- }
-
-
- /**
- * Add a new service record.
- * @param record The byte[] record
- * @return A handle to the new record
- */
- public synchronized int addServiceRecord(byte[] record) throws IOException {
- int handle = addServiceRecordNative(record);
- Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
- return handle;
- }
- private native int addServiceRecordNative(byte[] record)
- throws IOException;
-
- /**
- * Add a new service record, using XML.
- * @param record The record as an XML string
- * @return A handle to the new record
- */
- public synchronized int addServiceRecordFromXml(String record) throws IOException {
- int handle = addServiceRecordFromXmlNative(record);
- Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
- return handle;
- }
- private native int addServiceRecordFromXmlNative(String record)
- throws IOException;
-
- /**
- * Update an exisiting service record.
- * @param handle Handle to exisiting record
- * @param record The updated byte[] record
- */
- public synchronized void updateServiceRecord(int handle, byte[] record) {
- try {
- updateServiceRecordNative(handle, record);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void updateServiceRecordNative(int handle, byte[] record)
- throws IOException;
-
- /**
- * Update an exisiting record, using XML.
- * @param handle Handle to exisiting record
- * @param record The record as an XML string.
- */
- public synchronized void updateServiceRecordFromXml(int handle, String record) {
- try {
- updateServiceRecordFromXmlNative(handle, record);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void updateServiceRecordFromXmlNative(int handle, String record)
- throws IOException;
-
- /**
- * Remove a service record.
- * It is only possible to remove service records that were added by the
- * current connection.
- * @param handle Handle to exisiting record to be removed
- */
- public synchronized void removeServiceRecord(int handle) {
- try {
- removeServiceRecordNative(handle);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void removeServiceRecordNative(int handle) throws IOException;
-}
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index 1452985..05781f4 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -17,6 +17,8 @@
import java.util.Map;
import java.util.Vector;
import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
import com.google.android.collect.Maps;
@@ -55,6 +57,9 @@
return mIsTemporary;
}
+ private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>();
+ private final ThreadLocal<Set<Uri>> mPendingBatchNotifications = new ThreadLocal<Set<Uri>>();
+
/**
* Indicates whether or not this ContentProvider contains a full
* set of data or just diffs. This knowledge comes in handy when
@@ -243,26 +248,37 @@
public final int update(final Uri url, final ContentValues values,
final String selection, final String[] selectionArgs) {
mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
+ final boolean notApplyingBatch = !applyingBatch();
+ if (notApplyingBatch) {
+ mDb.beginTransaction();
+ }
try {
if (isTemporary() && mSyncState.matches(url)) {
int numRows = mSyncState.asContentProvider().update(
url, values, selection, selectionArgs);
- mDb.setTransactionSuccessful();
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
+ }
return numRows;
}
int result = updateInternal(url, values, selection, selectionArgs);
- mDb.setTransactionSuccessful();
-
- if (!isTemporary() && result > 0) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
}
-
+ if (!isTemporary() && result > 0) {
+ if (notApplyingBatch) {
+ getContext().getContentResolver().notifyChange(url, null /* observer */,
+ changeRequiresLocalSync(url));
+ } else {
+ mPendingBatchNotifications.get().add(url);
+ }
+ }
return result;
} finally {
- mDb.endTransaction();
+ if (notApplyingBatch) {
+ mDb.endTransaction();
+ }
}
}
@@ -270,44 +286,74 @@
public final int delete(final Uri url, final String selection,
final String[] selectionArgs) {
mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
+ final boolean notApplyingBatch = !applyingBatch();
+ if (notApplyingBatch) {
+ mDb.beginTransaction();
+ }
try {
if (isTemporary() && mSyncState.matches(url)) {
int numRows = mSyncState.asContentProvider().delete(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
+ }
return numRows;
}
int result = deleteInternal(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
+ }
if (!isTemporary() && result > 0) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
+ if (notApplyingBatch) {
+ getContext().getContentResolver().notifyChange(url, null /* observer */,
+ changeRequiresLocalSync(url));
+ } else {
+ mPendingBatchNotifications.get().add(url);
+ }
}
return result;
} finally {
- mDb.endTransaction();
+ if (notApplyingBatch) {
+ mDb.endTransaction();
+ }
}
}
+ private boolean applyingBatch() {
+ return mApplyingBatch.get() != null && mApplyingBatch.get();
+ }
+
@Override
public final Uri insert(final Uri url, final ContentValues values) {
mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
+ final boolean notApplyingBatch = !applyingBatch();
+ if (notApplyingBatch) {
+ mDb.beginTransaction();
+ }
try {
if (isTemporary() && mSyncState.matches(url)) {
Uri result = mSyncState.asContentProvider().insert(url, values);
- mDb.setTransactionSuccessful();
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
+ }
return result;
}
Uri result = insertInternal(url, values);
- mDb.setTransactionSuccessful();
+ if (notApplyingBatch) {
+ mDb.setTransactionSuccessful();
+ }
if (!isTemporary() && result != null) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
+ if (notApplyingBatch) {
+ getContext().getContentResolver().notifyChange(url, null /* observer */,
+ changeRequiresLocalSync(url));
+ } else {
+ mPendingBatchNotifications.get().add(url);
+ }
}
return result;
} finally {
- mDb.endTransaction();
+ if (notApplyingBatch) {
+ mDb.endTransaction();
+ }
}
}
@@ -343,6 +389,92 @@
}
/**
+ * <p>
+ * Start batch transaction. {@link #endTransaction} MUST be called after
+ * calling this method. Those methods should be used like this:
+ * </p>
+ *
+ * <pre class="prettyprint">
+ * boolean successful = false;
+ * beginBatch()
+ * try {
+ * // Do something related to mDb
+ * successful = true;
+ * return ret;
+ * } finally {
+ * endBatch(successful);
+ * }
+ * </pre>
+ *
+ * @hide This method should be used only when {@link #applyBatch} is not enough and must be
+ * used with {@link #endBatch}.
+ * e.g. If returned value has to be used during one transaction, this method might be useful.
+ */
+ public final void beginBatch() {
+ // initialize if this is the first time this thread has applied a batch
+ if (mApplyingBatch.get() == null) {
+ mApplyingBatch.set(false);
+ mPendingBatchNotifications.set(new HashSet<Uri>());
+ }
+
+ if (applyingBatch()) {
+ throw new IllegalStateException(
+ "applyBatch is not reentrant but mApplyingBatch is already set");
+ }
+ SQLiteDatabase db = getDatabase();
+ db.beginTransaction();
+ boolean successful = false;
+ try {
+ mApplyingBatch.set(true);
+ successful = true;
+ } finally {
+ if (!successful) {
+ // Something unexpected happened. We must call endTransaction() at least.
+ db.endTransaction();
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Finish batch transaction. If "successful" is true, try to call
+ * mDb.setTransactionSuccessful() before calling mDb.endTransaction().
+ * This method MUST be used with {@link #beginBatch()}.
+ * </p>
+ *
+ * @hide This method must be used with {@link #beginTransaction}
+ */
+ public final void endBatch(boolean successful) {
+ try {
+ if (successful) {
+ // setTransactionSuccessful() must be called just once during opening the
+ // transaction.
+ mDb.setTransactionSuccessful();
+ }
+ } finally {
+ mApplyingBatch.set(false);
+ getDatabase().endTransaction();
+ for (Uri url : mPendingBatchNotifications.get()) {
+ getContext().getContentResolver().notifyChange(url, null /* observer */,
+ changeRequiresLocalSync(url));
+ }
+ }
+ }
+
+ public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+ throws OperationApplicationException {
+ boolean successful = false;
+ beginBatch();
+ try {
+ ContentProviderResult[] results = super.applyBatch(operations);
+ successful = true;
+ return results;
+ } finally {
+ endBatch(successful);
+ }
+ }
+
+ /**
* Check if changes to this URI can be syncable changes.
* @param uri the URI of the resource that was changed
* @return true if changes to this URI can be syncable changes, false otherwise
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 3a8de6e..c204dda 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -629,4 +629,26 @@
ContentProvider.this.onCreate();
}
}
-}
+
+ /**
+ * Applies each of the {@link ContentProviderOperation} objects and returns an array
+ * of their results. Passes through OperationApplicationException, which may be thrown
+ * by the call to {@link ContentProviderOperation#apply}.
+ * If all the applications succeed then a {@link ContentProviderResult} array with the
+ * same number of elements as the operations will be returned. It is implementation-specific
+ * how many, if any, operations will have been successfully applied if a call to
+ * apply results in a {@link OperationApplicationException}.
+ * @param operations the operations to apply
+ * @return the results of the applications
+ * @throws OperationApplicationException thrown if an application fails.
+ * See {@link ContentProviderOperation#apply} for more information.
+ */
+ public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+ throws OperationApplicationException {
+ ContentProviderResult[] results = new ContentProviderResult[operations.length];
+ for (int i = 0; i < operations.length; i++) {
+ results[i] = operations[i].apply(this, results, i);
+ }
+ return results;
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
new file mode 100644
index 0000000..148cc35
--- /dev/null
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -0,0 +1,358 @@
+/*
+ * 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 android.content;
+
+import android.net.Uri;
+import android.database.Cursor;
+
+import java.util.Map;
+
+public class ContentProviderOperation {
+ private final static int TYPE_INSERT = 1;
+ private final static int TYPE_UPDATE = 2;
+ private final static int TYPE_DELETE = 3;
+ private final static int TYPE_COUNT = 4;
+
+ private final int mType;
+ private final Uri mUri;
+ private final String mSelection;
+ private final String[] mSelectionArgs;
+ private final ContentValues mValues;
+ private final Integer mExpectedCount;
+ private final ContentValues mValuesBackReferences;
+ private final Map<Integer, Integer> mSelectionArgsBackReferences;
+
+ private static final String[] COUNT_COLUMNS = new String[]{"count(*)"};
+
+ /**
+ * Creates a {@link ContentProviderOperation} by copying the contents of a
+ * {@link Builder}.
+ */
+ private ContentProviderOperation(Builder builder) {
+ mType = builder.mType;
+ mUri = builder.mUri;
+ mValues = builder.mValues;
+ mSelection = builder.mSelection;
+ mSelectionArgs = builder.mSelectionArgs;
+ mExpectedCount = builder.mExpectedCount;
+ mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
+ mValuesBackReferences = builder.mValuesBackReferences;
+ }
+
+ /**
+ * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}.
+ * @param uri The {@link Uri} that is the target of the insert.
+ * @return a {@link Builder}
+ */
+ public static Builder newInsert(Uri uri) {
+ return new Builder(TYPE_INSERT, uri);
+ }
+
+ /**
+ * Create a {@link Builder} suitable for building an update {@link ContentProviderOperation}.
+ * @param uri The {@link Uri} that is the target of the update.
+ * @return a {@link Builder}
+ */
+ public static Builder newUpdate(Uri uri) {
+ return new Builder(TYPE_UPDATE, uri);
+ }
+
+ /**
+ * Create a {@link Builder} suitable for building a delete {@link ContentProviderOperation}.
+ * @param uri The {@link Uri} that is the target of the delete.
+ * @return a {@link Builder}
+ */
+ public static Builder newDelete(Uri uri) {
+ return new Builder(TYPE_DELETE, uri);
+ }
+
+ /**
+ * Create a {@link Builder} suitable for building a count query. When used in conjunction
+ * with {@link Builder#withExpectedCount(int)} this is useful for checking that the
+ * uri/selection has the expected number of rows.
+ * {@link ContentProviderOperation}.
+ * @param uri The {@link Uri} to query.
+ * @return a {@link Builder}
+ */
+ public static Builder newCountQuery(Uri uri) {
+ return new Builder(TYPE_COUNT, uri);
+ }
+
+ /**
+ * Applies this operation using the given provider. The backRefs array is used to resolve any
+ * back references that were requested using
+ * {@link Builder#withValueBackReferences(ContentValues)} and
+ * {@link Builder#withSelectionBackReferences(java.util.Map)}.
+ * @param provider the {@link ContentProvider} on which this batch is applied
+ * @param backRefs a {@link ContentProviderResult} array that will be consulted
+ * to resolve any requested back references.
+ * @param numBackRefs the number of valid results on the backRefs array.
+ * @return a {@link ContentProviderResult} that contains either the {@link Uri} of the inserted
+ * row if this was an insert otherwise the number of rows affected.
+ * @throws OperationApplicationException thrown if either the insert fails or
+ * if the number of rows affected didn't match the expected count
+ */
+ public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs,
+ int numBackRefs) throws OperationApplicationException {
+ ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
+ String[] selectionArgs =
+ resolveSelectionArgsBackReferences(backRefs, numBackRefs);
+
+ if (mType == TYPE_INSERT) {
+ Uri newUri = provider.insert(mUri, values);
+ if (newUri == null) {
+ throw new OperationApplicationException("insert failed");
+ }
+ return new ContentProviderResult(newUri);
+ }
+
+ int numRows;
+ if (mType == TYPE_DELETE) {
+ numRows = provider.delete(mUri, mSelection, selectionArgs);
+ } else if (mType == TYPE_UPDATE) {
+ numRows = provider.update(mUri, values, mSelection, selectionArgs);
+ } else if (mType == TYPE_COUNT) {
+ Cursor cursor = provider.query(mUri, COUNT_COLUMNS, mSelection, selectionArgs, null);
+ try {
+ if (!cursor.moveToNext()) {
+ throw new RuntimeException("since we are doing a count query we should always "
+ + "be able to move to the first row");
+ }
+ if (cursor.getCount() != 1) {
+ throw new RuntimeException("since we are doing a count query there should "
+ + "always be exacly row, found " + cursor.getCount());
+ }
+ numRows = cursor.getInt(0);
+ } finally {
+ cursor.close();
+ }
+ } else {
+ throw new IllegalStateException("bad type, " + mType);
+ }
+
+ if (mExpectedCount != null && mExpectedCount != numRows) {
+ throw new OperationApplicationException("wrong number of rows: " + numRows);
+ }
+
+ return new ContentProviderResult(numRows);
+ }
+
+ /**
+ * The ContentValues back references are represented as a ContentValues object where the
+ * key refers to a column and the value is an index of the back reference whose
+ * valued should be associated with the column.
+ * @param backRefs an array of previous results
+ * @param numBackRefs the number of valid previous results in backRefs
+ * @return the ContentValues that should be used in this operation application after
+ * expansion of back references. This can be called if either mValues or mValuesBackReferences
+ * is null
+ * @VisibleForTesting this is intended to be a private method but it is exposed for
+ * unit testing purposes
+ */
+ public ContentValues resolveValueBackReferences(
+ ContentProviderResult[] backRefs, int numBackRefs) {
+ if (mValuesBackReferences == null) {
+ return mValues;
+ }
+ final ContentValues values;
+ if (mValues == null) {
+ values = new ContentValues();
+ } else {
+ values = new ContentValues(mValues);
+ }
+ for (Map.Entry<String, Object> entry : mValuesBackReferences.valueSet()) {
+ String key = entry.getKey();
+ Integer backRefIndex = mValuesBackReferences.getAsInteger(key);
+ if (backRefIndex == null) {
+ throw new IllegalArgumentException("values backref " + key + " is not an integer");
+ }
+ values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex));
+ }
+ return values;
+ }
+
+ /**
+ * The Selection Arguments back references are represented as a Map of Integer->Integer where
+ * the key is an index into the selection argument array (see {@link Builder#withSelection})
+ * and the value is the index of the previous result that should be used for that selection
+ * argument array slot.
+ * @param backRefs an array of previous results
+ * @param numBackRefs the number of valid previous results in backRefs
+ * @return the ContentValues that should be used in this operation application after
+ * expansion of back references. This can be called if either mValues or mValuesBackReferences
+ * is null
+ * @VisibleForTesting this is intended to be a private method but it is exposed for
+ * unit testing purposes
+ */
+ public String[] resolveSelectionArgsBackReferences(
+ ContentProviderResult[] backRefs, int numBackRefs) {
+ if (mSelectionArgsBackReferences == null) {
+ return mSelectionArgs;
+ }
+ String[] newArgs = new String[mSelectionArgs.length];
+ System.arraycopy(mSelectionArgs, 0, newArgs, 0, mSelectionArgs.length);
+ for (Map.Entry<Integer, Integer> selectionArgBackRef
+ : mSelectionArgsBackReferences.entrySet()) {
+ final Integer selectionArgIndex = selectionArgBackRef.getKey();
+ final int backRefIndex = selectionArgBackRef.getValue();
+ newArgs[selectionArgIndex] = backRefToValue(backRefs, numBackRefs, backRefIndex);
+ }
+ return newArgs;
+ }
+
+ /**
+ * Return the string representation of the requested back reference.
+ * @param backRefs an array of results
+ * @param numBackRefs the number of items in the backRefs array that are valid
+ * @param backRefIndex which backRef to be used
+ * @throws ArrayIndexOutOfBoundsException thrown if the backRefIndex is larger than
+ * the numBackRefs
+ * @return the string representation of the requested back reference.
+ */
+ private static String backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
+ Integer backRefIndex) {
+ if (backRefIndex > numBackRefs) {
+ throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex
+ + " but there are only " + numBackRefs + " back refs");
+ }
+ ContentProviderResult backRef = backRefs[backRefIndex];
+ String backRefValue;
+ if (backRef.uri != null) {
+ backRefValue = backRef.uri.getLastPathSegment();
+ } else {
+ backRefValue = String.valueOf(backRef.count);
+ }
+ return backRefValue;
+ }
+
+ /**
+ * Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
+ * first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
+ * {@link ContentProviderOperation#newUpdate(android.net.Uri)},
+ * {@link ContentProviderOperation#newDelete(android.net.Uri)} or
+ * {@link ContentProviderOperation#newCountQuery(android.net.Uri)}. The withXXX methods
+ * can then be used to add parameters to the builder. See the specific methods to find for
+ * which {@link Builder} type each is allowed. Call {@link #build} to create the
+ * {@link ContentProviderOperation} once all the parameters have been supplied.
+ */
+ public static class Builder {
+ private final int mType;
+ private final Uri mUri;
+ private String mSelection;
+ private String[] mSelectionArgs;
+ private ContentValues mValues;
+ private Integer mExpectedCount;
+ private ContentValues mValuesBackReferences;
+ private Map<Integer, Integer> mSelectionArgsBackReferences;
+
+ /** Create a {@link Builder} of a given type. The uri must not be null. */
+ private Builder(int type, Uri uri) {
+ if (uri == null) {
+ throw new IllegalArgumentException("uri must not be null");
+ }
+ mType = type;
+ mUri = uri;
+ }
+
+ /** Create a ContentroviderOperation from this {@link Builder}. */
+ public ContentProviderOperation build() {
+ return new ContentProviderOperation(this);
+ }
+
+ /**
+ * Add a {@link ContentValues} of back references. The key is the name of the column
+ * and the value is an integer that is the index of the previous result whose
+ * value should be used for the column. The value is added as a {@link String}.
+ * A column value from the back references takes precedence over a value specified in
+ * {@link #withValues}.
+ * This can only be used with builders of type insert or update.
+ * @return this builder, to allow for chaining.
+ */
+ public Builder withValueBackReferences(ContentValues backReferences) {
+ if (mType != TYPE_INSERT && mType != TYPE_UPDATE) {
+ throw new IllegalArgumentException(
+ "only inserts and updates can have value back-references");
+ }
+ mValuesBackReferences = backReferences;
+ return this;
+ }
+
+ /**
+ * Add a {@link Map} of back references. The integer key is the index of the selection arg
+ * to set and the integer value is the index of the previous result whose
+ * value should be used for the arg. If any value at that index of the selection arg
+ * that was specified by {@likn withSelection} will be overwritten.
+ * This can only be used with builders of type update, delete, or count query.
+ * @return this builder, to allow for chaining.
+ */
+ public Builder withSelectionBackReferences(Map<Integer, Integer> backReferences) {
+ if (mType != TYPE_COUNT && mType != TYPE_UPDATE && mType != TYPE_DELETE) {
+ throw new IllegalArgumentException(
+ "only deletes, updates and counts can have selection back-references");
+ }
+ mSelectionArgsBackReferences = backReferences;
+ return this;
+ }
+
+ /**
+ * The ContentValues to use. This may be null. These values may be overwritten by
+ * the corresponding value specified by {@link #withValueBackReferences(ContentValues)}.
+ * This can only be used with builders of type insert or update.
+ * @return this builder, to allow for chaining.
+ */
+ public Builder withValues(ContentValues values) {
+ if (mType != TYPE_INSERT && mType != TYPE_UPDATE) {
+ throw new IllegalArgumentException("only inserts and updates can have values");
+ }
+ mValues = values;
+ return this;
+ }
+
+ /**
+ * The selection and arguments to use. An occurrence of '?' in the selection will be
+ * replaced with the corresponding occurence of the selection argument. Any of the
+ * selection arguments may be overwritten by a selection argument back reference as
+ * specified by {@link #withSelectionBackReferences}.
+ * This can only be used with builders of type update, delete, or count query.
+ * @return this builder, to allow for chaining.
+ */
+ public Builder withSelection(String selection, String[] selectionArgs) {
+ if (mType != TYPE_DELETE && mType != TYPE_UPDATE && mType != TYPE_COUNT) {
+ throw new IllegalArgumentException(
+ "only deletes, updates and counts can have selections");
+ }
+ mSelection = selection;
+ mSelectionArgs = selectionArgs;
+ return this;
+ }
+
+ /**
+ * If set then if the number of rows affected by this operation do not match
+ * this count {@link OperationApplicationException} will be throw.
+ * This can only be used with builders of type update, delete, or count query.
+ * @return this builder, to allow for chaining.
+ */
+ public Builder withExpectedCount(int count) {
+ if (mType != TYPE_DELETE && mType != TYPE_UPDATE && mType != TYPE_COUNT) {
+ throw new IllegalArgumentException(
+ "only deletes, updates and counts can have expected counts");
+ }
+ mExpectedCount = count;
+ return this;
+ }
+ }
+}
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
new file mode 100644
index 0000000..2e34e40
--- /dev/null
+++ b/core/java/android/content/ContentProviderResult.java
@@ -0,0 +1,39 @@
+/*
+ * 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 android.content;
+
+import android.net.Uri;
+
+/**
+ * Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
+ * to have exactly one of {@link #uri} or {@link #count} set.
+ */
+public class ContentProviderResult {
+ public final Uri uri;
+ public final Integer count;
+
+ public ContentProviderResult(Uri uri) {
+ if (uri == null) throw new IllegalArgumentException("uri must not be null");
+ this.uri = uri;
+ this.count = null;
+ }
+
+ public ContentProviderResult(int count) {
+ this.count = count;
+ this.uri = null;
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/content/OperationApplicationException.java b/core/java/android/content/OperationApplicationException.java
new file mode 100644
index 0000000..d4101bf
--- /dev/null
+++ b/core/java/android/content/OperationApplicationException.java
@@ -0,0 +1,36 @@
+/*
+ * 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 android.content;
+
+/**
+ * Thrown when an application of a {@link ContentProviderOperation} fails due the specified
+ * constraints.
+ */
+public class OperationApplicationException extends Exception {
+ public OperationApplicationException() {
+ super();
+ }
+ public OperationApplicationException(String message) {
+ super(message);
+ }
+ public OperationApplicationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ public OperationApplicationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 88ac04c..ad022e7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -123,13 +123,7 @@
* Value for {@link #flags}: this is set of the application has set
* its android:targetSdkVersion to something >= the current SDK version.
*/
- public static final int FLAG_TARGETS_SDK = 1<<8;
-
- /**
- * Value for {@link #flags}: this is set of the application has set
- * its android:targetSdkVersion to something >= the current SDK version.
- */
- public static final int FLAG_TEST_ONLY = 1<<9;
+ public static final int FLAG_TEST_ONLY = 1<<8;
/**
* Flags associated with the application. Any combination of
@@ -137,7 +131,7 @@
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
* {@link #FLAG_ALLOW_TASK_REPARENTING}
* {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
- * {@link #FLAG_TARGETS_SDK}.
+ * {@link #FLAG_TEST_ONLY}.
*/
public int flags = 0;
@@ -182,6 +176,16 @@
public int[] supportsDensities;
/**
+ * The minimum SDK version this application targets. It may run on earilier
+ * versions, but it knows how to work with any new behavior added at this
+ * version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
+ * if this is a development build and the app is targeting that. You should
+ * compare that this number is >= the SDK version number at which your
+ * behavior was introduced.
+ */
+ public int targetSdkVersion;
+
+ /**
* When false, indicates that all components within this application are
* considered disabled, regardless of their individually set enabled status.
*/
@@ -200,6 +204,7 @@
pw.println(prefix + "publicSourceDir=" + publicSourceDir);
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
pw.println(prefix + "dataDir=" + dataDir);
+ pw.println(prefix + "targetSdkVersion=" + targetSdkVersion);
pw.println(prefix + "enabled=" + enabled);
pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
@@ -246,6 +251,7 @@
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
uid = orig.uid;
+ targetSdkVersion = orig.targetSdkVersion;
enabled = orig.enabled;
manageSpaceActivityName = orig.manageSpaceActivityName;
descriptionRes = orig.descriptionRes;
@@ -276,6 +282,7 @@
dest.writeStringArray(sharedLibraryFiles);
dest.writeString(dataDir);
dest.writeInt(uid);
+ dest.writeInt(targetSdkVersion);
dest.writeInt(enabled ? 1 : 0);
dest.writeString(manageSpaceActivityName);
dest.writeInt(descriptionRes);
@@ -305,6 +312,7 @@
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
uid = source.readInt();
+ targetSdkVersion = source.readInt();
enabled = source.readInt() != 0;
manageSpaceActivityName = source.readString();
descriptionRes = source.readInt();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 88907c1..78462f1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -55,6 +55,30 @@
* {@hide}
*/
public class PackageParser {
+ /** @hide */
+ public static class NewPermissionInfo {
+ public final String name;
+ public final int sdkVersion;
+ public final int fileVersion;
+
+ public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
+ this.name = name;
+ this.sdkVersion = sdkVersion;
+ this.fileVersion = fileVersion;
+ }
+ }
+
+ /**
+ * List of new permissions that have been added since 1.0.
+ * NOTE: These must be declared in SDK version order, with permissions
+ * added to older SDKs appearing before those added to newer SDKs.
+ * @hide
+ */
+ public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = new PackageParser.NewPermissionInfo[] {
+ new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
+ android.os.Build.VERSION_CODES.DONUT,
+ 0)
+ };
private String mArchiveSourcePath;
private String[] mSeparateProcesses;
@@ -616,7 +640,6 @@
final Package pkg = new Package(pkgName);
boolean foundApp = false;
- boolean targetsSdk = false;
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
@@ -774,11 +797,10 @@
return null;
}
// If the code matches, it definitely targets this SDK.
- targetsSdk = true;
- } else if (targetVers >= mSdkVersion) {
- // If they have explicitly targeted our current version
- // or something after it, then note this.
- targetsSdk = true;
+ pkg.applicationInfo.targetSdkVersion
+ = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
+ } else {
+ pkg.applicationInfo.targetSdkVersion = targetVers;
}
if (minVers > mSdkVersion) {
@@ -824,8 +846,18 @@
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
}
- if (targetsSdk) {
- pkg.applicationInfo.flags |= ApplicationInfo.FLAG_TARGETS_SDK;
+ final int NP = PackageParser.NEW_PERMISSIONS.length;
+ for (int ip=0; ip<NP; ip++) {
+ final PackageParser.NewPermissionInfo npi
+ = PackageParser.NEW_PERMISSIONS[ip];
+ if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
+ break;
+ }
+ if (!pkg.requestedPermissions.contains(npi.name)) {
+ Log.i(TAG, "Impliciting adding " + npi.name + " to old pkg "
+ + pkg.packageName);
+ pkg.requestedPermissions.add(npi.name);
+ }
}
if (pkg.usesLibraries.size() > 0) {
diff --git a/core/java/android/gesture/Gesture.java b/core/java/android/gesture/Gesture.java
new file mode 100755
index 0000000..14530a1
--- /dev/null
+++ b/core/java/android/gesture/Gesture.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+
+/**
+ * A gesture can have a single or multiple strokes
+ */
+
+public class Gesture implements Parcelable {
+ private static final long GESTURE_ID_BASE = System.currentTimeMillis();
+
+ private static final int BITMAP_RENDERING_WIDTH = 2;
+
+ private static final boolean BITMAP_RENDERING_ANTIALIAS = true;
+ private static final boolean BITMAP_RENDERING_DITHER = true;
+
+ private static int sGestureCount = 0;
+
+ private RectF mBoundingBox;
+
+ // the same as its instance ID
+ private long mGestureID;
+
+ private final ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
+
+ public Gesture() {
+ mGestureID = GESTURE_ID_BASE + sGestureCount++;
+ }
+
+ /**
+ * @return all the strokes of the gesture
+ */
+ public ArrayList<GestureStroke> getStrokes() {
+ return mStrokes;
+ }
+
+ /**
+ * @return the number of strokes included by this gesture
+ */
+ public int getStrokesCount() {
+ return mStrokes.size();
+ }
+
+ /**
+ * Add a stroke to the gesture
+ *
+ * @param stroke
+ */
+ public void addStroke(GestureStroke stroke) {
+ mStrokes.add(stroke);
+
+ if (mBoundingBox == null) {
+ mBoundingBox = new RectF(stroke.boundingBox);
+ } else {
+ mBoundingBox.union(stroke.boundingBox);
+ }
+ }
+
+ /**
+ * Get the total length of the gesture. When there are multiple strokes in
+ * the gesture, this returns the sum of the lengths of all the strokes
+ *
+ * @return the length of the gesture
+ */
+ public float getLength() {
+ int len = 0;
+ final ArrayList<GestureStroke> strokes = mStrokes;
+ final int count = strokes.size();
+
+ for (int i = 0; i < count; i++) {
+ len += strokes.get(i).length;
+ }
+
+ return len;
+ }
+
+ /**
+ * @return the bounding box of the gesture
+ */
+ public RectF getBoundingBox() {
+ return mBoundingBox;
+ }
+
+ /**
+ * Set the id of the gesture
+ *
+ * @param id
+ */
+ void setID(long id) {
+ mGestureID = id;
+ }
+
+ /**
+ * @return the id of the gesture
+ */
+ public long getID() {
+ return mGestureID;
+ }
+
+ /**
+ * draw the gesture
+ *
+ * @param canvas
+ */
+ void draw(Canvas canvas, Paint paint) {
+ final ArrayList<GestureStroke> strokes = mStrokes;
+ final int count = strokes.size();
+
+ for (int i = 0; i < count; i++) {
+ strokes.get(i).draw(canvas, paint);
+ }
+ }
+
+ /**
+ * Create a bitmap of the gesture with a transparent background
+ *
+ * @param width width of the target bitmap
+ * @param height height of the target bitmap
+ * @param edge the edge
+ * @param numSample
+ * @param color
+ * @return the bitmap
+ */
+ public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
+ final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(bitmap);
+
+ canvas.translate(edge, edge);
+
+ final Paint paint = new Paint();
+ paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
+ paint.setDither(BITMAP_RENDERING_DITHER);
+ paint.setColor(color);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeJoin(Paint.Join.ROUND);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
+
+ final ArrayList<GestureStroke> strokes = mStrokes;
+ final int count = strokes.size();
+
+ for (int i = 0; i < count; i++) {
+ Path path = strokes.get(i).toPath(width - 2 * edge, height - 2 * edge, numSample);
+ canvas.drawPath(path, paint);
+ }
+
+ return bitmap;
+ }
+
+ /**
+ * Create a bitmap of the gesture with a transparent background
+ *
+ * @param width
+ * @param height
+ * @param edge
+ * @param color
+ * @return the bitmap
+ */
+ public Bitmap toBitmap(int width, int height, int edge, int color) {
+ final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(bitmap);
+
+ canvas.translate(edge, edge);
+
+ final Paint paint = new Paint();
+ paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
+ paint.setDither(BITMAP_RENDERING_DITHER);
+ paint.setColor(color);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeJoin(Paint.Join.ROUND);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
+
+ final ArrayList<GestureStroke> strokes = mStrokes;
+ final int count = strokes.size();
+
+ for (int i = 0; i < count; i++) {
+ strokes.get(i).draw(canvas, paint);
+ }
+
+ return bitmap;
+ }
+
+ void serialize(DataOutputStream out) throws IOException {
+ final ArrayList<GestureStroke> strokes = mStrokes;
+ final int count = strokes.size();
+
+ // Write gesture ID
+ out.writeLong(mGestureID);
+ // Write number of strokes
+ out.writeInt(count);
+
+ for (int i = 0; i < count; i++) {
+ strokes.get(i).serialize(out);
+ }
+ }
+
+ static Gesture deserialize(DataInputStream in) throws IOException {
+ final Gesture gesture = new Gesture();
+
+ // Gesture ID
+ gesture.mGestureID = in.readLong();
+ // Number of strokes
+ final int count = in.readInt();
+
+ for (int i = 0; i < count; i++) {
+ gesture.addStroke(GestureStroke.deserialize(in));
+ }
+
+ return gesture;
+ }
+
+ public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
+ public Gesture createFromParcel(Parcel in) {
+ Gesture gesture = null;
+ final long gestureID = in.readLong();
+
+ final DataInputStream inStream = new DataInputStream(
+ new ByteArrayInputStream(in.createByteArray()));
+
+ try {
+ gesture = deserialize(inStream);
+ } catch (IOException e) {
+ Log.e(GestureConstants.LOG_TAG, "Error reading Gesture from parcel:", e);
+ } finally {
+ GestureUtilities.closeStream(inStream);
+ }
+
+ if (gesture != null) {
+ gesture.mGestureID = gestureID;
+ }
+
+ return gesture;
+ }
+
+ public Gesture[] newArray(int size) {
+ return new Gesture[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(mGestureID);
+
+ boolean result = false;
+ final ByteArrayOutputStream byteStream =
+ new ByteArrayOutputStream(GestureConstants.IO_BUFFER_SIZE);
+ final DataOutputStream outStream = new DataOutputStream(byteStream);
+
+ try {
+ serialize(outStream);
+ result = true;
+ } catch (IOException e) {
+ Log.e(GestureConstants.LOG_TAG, "Error writing Gesture to parcel:", e);
+ } finally {
+ GestureUtilities.closeStream(outStream);
+ GestureUtilities.closeStream(byteStream);
+ }
+
+ if (result) {
+ out.writeByteArray(byteStream.toByteArray());
+ }
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+}
+
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/core/java/android/gesture/GestureConstants.java
old mode 100755
new mode 100644
similarity index 61%
copy from tests/sketch/src/com/android/gesture/GestureListener.java
copy to core/java/android/gesture/GestureConstants.java
index ebb4149..230db0c
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/core/java/android/gesture/GestureConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * 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.
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package com.android.gesture;
+package android.gesture;
-import android.view.MotionEvent;
+interface GestureConstants {
+ static final int STROKE_STRING_BUFFER_SIZE = 1024;
+ static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
-public interface GestureListener {
- public void onStartGesture(GesturePad pad, MotionEvent event);
- public void onGesture(GesturePad pad, MotionEvent event);
- public void onFinishGesture(GesturePad pad, MotionEvent event);
+ static final int IO_BUFFER_SIZE = 32 * 1024; // 32K
+
+ static final String LOG_TAG = "Gestures";
}
diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java
new file mode 100644
index 0000000..1cf192e
--- /dev/null
+++ b/core/java/android/gesture/GestureLibrary.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.util.Log;
+import android.os.SystemClock;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map;
+
+import static android.gesture.GestureConstants.LOG_TAG;
+
+/**
+ * GestureLibrary maintains gesture examples and makes predictions on a new
+ * gesture
+ */
+//
+// File format for GestureLibrary:
+//
+// Nb. bytes Java type Description
+// -----------------------------------
+// Header
+// 2 bytes short File format version number
+// 4 bytes int Number of entries
+// Entry
+// X bytes UTF String Entry name
+// 4 bytes int Number of gestures
+// Gesture
+// 8 bytes long Gesture ID
+// 4 bytes int Number of strokes
+// Stroke
+// 4 bytes int Number of points
+// Point
+// 4 bytes float X coordinate of the point
+// 4 bytes float Y coordinate of the point
+// 8 bytes long Time stamp
+//
+public class GestureLibrary {
+ public static final int SEQUENCE_INVARIANT = 1;
+ // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
+ public static final int SEQUENCE_SENSITIVE = 2;
+
+ // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
+ public static final int ORIENTATION_INVARIANT = 1;
+ public static final int ORIENTATION_SENSITIVE = 2;
+
+ private static final short FILE_FORMAT_VERSION = 1;
+
+ private static final boolean PROFILE_LOADING_SAVING = false;
+
+ private int mSequenceType = SEQUENCE_SENSITIVE;
+ private int mOrientationStyle = ORIENTATION_SENSITIVE;
+
+ private final String mGestureFileName;
+
+ private final HashMap<String, ArrayList<Gesture>> mNamedGestures =
+ new HashMap<String, ArrayList<Gesture>>();
+
+ private Learner mClassifier;
+
+ private boolean mChanged = false;
+
+ /**
+ * @param path where gesture data is stored
+ */
+ public GestureLibrary(String path) {
+ mGestureFileName = path;
+ mClassifier = new InstanceLearner();
+ }
+
+ /**
+ * Specify how the gesture library will handle orientation.
+ * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
+ *
+ * @param style
+ */
+ public void setOrientationStyle(int style) {
+ mOrientationStyle = style;
+ }
+
+ public int getOrientationStyle() {
+ return mOrientationStyle;
+ }
+
+ /**
+ * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
+ */
+ public void setSequenceType(int type) {
+ mSequenceType = type;
+ }
+
+ /**
+ * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
+ */
+ public int getSequenceType() {
+ return mSequenceType;
+ }
+
+ /**
+ * Get all the gesture entry names in the library
+ *
+ * @return a set of strings
+ */
+ public Set<String> getGestureEntries() {
+ return mNamedGestures.keySet();
+ }
+
+ /**
+ * Recognize a gesture
+ *
+ * @param gesture the query
+ * @return a list of predictions of possible entries for a given gesture
+ */
+ public ArrayList<Prediction> recognize(Gesture gesture) {
+ Instance instance = Instance.createInstance(mSequenceType, gesture, null);
+ return mClassifier.classify(mSequenceType, instance.vector);
+ }
+
+ /**
+ * Add a gesture for the entry
+ *
+ * @param entryName entry name
+ * @param gesture
+ */
+ public void addGesture(String entryName, Gesture gesture) {
+ if (entryName == null || entryName.length() == 0) {
+ return;
+ }
+ ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+ if (gestures == null) {
+ gestures = new ArrayList<Gesture>();
+ mNamedGestures.put(entryName, gestures);
+ }
+ gestures.add(gesture);
+ mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName));
+ mChanged = true;
+ }
+
+ /**
+ * Remove a gesture from the library. If there are no more gestures for the
+ * given entry, the gesture entry will be removed.
+ *
+ * @param entryName entry name
+ * @param gesture
+ */
+ public void removeGesture(String entryName, Gesture gesture) {
+ ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+ if (gestures == null) {
+ return;
+ }
+
+ gestures.remove(gesture);
+
+ // if there are no more samples, remove the entry automatically
+ if (gestures.isEmpty()) {
+ mNamedGestures.remove(entryName);
+ }
+
+ mClassifier.removeInstance(gesture.getID());
+
+ mChanged = true;
+ }
+
+ /**
+ * Remove a entry of gestures
+ *
+ * @param entryName the entry name
+ */
+ public void removeEntry(String entryName) {
+ mNamedGestures.remove(entryName);
+ mClassifier.removeInstances(entryName);
+ mChanged = true;
+ }
+
+ /**
+ * Get all the gestures of an entry
+ *
+ * @param entryName
+ * @return the list of gestures that is under this name
+ */
+ public ArrayList<Gesture> getGestures(String entryName) {
+ ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+ if (gestures != null) {
+ return new ArrayList<Gesture>(gestures);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Save the gesture library
+ */
+ public boolean save() {
+ if (!mChanged) {
+ return true;
+ }
+
+ boolean result = false;
+ DataOutputStream out = null;
+
+ try {
+ File file = new File(mGestureFileName);
+ if (!file.getParentFile().exists()) {
+ if (!file.getParentFile().mkdirs()) {
+ return false;
+ }
+ }
+
+ long start;
+ if (PROFILE_LOADING_SAVING) {
+ start = SystemClock.elapsedRealtime();
+ }
+
+ final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures;
+
+ out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file),
+ GestureConstants.IO_BUFFER_SIZE));
+ // Write version number
+ out.writeShort(FILE_FORMAT_VERSION);
+ // Write number of entries
+ out.writeInt(maps.size());
+
+ for (Map.Entry<String, ArrayList<Gesture>> entry : maps.entrySet()) {
+ final String key = entry.getKey();
+ final ArrayList<Gesture> examples = entry.getValue();
+ final int count = examples.size();
+
+ // Write entry name
+ out.writeUTF(key);
+ // Write number of examples for this entry
+ out.writeInt(count);
+
+ for (int i = 0; i < count; i++) {
+ examples.get(i).serialize(out);
+ }
+ }
+
+ out.flush();
+
+ if (PROFILE_LOADING_SAVING) {
+ long end = SystemClock.elapsedRealtime();
+ Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms");
+ }
+
+ mChanged = false;
+ result = true;
+ } catch (IOException ex) {
+ Log.d(LOG_TAG, "Failed to save gestures:", ex);
+ } finally {
+ GestureUtilities.closeStream(out);
+ }
+
+ return result;
+ }
+
+ /**
+ * Load the gesture library
+ */
+ public boolean load() {
+ boolean result = false;
+
+ final File file = new File(mGestureFileName);
+ if (file.exists()) {
+ DataInputStream in = null;
+ try {
+ in = new DataInputStream(new BufferedInputStream(
+ new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
+
+ long start;
+ if (PROFILE_LOADING_SAVING) {
+ start = SystemClock.elapsedRealtime();
+ }
+
+ // Read file format version number
+ final short versionNumber = in.readShort();
+ switch (versionNumber) {
+ case 1:
+ readFormatV1(in);
+ break;
+ }
+
+ if (PROFILE_LOADING_SAVING) {
+ long end = SystemClock.elapsedRealtime();
+ Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms");
+ }
+
+ result = true;
+ } catch (IOException ex) {
+ Log.d(LOG_TAG, "Failed to load gestures:", ex);
+ } finally {
+ GestureUtilities.closeStream(in);
+ }
+ }
+
+ return result;
+ }
+
+ private void readFormatV1(DataInputStream in) throws IOException {
+ final Learner classifier = mClassifier;
+ final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures;
+ namedGestures.clear();
+
+ // Number of entries in the library
+ final int entriesCount = in.readInt();
+
+ for (int i = 0; i < entriesCount; i++) {
+ // Entry name
+ final String name = in.readUTF();
+ // Number of gestures
+ final int gestureCount = in.readInt();
+
+ final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount);
+ for (int j = 0; j < gestureCount; j++) {
+ final Gesture gesture = Gesture.deserialize(in);
+ gestures.add(gesture);
+ classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name));
+ }
+
+ namedGestures.put(name, gestures);
+ }
+ }
+}
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
new file mode 100755
index 0000000..bffd12e
--- /dev/null
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Color;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * A (transparent) overlay for gesture input that can be placed on top of other
+ * widgets. The view can also be opaque.
+ */
+
+public class GestureOverlayView extends View {
+ static final float TOUCH_TOLERANCE = 3;
+
+ // TODO: Move all these values into XML attributes
+ private static final int TRANSPARENT_BACKGROUND = 0x00000000;
+
+ // TODO: SHOULD BE A TOTAL DURATION
+ private static final float FADING_ALPHA_CHANGE = 0.15f;
+ private static final long FADING_OFFSET = 300;
+ private static final long FADING_REFRESHING_RATE = 16;
+
+ private static final int GESTURE_STROKE_WIDTH = 12;
+ private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
+
+ private static final boolean DITHER_FLAG = true;
+
+ public static final int DEFAULT_GESTURE_COLOR = 0xFFFFFF00;
+ public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
+
+ private static final int REFRESH_RANGE = 10;
+
+ private static final BlurMaskFilter BLUR_MASK_FILTER =
+ new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL);
+
+ private Paint mGesturePaint;
+
+ private final Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+ private Bitmap mBitmap; // with transparent background
+ private Canvas mBitmapCanvas;
+
+ private int mCertainGestureColor = DEFAULT_GESTURE_COLOR;
+ private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
+
+ // for rendering immediate ink feedback
+ private Rect mInvalidRect = new Rect();
+
+ private Path mPath;
+
+ private float mX;
+ private float mY;
+
+ private float mCurveEndX;
+ private float mCurveEndY;
+
+ // current gesture
+ private Gesture mCurrentGesture = null;
+
+ // TODO: Make this a list of WeakReferences
+ private final ArrayList<OnGestureListener> mOnGestureListeners = new ArrayList<OnGestureListener>();
+ private ArrayList<GesturePoint> mPointBuffer = null;
+
+ // fading out effect
+ private boolean mIsFadingOut = false;
+ private float mFadingAlpha = 1;
+
+ private Handler mHandler = new Handler();
+
+ private final Runnable mFadingOut = new Runnable() {
+ public void run() {
+ if (mIsFadingOut) {
+ mFadingAlpha -= FADING_ALPHA_CHANGE;
+ if (mFadingAlpha <= 0) {
+ mIsFadingOut = false;
+ mPath = null;
+ mCurrentGesture = null;
+ mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+ } else {
+ mHandler.postDelayed(this, FADING_REFRESHING_RATE);
+ }
+ invalidate();
+ }
+ }
+ };
+
+ public GestureOverlayView(Context context) {
+ super(context);
+ init();
+ }
+
+ public GestureOverlayView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public ArrayList<GesturePoint> getCurrentStroke() {
+ return mPointBuffer;
+ }
+
+ public Gesture getCurrentGesture() {
+ return mCurrentGesture;
+ }
+
+ /**
+ * Set Gesture color
+ *
+ * @param color
+ */
+ public void setGestureDrawingColor(int color) {
+ mGesturePaint.setColor(color);
+ if (mCurrentGesture != null) {
+ mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+ mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+ }
+ }
+
+ public void setGestureColor(int color) {
+ mCertainGestureColor = color;
+ }
+
+ public void setUncertainGestureColor(int color) {
+ mUncertainGestureColor = color;
+ }
+
+ public int getUncertainGestureColor() {
+ return mUncertainGestureColor;
+ }
+
+ public int getGestureColor() {
+ return mCertainGestureColor;
+ }
+
+ /**
+ * Set the gesture to be shown in the view
+ *
+ * @param gesture
+ */
+ public void setCurrentGesture(Gesture gesture) {
+ if (mCurrentGesture != null) {
+ clear(false);
+ }
+
+ mCurrentGesture = gesture;
+
+ if (gesture != null) {
+ if (mBitmapCanvas != null) {
+ gesture.draw(mBitmapCanvas, mGesturePaint);
+ invalidate();
+ }
+ }
+ }
+
+ private void init() {
+ mGesturePaint = new Paint();
+
+ final Paint gesturePaint = mGesturePaint;
+ gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
+ gesturePaint.setColor(DEFAULT_GESTURE_COLOR);
+ gesturePaint.setStyle(Paint.Style.STROKE);
+ gesturePaint.setStrokeJoin(Paint.Join.ROUND);
+ gesturePaint.setStrokeCap(Paint.Cap.ROUND);
+ gesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
+ gesturePaint.setDither(DITHER_FLAG);
+
+ mPath = null;
+ }
+
+ @Override
+ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
+ super.onSizeChanged(width, height, oldWidth, oldHeight);
+
+ if (width <= 0 || height <= 0) {
+ return;
+ }
+
+ int targetWidth = width > oldWidth ? width : oldWidth;
+ int targetHeight = height > oldHeight ? height : oldHeight;
+
+ if (mBitmap != null) mBitmap.recycle();
+
+ mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
+ if (mBitmapCanvas != null) {
+ mBitmapCanvas.setBitmap(mBitmap);
+ } else {
+ mBitmapCanvas = new Canvas(mBitmap);
+ }
+ mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
+
+ if (mCurrentGesture != null) {
+ mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+ }
+ }
+
+ public void addOnGestureListener(OnGestureListener listener) {
+ mOnGestureListeners.add(listener);
+ }
+
+ public void removeOnGestureListener(OnGestureListener listener) {
+ mOnGestureListeners.remove(listener);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // draw double buffer
+ if (mIsFadingOut) {
+ mBitmapPaint.setAlpha((int) (255 * mFadingAlpha));
+ canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+ } else {
+ mBitmapPaint.setAlpha(255);
+ canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+ }
+
+ // draw the current stroke
+ if (mPath != null) {
+ canvas.drawPath(mPath, mGesturePaint);
+ }
+ }
+
+ /**
+ * Clear up the overlay
+ *
+ * @param fadeOut whether the gesture on the overlay should fade out
+ * gradually or disappear immediately
+ */
+ public void clear(boolean fadeOut) {
+ if (fadeOut) {
+ mFadingAlpha = 1;
+ mIsFadingOut = true;
+ mHandler.removeCallbacks(mFadingOut);
+ mHandler.postDelayed(mFadingOut, FADING_OFFSET);
+ } else {
+ mPath = null;
+ mCurrentGesture = null;
+ if (mBitmap != null) {
+ mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+ invalidate();
+ }
+ }
+ }
+
+ public void cancelFadingOut() {
+ mIsFadingOut = false;
+ mHandler.removeCallbacks(mFadingOut);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!isEnabled()) {
+ return true;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ Rect rect = touchStart(event);
+ invalidate(rect);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ rect = touchMove(event);
+ if (rect != null) {
+ invalidate(rect);
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ touchUp(event);
+ invalidate();
+ break;
+ }
+
+ return true;
+ }
+
+ private Rect touchStart(MotionEvent event) {
+ // pass the event to handlers
+ final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+ final int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ OnGestureListener listener = listeners.get(i);
+ listener.onGestureStarted(this, event);
+ }
+
+ // if there is fading out going on, stop it.
+ if (mIsFadingOut) {
+ mIsFadingOut = false;
+ mHandler.removeCallbacks(mFadingOut);
+ mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+ mCurrentGesture = null;
+ }
+
+ float x = event.getX();
+ float y = event.getY();
+
+ mX = x;
+ mY = y;
+
+ if (mCurrentGesture == null) {
+ mCurrentGesture = new Gesture();
+ }
+
+ mPointBuffer = new ArrayList<GesturePoint>();
+ mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+
+ mPath = new Path();
+ mPath.moveTo(x, y);
+
+ mInvalidRect.set((int) x - REFRESH_RANGE, (int) y - REFRESH_RANGE,
+ (int) x + REFRESH_RANGE, (int) y + REFRESH_RANGE);
+
+ mCurveEndX = x;
+ mCurveEndY = y;
+
+ return mInvalidRect;
+ }
+
+ private Rect touchMove(MotionEvent event) {
+ Rect areaToRefresh = null;
+
+ float x = event.getX();
+ float y = event.getY();
+
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+
+ if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+
+ // start with the curve end
+ mInvalidRect.set((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
+ (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
+
+ mCurveEndX = (x + mX) / 2;
+ mCurveEndY = (y + mY) / 2;
+ mPath.quadTo(mX, mY, mCurveEndX, mCurveEndY);
+
+ // union with the control point of the new curve
+ mInvalidRect.union((int) mX - REFRESH_RANGE, (int) mY - REFRESH_RANGE,
+ (int) mX + REFRESH_RANGE, (int) mY + REFRESH_RANGE);
+
+ // union with the end point of the new curve
+ mInvalidRect.union((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
+ (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
+
+ areaToRefresh = mInvalidRect;
+
+ mX = x;
+ mY = y;
+ }
+
+
+ mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+
+ // pass the event to handlers
+ final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+ final int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ listeners.get(i).onGesture(this, event);
+ }
+
+ return areaToRefresh;
+ }
+
+ private void touchUp(MotionEvent event) {
+ // add the stroke to the current gesture
+ mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
+
+ // add the stroke to the double buffer
+ mGesturePaint.setMaskFilter(BLUR_MASK_FILTER);
+ mBitmapCanvas.drawPath(mPath, mGesturePaint);
+ mGesturePaint.setMaskFilter(null);
+
+ // pass the event to handlers
+ final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+ final int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ listeners.get(i).onGestureEnded(this, event);
+ }
+
+ mPath = null;
+ mPointBuffer = null;
+ }
+
+ /**
+ * An interface for processing gesture events
+ */
+ public static interface OnGestureListener {
+ public void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
+
+ public void onGesture(GestureOverlayView overlay, MotionEvent event);
+
+ public void onGestureEnded(GestureOverlayView overlay, MotionEvent event);
+ }
+}
diff --git a/core/java/android/gesture/GesturePoint.java b/core/java/android/gesture/GesturePoint.java
new file mode 100644
index 0000000..3698011
--- /dev/null
+++ b/core/java/android/gesture/GesturePoint.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * A timed point of a gesture stroke
+ */
+
+public class GesturePoint {
+ public final float x;
+ public final float y;
+
+ public final long timestamp;
+
+ public GesturePoint(float x, float y, long t) {
+ this.x = x;
+ this.y = y;
+ timestamp = t;
+ }
+
+ static GesturePoint deserialize(DataInputStream in) throws IOException {
+ // Read X and Y
+ final float x = in.readFloat();
+ final float y = in.readFloat();
+ // Read timestamp
+ final long timeStamp = in.readLong();
+ return new GesturePoint(x, y, timeStamp);
+ }
+}
diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java
new file mode 100644
index 0000000..5160a76
--- /dev/null
+++ b/core/java/android/gesture/GestureStroke.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.util.ArrayList;
+
+/**
+ * A gesture stroke started on a touch down and ended on a touch up.
+ */
+public class GestureStroke {
+ public final RectF boundingBox;
+
+ public final float length;
+ public final float[] points;
+
+ private final long[] timestamps;
+ private Path mCachedPath;
+
+ /**
+ * Construct a gesture stroke from a list of gesture points
+ *
+ * @param points
+ */
+ public GestureStroke(ArrayList<GesturePoint> points) {
+ final int count = points.size();
+ final float[] tmpPoints = new float[count * 2];
+ final long[] times = new long[count];
+
+ RectF bx = null;
+ float len = 0;
+ int index = 0;
+
+ for (int i = 0; i < count; i++) {
+ final GesturePoint p = points.get(i);
+ tmpPoints[i * 2] = p.x;
+ tmpPoints[i * 2 + 1] = p.y;
+ times[index] = p.timestamp;
+
+ if (bx == null) {
+ bx = new RectF();
+ bx.top = p.y;
+ bx.left = p.x;
+ bx.right = p.x;
+ bx.bottom = p.y;
+ len = 0;
+ } else {
+ len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
+ + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
+ bx.union(p.x, p.y);
+ }
+ index++;
+ }
+
+ timestamps = times;
+ this.points = tmpPoints;
+ boundingBox = bx;
+ length = len;
+ }
+
+ /**
+ * Draw the gesture with a given canvas and paint
+ *
+ * @param canvas
+ */
+ void draw(Canvas canvas, Paint paint) {
+ if (mCachedPath == null) {
+ final float[] localPoints = points;
+ final int count = localPoints.length;
+
+ Path path = null;
+
+ float mX = 0;
+ float mY = 0;
+
+ for (int i = 0; i < count; i += 2) {
+ float x = localPoints[i];
+ float y = localPoints[i + 1];
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= 3 || dy >= 3) {
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+
+ mCachedPath = path;
+ }
+
+ canvas.drawPath(mCachedPath, paint);
+ }
+
+ /**
+ * Convert the stroke to a Path based on the number of points
+ *
+ * @param width the width of the bounding box of the target path
+ * @param height the height of the bounding box of the target path
+ * @param numSample the number of points needed
+ *
+ * @return the path
+ */
+ public Path toPath(float width, float height, int numSample) {
+ final float[] pts = GestureUtilities.temporalSampling(this, numSample);
+ final RectF rect = boundingBox;
+
+ final Matrix matrix = new Matrix();
+ matrix.setTranslate(-rect.left, -rect.top);
+ matrix.postScale(width / rect.width(), height / rect.height());
+ matrix.mapPoints(pts);
+
+ float mX = 0;
+ float mY = 0;
+
+ Path path = null;
+
+ final int count = pts.length;
+
+ for (int i = 0; i < count; i += 2) {
+ float x = pts[i];
+ float y = pts[i + 1];
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= GestureOverlayView.TOUCH_TOLERANCE ||
+ dy >= GestureOverlayView.TOUCH_TOLERANCE) {
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+
+ return path;
+ }
+
+ void serialize(DataOutputStream out) throws IOException {
+ final float[] pts = points;
+ final long[] times = timestamps;
+ final int count = points.length;
+
+ // Write number of points
+ out.writeInt(count / 2);
+
+ for (int i = 0; i < count; i += 2) {
+ // Write X
+ out.writeFloat(pts[i]);
+ // Write Y
+ out.writeFloat(pts[i + 1]);
+ // Write timestamp
+ out.writeLong(times[i / 2]);
+ }
+ }
+
+ static GestureStroke deserialize(DataInputStream in) throws IOException {
+ // Number of points
+ final int count = in.readInt();
+
+ final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(count);
+ for (int i = 0; i < count; i++) {
+ points.add(GesturePoint.deserialize(in));
+ }
+
+ return new GestureStroke(points);
+ }
+
+ /**
+ * Invalidate the cached path that is used to render the stroke
+ */
+ public void clearPath() {
+ if (mCachedPath != null) mCachedPath.rewind();
+ }
+
+ /**
+ * Compute an oriented bounding box of the stroke
+ * @return OrientedBoundingBox
+ */
+ public OrientedBoundingBox computeOrientedBoundingBox() {
+ return GestureUtilities.computeOrientedBoundingBox(points);
+ }
+}
diff --git a/core/java/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java
new file mode 100755
index 0000000..e47856c
--- /dev/null
+++ b/core/java/android/gesture/GestureUtilities.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.graphics.RectF;
+import android.graphics.Matrix;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.io.Closeable;
+import java.io.IOException;
+
+import static android.gesture.GestureConstants.*;
+
+final class GestureUtilities {
+ private static final int TEMPORAL_SAMPLING_RATE = 16;
+
+ private GestureUtilities() {
+ }
+
+ /**
+ * Closes the specified stream.
+ *
+ * @param stream The stream to close.
+ */
+ static void closeStream(Closeable stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Could not close stream", e);
+ }
+ }
+ }
+
+ static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension) {
+ final float targetPatchSize = sampleMatrixDimension - 1; // edge inclusive
+ float[] sample = new float[sampleMatrixDimension * sampleMatrixDimension];
+ Arrays.fill(sample, 0);
+
+ RectF rect = gesture.getBoundingBox();
+ float sx = targetPatchSize / rect.width();
+ float sy = targetPatchSize / rect.height();
+ float scale = sx < sy ? sx : sy;
+
+ Matrix trans = new Matrix();
+ trans.setScale(scale, scale);
+ trans.preTranslate(-rect.centerX(), -rect.centerY());
+ trans.postTranslate(targetPatchSize / 2, targetPatchSize / 2);
+
+ final ArrayList<GestureStroke> strokes = gesture.getStrokes();
+ final int count = strokes.size();
+
+ int size;
+ float xpos;
+ float ypos;
+
+ for (int index = 0; index < count; index++) {
+ final GestureStroke stroke = strokes.get(index);
+ size = stroke.points.length;
+
+ final float[] pts = new float[size];
+
+ trans.mapPoints(pts, 0, stroke.points, 0, size / 2);
+ float segmentEndX = -1;
+ float segmentEndY = -1;
+
+ for (int i = 0; i < size; i += 2) {
+
+ float segmentStartX = pts[i] < 0 ? 0 : pts[i];
+ float segmentStartY = pts[i + 1] < 0 ? 0 : pts[i + 1];
+
+ if (segmentStartX > targetPatchSize) {
+ segmentStartX = targetPatchSize;
+ }
+
+ if (segmentStartY > targetPatchSize) {
+ segmentStartY = targetPatchSize;
+ }
+
+ plot(segmentStartX, segmentStartY, sample, sampleMatrixDimension);
+
+ if (segmentEndX != -1) {
+ // evaluate horizontally
+ if (segmentEndX > segmentStartX) {
+ xpos = (float) Math.ceil(segmentStartX);
+ float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX);
+ while (xpos < segmentEndX) {
+ ypos = slope * (xpos - segmentStartX) + segmentStartY;
+ plot(xpos, ypos, sample, sampleMatrixDimension);
+ xpos++;
+ }
+ } else if (segmentEndX < segmentStartX){
+ xpos = (float) Math.ceil(segmentEndX);
+ float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX);
+ while (xpos < segmentStartX) {
+ ypos = slope * (xpos - segmentStartX) + segmentStartY;
+ plot(xpos, ypos, sample, sampleMatrixDimension);
+ xpos++;
+ }
+ }
+
+ // evaluating vertically
+ if (segmentEndY > segmentStartY) {
+ ypos = (float) Math.ceil(segmentStartY);
+ float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY);
+ while (ypos < segmentEndY) {
+ xpos = invertSlope * (ypos - segmentStartY) + segmentStartX;
+ plot(xpos, ypos, sample, sampleMatrixDimension);
+ ypos++;
+ }
+ } else if (segmentEndY < segmentStartY) {
+ ypos = (float) Math.ceil(segmentEndY);
+ float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY);
+ while (ypos < segmentStartY) {
+ xpos = invertSlope * (ypos - segmentStartY) + segmentStartX;
+ plot(xpos, ypos, sample, sampleMatrixDimension);
+ ypos++;
+ }
+ }
+ }
+
+ segmentEndX = segmentStartX;
+ segmentEndY = segmentStartY;
+ }
+ }
+
+
+ return sample;
+ }
+
+ private static void plot(float x, float y, float[] sample, int sampleSize) {
+ x = x < 0 ? 0 : x;
+ y = y < 0 ? 0 : y;
+ int xFloor = (int) Math.floor(x);
+ int xCeiling = (int) Math.ceil(x);
+ int yFloor = (int) Math.floor(y);
+ int yCeiling = (int) Math.ceil(y);
+
+ // if it's an integer
+ if (x == xFloor && y == yFloor) {
+ int index = yCeiling * sampleSize + xCeiling;
+ if (sample[index] < 1){
+ sample[index] = 1;
+ }
+ } else {
+ double topLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yFloor - y, 2));
+ double topRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yFloor - y, 2));
+ double btmLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yCeiling - y, 2));
+ double btmRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yCeiling - y, 2));
+ double sum = topLeft + topRight + btmLeft + btmRight;
+
+ double value = topLeft / sum;
+ int index = yFloor * sampleSize + xFloor;
+ if (value > sample[index]){
+ sample[index] = (float) value;
+ }
+
+ value = topRight / sum;
+ index = yFloor * sampleSize + xCeiling;
+ if (value > sample[index]){
+ sample[index] = (float) value;
+ }
+
+ value = btmLeft / sum;
+ index = yCeiling * sampleSize + xFloor;
+ if (value > sample[index]){
+ sample[index] = (float) value;
+ }
+
+ value = btmRight / sum;
+ index = yCeiling * sampleSize + xCeiling;
+ if (value > sample[index]){
+ sample[index] = (float) value;
+ }
+ }
+ }
+
+ /**
+ * Featurize a stroke into a vector of a given number of elements
+ *
+ * @param stroke
+ * @param sampleSize
+ * @return a float array
+ */
+ static float[] temporalSampling(GestureStroke stroke, int sampleSize) {
+ final float increment = stroke.length / (sampleSize - 1);
+ int vectorLength = sampleSize * 2;
+ float[] vector = new float[vectorLength];
+ float distanceSoFar = 0;
+ float[] pts = stroke.points;
+ float lstPointX = pts[0];
+ float lstPointY = pts[1];
+ int index = 0;
+ float currentPointX = Float.MIN_VALUE;
+ float currentPointY = Float.MIN_VALUE;
+ vector[index] = lstPointX;
+ index++;
+ vector[index] = lstPointY;
+ index++;
+ int i = 0;
+ int count = pts.length / 2;
+ while (i < count) {
+ if (currentPointX == Float.MIN_VALUE) {
+ i++;
+ if (i >= count) {
+ break;
+ }
+ currentPointX = pts[i * 2];
+ currentPointY = pts[i * 2 + 1];
+ }
+ float deltaX = currentPointX - lstPointX;
+ float deltaY = currentPointY - lstPointY;
+ float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ if (distanceSoFar + distance >= increment) {
+ float ratio = (increment - distanceSoFar) / distance;
+ float nx = lstPointX + ratio * deltaX;
+ float ny = lstPointY + ratio * deltaY;
+ vector[index] = nx;
+ index++;
+ vector[index] = ny;
+ index++;
+ lstPointX = nx;
+ lstPointY = ny;
+ distanceSoFar = 0;
+ } else {
+ lstPointX = currentPointX;
+ lstPointY = currentPointY;
+ currentPointX = Float.MIN_VALUE;
+ currentPointY = Float.MIN_VALUE;
+ distanceSoFar += distance;
+ }
+ }
+
+ for (i = index; i < vectorLength; i += 2) {
+ vector[i] = lstPointX;
+ vector[i + 1] = lstPointY;
+ }
+ return vector;
+ }
+
+ /**
+ * Calculate the centroid
+ *
+ * @param points
+ * @return the centroid
+ */
+ static float[] computeCentroid(float[] points) {
+ float centerX = 0;
+ float centerY = 0;
+ int count = points.length;
+ for (int i = 0; i < count; i++) {
+ centerX += points[i];
+ i++;
+ centerY += points[i];
+ }
+ float[] center = new float[2];
+ center[0] = 2 * centerX / count;
+ center[1] = 2 * centerY / count;
+
+ return center;
+ }
+
+ /**
+ * calculate the variance-covariance matrix, treat each point as a sample
+ *
+ * @param points
+ * @return the covariance matrix
+ */
+ private static double[][] computeCoVariance(float[] points) {
+ double[][] array = new double[2][2];
+ array[0][0] = 0;
+ array[0][1] = 0;
+ array[1][0] = 0;
+ array[1][1] = 0;
+ int count = points.length;
+ for (int i = 0; i < count; i++) {
+ float x = points[i];
+ i++;
+ float y = points[i];
+ array[0][0] += x * x;
+ array[0][1] += x * y;
+ array[1][0] = array[0][1];
+ array[1][1] += y * y;
+ }
+ array[0][0] /= (count / 2);
+ array[0][1] /= (count / 2);
+ array[1][0] /= (count / 2);
+ array[1][1] /= (count / 2);
+
+ return array;
+ }
+
+ static float computeTotalLength(float[] points) {
+ float sum = 0;
+ int count = points.length - 4;
+ for (int i = 0; i < count; i += 2) {
+ float dx = points[i + 2] - points[i];
+ float dy = points[i + 3] - points[i + 1];
+ sum += Math.sqrt(dx * dx + dy * dy);
+ }
+ return sum;
+ }
+
+ static double computeStraightness(float[] points) {
+ float totalLen = computeTotalLength(points);
+ float dx = points[2] - points[0];
+ float dy = points[3] - points[1];
+ return Math.sqrt(dx * dx + dy * dy) / totalLen;
+ }
+
+ static double computeStraightness(float[] points, float totalLen) {
+ float dx = points[2] - points[0];
+ float dy = points[3] - points[1];
+ return Math.sqrt(dx * dx + dy * dy) / totalLen;
+ }
+
+ /**
+ * Calculate the squared Euclidean distance between two vectors
+ *
+ * @param vector1
+ * @param vector2
+ * @return the distance
+ */
+ static double squaredEuclideanDistance(float[] vector1, float[] vector2) {
+ double squaredDistance = 0;
+ int size = vector1.length;
+ for (int i = 0; i < size; i++) {
+ float difference = vector1[i] - vector2[i];
+ squaredDistance += difference * difference;
+ }
+ return squaredDistance / size;
+ }
+
+ /**
+ * Calculate the cosine distance between two instances
+ *
+ * @param vector1
+ * @param vector2
+ * @return the distance between 0 and Math.PI
+ */
+ static double cosineDistance(float[] vector1, float[] vector2) {
+ float sum = 0;
+ int len = vector1.length;
+ for (int i = 0; i < len; i++) {
+ sum += vector1[i] * vector2[i];
+ }
+ return Math.acos(sum);
+ }
+
+ static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) {
+ GestureStroke stroke = new GestureStroke(pts);
+ float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE);
+ return computeOrientedBoundingBox(points);
+ }
+
+ static OrientedBoundingBox computeOrientedBoundingBox(float[] points) {
+ float[] meanVector = computeCentroid(points);
+ return computeOrientedBoundingBox(points, meanVector);
+ }
+
+ static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) {
+ Matrix tr = new Matrix();
+ tr.setTranslate(-centroid[0], -centroid[1]);
+ tr.mapPoints(points);
+
+ double[][] array = computeCoVariance(points);
+ double[] targetVector = computeOrientation(array);
+
+ float angle;
+ if (targetVector[0] == 0 && targetVector[1] == 0) {
+ angle = -90;
+ } else { // -PI<alpha<PI
+ angle = (float) Math.atan2(targetVector[1], targetVector[0]);
+ angle = (float) (180 * angle / Math.PI);
+ android.graphics.Matrix trans = new android.graphics.Matrix();
+ trans.setRotate(-angle);
+ trans.mapPoints(points);
+ }
+
+ float minx = Float.MAX_VALUE;
+ float miny = Float.MAX_VALUE;
+ float maxx = Float.MIN_VALUE;
+ float maxy = Float.MIN_VALUE;
+ int count = points.length;
+ for (int i = 0; i < count; i++) {
+ if (points[i] < minx) {
+ minx = points[i];
+ }
+ if (points[i] > maxx) {
+ maxx = points[i];
+ }
+ i++;
+ if (points[i] < miny) {
+ miny = points[i];
+ }
+ if (points[i] > maxy) {
+ maxy = points[i];
+ }
+ }
+
+ return new OrientedBoundingBox(angle, centroid[0], centroid[1], maxx - minx, maxy - miny);
+ }
+
+ private static double[] computeOrientation(double[][] covarianceMatrix) {
+ double[] targetVector = new double[2];
+ if (covarianceMatrix[0][1] == 0 || covarianceMatrix[1][0] == 0) {
+ targetVector[0] = 1;
+ targetVector[1] = 0;
+ }
+
+ double a = -covarianceMatrix[0][0] - covarianceMatrix[1][1];
+ double b = covarianceMatrix[0][0] * covarianceMatrix[1][1] - covarianceMatrix[0][1]
+ * covarianceMatrix[1][0];
+ double value = a / 2;
+ double rightside = Math.sqrt(Math.pow(value, 2) - b);
+ double lambda1 = -value + rightside;
+ double lambda2 = -value - rightside;
+ if (lambda1 == lambda2) {
+ targetVector[0] = 0;
+ targetVector[1] = 0;
+ } else {
+ double lambda = lambda1 > lambda2 ? lambda1 : lambda2;
+ targetVector[0] = 1;
+ targetVector[1] = (lambda - covarianceMatrix[0][0]) / covarianceMatrix[0][1];
+ }
+ return targetVector;
+ }
+}
diff --git a/core/java/android/gesture/Instance.java b/core/java/android/gesture/Instance.java
new file mode 100755
index 0000000..7922fab
--- /dev/null
+++ b/core/java/android/gesture/Instance.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.graphics.Matrix;
+
+/**
+ * An instance represents a sample if the label is available or a query if the
+ * label is null.
+ */
+class Instance {
+ private static final int SEQUENCE_SAMPLE_SIZE = 16;
+
+ private static final int PATCH_SAMPLE_SIZE = 16;
+
+ private final static float[] ORIENTATIONS = {
+ 0, 45, 90, 135, 180, -0, -45, -90, -135, -180
+ };
+
+ // the feature vector
+ final float[] vector;
+
+ // the label can be null
+ final String label;
+
+ // the id of the instance
+ final long id;
+
+ private Instance(long id, float[] sample, String sampleName) {
+ this.id = id;
+ vector = sample;
+ label = sampleName;
+ }
+
+ private void normalize() {
+ float[] sample = vector;
+ float sum = 0;
+
+ int size = sample.length;
+ for (int i = 0; i < size; i++) {
+ sum += sample[i] * sample[i];
+ }
+
+ float magnitude = (float) Math.sqrt(sum);
+ for (int i = 0; i < size; i++) {
+ sample[i] /= magnitude;
+ }
+ }
+
+ /**
+ * create a learning instance for a single stroke gesture
+ *
+ * @param gesture
+ * @param label
+ * @return the instance
+ */
+ static Instance createInstance(int samplingType, Gesture gesture, String label) {
+ float[] pts;
+ Instance instance;
+ if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) {
+ pts = temporalSampler(samplingType, gesture);
+ instance = new Instance(gesture.getID(), pts, label);
+ instance.normalize();
+ } else {
+ pts = spatialSampler(gesture);
+ instance = new Instance(gesture.getID(), pts, label);
+ }
+ return instance;
+ }
+
+ private static float[] spatialSampler(Gesture gesture) {
+ return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
+ }
+
+ private static float[] temporalSampler(int samplingType, Gesture gesture) {
+ float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0),
+ SEQUENCE_SAMPLE_SIZE);
+ float[] center = GestureUtilities.computeCentroid(pts);
+ float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
+ orientation *= 180 / Math.PI;
+
+ float adjustment = -orientation;
+ if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) {
+ int count = ORIENTATIONS.length;
+ for (int i = 0; i < count; i++) {
+ float delta = ORIENTATIONS[i] - orientation;
+ if (Math.abs(delta) < Math.abs(adjustment)) {
+ adjustment = delta;
+ }
+ }
+ }
+
+ Matrix m = new Matrix();
+ m.setTranslate(-center[0], -center[1]);
+ m.postRotate(adjustment);
+ m.mapPoints(pts);
+
+ return pts;
+ }
+
+}
diff --git a/core/java/android/gesture/InstanceLearner.java b/core/java/android/gesture/InstanceLearner.java
new file mode 100644
index 0000000..1739cdc
--- /dev/null
+++ b/core/java/android/gesture/InstanceLearner.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.util.Config;
+import android.util.Log;
+import static android.gesture.GestureConstants.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+/**
+ * An implementation of an instance-based learner
+ */
+
+class InstanceLearner extends Learner {
+ @Override
+ ArrayList<Prediction> classify(int gestureType, float[] vector) {
+ ArrayList<Prediction> predictions = new ArrayList<Prediction>();
+ ArrayList<Instance> instances = getInstances();
+ int count = instances.size();
+ TreeMap<String, Double> label2score = new TreeMap<String, Double>();
+ for (int i = 0; i < count; i++) {
+ Instance sample = instances.get(i);
+ if (sample.vector.length != vector.length) {
+ continue;
+ }
+ double distance;
+ if (gestureType == GestureLibrary.SEQUENCE_SENSITIVE) {
+ distance = GestureUtilities.cosineDistance(sample.vector, vector);
+ } else {
+ distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);
+ }
+ double weight;
+ if (distance == 0) {
+ weight = Double.MAX_VALUE;
+ } else {
+ weight = 1 / distance;
+ }
+ Double score = label2score.get(sample.label);
+ if (score == null || weight > score) {
+ label2score.put(sample.label, weight);
+ }
+ }
+
+ double sum = 0;
+ for (String name : label2score.keySet()) {
+ double score = label2score.get(name);
+ sum += score;
+ predictions.add(new Prediction(name, score));
+ }
+
+ // normalize
+ for (Prediction prediction : predictions) {
+ prediction.score /= sum;
+ }
+
+ Collections.sort(predictions, new Comparator<Prediction>() {
+ public int compare(Prediction object1, Prediction object2) {
+ double score1 = object1.score;
+ double score2 = object2.score;
+ if (score1 > score2) {
+ return -1;
+ } else if (score1 < score2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ });
+
+ return predictions;
+ }
+}
diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
new file mode 100755
index 0000000..feacde5
--- /dev/null
+++ b/core/java/android/gesture/Learner.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import java.util.ArrayList;
+
+/**
+ * The abstract class of a gesture learner
+ */
+abstract class Learner {
+ private final ArrayList<Instance> mInstances = new ArrayList<Instance>();
+
+ /**
+ * Add an instance to the learner
+ *
+ * @param instance
+ */
+ void addInstance(Instance instance) {
+ mInstances.add(instance);
+ }
+
+ /**
+ * Retrieve all the instances
+ *
+ * @return instances
+ */
+ ArrayList<Instance> getInstances() {
+ return mInstances;
+ }
+
+ /**
+ * Remove an instance based on its id
+ *
+ * @param id
+ */
+ void removeInstance(long id) {
+ ArrayList<Instance> instances = mInstances;
+ int count = instances.size();
+ for (int i = 0; i < count; i++) {
+ Instance instance = instances.get(i);
+ if (id == instance.id) {
+ instances.remove(instance);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Remove all the instances of a category
+ *
+ * @param name the category name
+ */
+ void removeInstances(String name) {
+ final ArrayList<Instance> toDelete = new ArrayList<Instance>();
+ final ArrayList<Instance> instances = mInstances;
+ final int count = instances.size();
+
+ for (int i = 0; i < count; i++) {
+ final Instance instance = instances.get(i);
+ // the label can be null, as specified in Instance
+ if ((instance.label == null && name == null) || instance.label.equals(name)) {
+ toDelete.add(instance);
+ }
+ }
+ instances.removeAll(toDelete);
+ }
+
+ abstract ArrayList<Prediction> classify(int gestureType, float[] vector);
+}
diff --git a/core/java/android/gesture/LetterRecognizer.java b/core/java/android/gesture/LetterRecognizer.java
new file mode 100644
index 0000000..4476746
--- /dev/null
+++ b/core/java/android/gesture/LetterRecognizer.java
@@ -0,0 +1,273 @@
+/*
+ * 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 android.gesture;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+
+import static android.gesture.GestureConstants.LOG_TAG;
+
+public class LetterRecognizer {
+ public final static int RECOGNIZER_LATIN_LOWERCASE = 0;
+ static final String GESTURE_FILE_NAME = "letters.gestures";
+
+ private final static int ADJUST_RANGE = 3;
+
+ private SigmoidUnit[] mHiddenLayer;
+ private SigmoidUnit[] mOutputLayer;
+
+ private final String[] mClasses;
+
+ private final int mPatchSize;
+
+ private GestureLibrary mGestureLibrary;
+
+ private static class SigmoidUnit {
+ final float[] mWeights;
+
+ private boolean mComputed;
+ private float mResult;
+
+ SigmoidUnit(float[] weights) {
+ mWeights = weights;
+ }
+
+ private float compute(float[] inputs) {
+ if (!mComputed) {
+ float sum = 0;
+
+ final int count = inputs.length;
+ final float[] weights = mWeights;
+
+ for (int i = 0; i < count; i++) {
+ sum += inputs[i] * weights[i];
+ }
+ sum += weights[weights.length - 1];
+
+ mResult = 1.0f / (float) (1 + Math.exp(-sum));
+ mComputed = true;
+ }
+ return mResult;
+ }
+ }
+
+ public static LetterRecognizer getLetterRecognizer(Context context, int type) {
+ switch (type) {
+ case RECOGNIZER_LATIN_LOWERCASE: {
+ return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
+ }
+ }
+ return null;
+ }
+
+ private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
+ mPatchSize = (int) Math.sqrt(numOfInput);
+ mHiddenLayer = new SigmoidUnit[numOfHidden];
+ mClasses = classes;
+ mOutputLayer = new SigmoidUnit[classes.length];
+ }
+
+ public ArrayList<Prediction> recognize(Gesture gesture) {
+ float[] query = GestureUtilities.spatialSampling(gesture, mPatchSize);
+ ArrayList<Prediction> predictions = classify(query);
+ adjustPrediction(gesture, predictions);
+ return predictions;
+ }
+
+ private ArrayList<Prediction> classify(float[] vector) {
+ final float[] intermediateOutput = compute(mHiddenLayer, vector);
+ final float[] output = compute(mOutputLayer, intermediateOutput);
+ final ArrayList<Prediction> predictions = new ArrayList<Prediction>();
+
+ double sum = 0;
+
+ final String[] classes = mClasses;
+ final int count = classes.length;
+
+ for (int i = 0; i < count; i++) {
+ double score = output[i];
+ sum += score;
+ predictions.add(new Prediction(classes[i], score));
+ }
+
+ for (int i = 0; i < count; i++) {
+ predictions.get(i).score /= sum;
+ }
+
+ Collections.sort(predictions, new Comparator<Prediction>() {
+ public int compare(Prediction object1, Prediction object2) {
+ double score1 = object1.score;
+ double score2 = object2.score;
+ if (score1 > score2) {
+ return -1;
+ } else if (score1 < score2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ });
+ return predictions;
+ }
+
+ private float[] compute(SigmoidUnit[] layer, float[] input) {
+ final float[] output = new float[layer.length];
+ final int count = layer.length;
+
+ for (int i = 0; i < count; i++) {
+ output[i] = layer[i].compute(input);
+ }
+
+ return output;
+ }
+
+ private static LetterRecognizer createFromResource(Context context, int resourceID) {
+ final Resources resources = context.getResources();
+
+ DataInputStream in = null;
+ LetterRecognizer classifier = null;
+
+ try {
+ in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID),
+ GestureConstants.IO_BUFFER_SIZE));
+
+ final int version = in.readShort();
+
+ switch (version) {
+ case 1:
+ classifier = readV1(in);
+ break;
+ }
+
+ } catch (IOException e) {
+ Log.d(LOG_TAG, "Failed to load handwriting data:", e);
+ } finally {
+ GestureUtilities.closeStream(in);
+ }
+
+ return classifier;
+ }
+
+ private static LetterRecognizer readV1(DataInputStream in) throws IOException {
+
+ final int iCount = in.readInt();
+ final int hCount = in.readInt();
+ final int oCount = in.readInt();
+
+ final String[] classes = new String[oCount];
+ for (int i = 0; i < classes.length; i++) {
+ classes[i] = in.readUTF();
+ }
+
+ final LetterRecognizer classifier = new LetterRecognizer(iCount, hCount, classes);
+ final SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
+ final SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
+
+ for (int i = 0; i < hCount; i++) {
+ final float[] weights = new float[iCount + 1];
+ for (int j = 0; j <= iCount; j++) {
+ weights[j] = in.readFloat();
+ }
+ hiddenLayer[i] = new SigmoidUnit(weights);
+ }
+
+ for (int i = 0; i < oCount; i++) {
+ final float[] weights = new float[hCount + 1];
+ for (int j = 0; j <= hCount; j++) {
+ weights[j] = in.readFloat();
+ }
+ outputLayer[i] = new SigmoidUnit(weights);
+ }
+
+ classifier.mHiddenLayer = hiddenLayer;
+ classifier.mOutputLayer = outputLayer;
+
+ return classifier;
+ }
+
+ /**
+ * TODO: Publish this API once we figure out where we should save the personzlied
+ * gestures, and how to do so across all apps
+ *
+ * @hide
+ */
+ public boolean save() {
+ if (mGestureLibrary != null) {
+ return mGestureLibrary.save();
+ }
+ return false;
+ }
+
+ /**
+ * TODO: Publish this API once we figure out where we should save the personzlied
+ * gestures, and how to do so across all apps
+ *
+ * @hide
+ */
+ public void setPersonalizationEnabled(boolean enabled) {
+ if (enabled) {
+ mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
+ mGestureLibrary.setSequenceType(GestureLibrary.SEQUENCE_INVARIANT);
+ mGestureLibrary.load();
+ } else {
+ mGestureLibrary = null;
+ }
+ }
+
+ /**
+ * TODO: Publish this API once we figure out where we should save the personzlied
+ * gestures, and how to do so across all apps
+ *
+ * @hide
+ */
+ public void addExample(String letter, Gesture example) {
+ if (mGestureLibrary != null) {
+ mGestureLibrary.addGesture(letter, example);
+ }
+ }
+
+ private void adjustPrediction(Gesture query, ArrayList<Prediction> predictions) {
+ if (mGestureLibrary != null) {
+ final ArrayList<Prediction> results = mGestureLibrary.recognize(query);
+ final HashMap<String, Prediction> topNList = new HashMap<String, Prediction>();
+
+ for (int j = 0; j < ADJUST_RANGE; j++) {
+ Prediction prediction = predictions.remove(0);
+ topNList.put(prediction.name, prediction);
+ }
+
+ final int count = results.size();
+ for (int j = count - 1; j >= 0 && !topNList.isEmpty(); j--) {
+ final Prediction item = results.get(j);
+ final Prediction original = topNList.get(item.name);
+ if (original != null) {
+ predictions.add(0, original);
+ topNList.remove(item.name);
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/gesture/OrientedBoundingBox.java b/core/java/android/gesture/OrientedBoundingBox.java
new file mode 100644
index 0000000..f1335ee
--- /dev/null
+++ b/core/java/android/gesture/OrientedBoundingBox.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.graphics.Matrix;
+import android.graphics.Path;
+
+/**
+ * An oriented bounding box
+ */
+public class OrientedBoundingBox {
+ public final float squareness;
+
+ public final float width;
+ public final float height;
+
+ public final float orientation;
+
+ public final float centerX;
+ public final float centerY;
+
+ OrientedBoundingBox(float angle, float cx, float cy, float w, float h) {
+ orientation = angle;
+ width = w;
+ height = h;
+ centerX = cx;
+ centerY = cy;
+ float ratio = w / h;
+ if (ratio > 1) {
+ squareness = 1 / ratio;
+ } else {
+ squareness = ratio;
+ }
+ }
+
+ /**
+ * Currently used for debugging purpose only.
+ *
+ * @hide
+ */
+ public Path toPath() {
+ Path path = new Path();
+ float[] point = new float[2];
+ point[0] = -width / 2;
+ point[1] = height / 2;
+ Matrix matrix = new Matrix();
+ matrix.setRotate(orientation);
+ matrix.postTranslate(centerX, centerY);
+ matrix.mapPoints(point);
+ path.moveTo(point[0], point[1]);
+
+ point[0] = -width / 2;
+ point[1] = -height / 2;
+ matrix.mapPoints(point);
+ path.lineTo(point[0], point[1]);
+
+ point[0] = width / 2;
+ point[1] = -height / 2;
+ matrix.mapPoints(point);
+ path.lineTo(point[0], point[1]);
+
+ point[0] = width / 2;
+ point[1] = height / 2;
+ matrix.mapPoints(point);
+ path.lineTo(point[0], point[1]);
+
+ path.close();
+
+ return path;
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/core/java/android/gesture/Prediction.java
similarity index 67%
rename from tests/sketch/src/com/android/gesture/GestureListener.java
rename to core/java/android/gesture/Prediction.java
index ebb4149..ce6ad57 100755
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/core/java/android/gesture/Prediction.java
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-package com.android.gesture;
+package android.gesture;
-import android.view.MotionEvent;
+public class Prediction {
+ public final String name;
-public interface GestureListener {
- public void onStartGesture(GesturePad pad, MotionEvent event);
- public void onGesture(GesturePad pad, MotionEvent event);
- public void onFinishGesture(GesturePad pad, MotionEvent event);
+ public double score;
+
+ Prediction(String label, double predictionScore) {
+ name = label;
+ score = predictionScore;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
}
diff --git a/core/java/android/gesture/TouchThroughGestureListener.java b/core/java/android/gesture/TouchThroughGestureListener.java
new file mode 100644
index 0000000..7621ddf
--- /dev/null
+++ b/core/java/android/gesture/TouchThroughGestureListener.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008-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 android.gesture;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.lang.ref.WeakReference;
+
+/**
+ * TouchThroughGesturing implements the interaction behavior that allows a user
+ * to gesture over a regular UI widget such as ListView and at the same time,
+ * still allows a user to perform basic interactions (clicking, scrolling and panning)
+ * with the underlying widget.
+ */
+public class TouchThroughGestureListener implements GestureOverlayView.OnGestureListener {
+ public static final int SINGLE_STROKE = 0;
+ public static final int MULTIPLE_STROKE = 1;
+
+ // TODO: Add properties for all these
+ private static final float STROKE_LENGTH_THRESHOLD = 30;
+ private static final float SQUARENESS_THRESHOLD = 0.275f;
+ private static final float ANGLE_THRESHOLD = 40;
+
+ private boolean mIsGesturing = false;
+
+ private float mTotalLength;
+
+ private float mX;
+ private float mY;
+
+ private WeakReference<View> mModel;
+
+ private int mGestureType = SINGLE_STROKE;
+
+ // TODO: Use WeakReferences
+ private final ArrayList<OnGesturePerformedListener> mPerformedListeners =
+ new ArrayList<OnGesturePerformedListener>();
+
+ private boolean mStealEvents = false;
+
+ public TouchThroughGestureListener(View model) {
+ this(model, false);
+ }
+
+ public TouchThroughGestureListener(View model, boolean stealEvents) {
+ mModel = new WeakReference<View>(model);
+ mStealEvents = stealEvents;
+ }
+
+ /**
+ *
+ * @param type SINGLE_STROKE or MULTIPLE_STROKE
+ */
+ public void setGestureType(int type) {
+ mGestureType = type;
+ }
+
+ public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
+ if (mGestureType == MULTIPLE_STROKE) {
+ overlay.cancelFadingOut();
+ }
+
+ mX = event.getX();
+ mY = event.getY();
+ mTotalLength = 0;
+ mIsGesturing = false;
+
+ if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
+ || overlay.getCurrentGesture().getStrokesCount() == 0) {
+ overlay.setGestureDrawingColor(overlay.getUncertainGestureColor());
+ }
+
+ dispatchEventToModel(event);
+ }
+
+ private void dispatchEventToModel(MotionEvent event) {
+ View v = mModel.get();
+ if (v != null) v.dispatchTouchEvent(event);
+ }
+
+ public void onGesture(GestureOverlayView overlay, MotionEvent event) {
+ //noinspection PointlessBooleanExpression
+ if (!mStealEvents) {
+ dispatchEventToModel(event);
+ }
+
+ if (mIsGesturing) {
+ return;
+ }
+
+ final float x = event.getX();
+ final float y = event.getY();
+ final float dx = x - mX;
+ final float dy = y - mY;
+
+ mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
+ mX = x;
+ mY = y;
+
+ if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
+ final OrientedBoundingBox box =
+ GestureUtilities.computeOrientedBoundingBox(overlay.getCurrentStroke());
+ float angle = Math.abs(box.orientation);
+ if (angle > 90) {
+ angle = 180 - angle;
+ }
+ if (box.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
+ mIsGesturing = true;
+ overlay.setGestureDrawingColor(overlay.getGestureColor());
+ if (mStealEvents) {
+ event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
+ MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(),
+ event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
+ event.getDeviceId(), event.getEdgeFlags());
+ }
+ }
+ }
+
+ if (mStealEvents) {
+ dispatchEventToModel(event);
+ }
+ }
+
+ public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
+ if (mIsGesturing) {
+ overlay.clear(true);
+
+ final ArrayList<OnGesturePerformedListener> listeners = mPerformedListeners;
+ final int count = listeners.size();
+
+ for (int i = 0; i < count; i++) {
+ listeners.get(i).onGesturePerformed(overlay, overlay.getCurrentGesture());
+ }
+ } else {
+ dispatchEventToModel(event);
+ overlay.clear(false);
+ }
+ }
+
+ public void addOnGestureActionListener(OnGesturePerformedListener listener) {
+ mPerformedListeners.add(listener);
+ }
+
+ public void removeOnGestureActionListener(OnGesturePerformedListener listener) {
+ mPerformedListeners.remove(listener);
+ }
+
+ public boolean isGesturing() {
+ return mIsGesturing;
+ }
+
+ public static interface OnGesturePerformedListener {
+ public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture);
+ }
+}
diff --git a/core/java/android/net/http/RequestQueue.java b/core/java/android/net/http/RequestQueue.java
index 66d5722..54a1cce 100644
--- a/core/java/android/net/http/RequestQueue.java
+++ b/core/java/android/net/http/RequestQueue.java
@@ -52,10 +52,44 @@
private Context mContext;
+ private static class RequestSet {
+ private final LinkedList<Request> mHighPriority;
+ private final LinkedList<Request> mLowPriority;
+
+ RequestSet() {
+ mHighPriority = new LinkedList<Request>();
+ mLowPriority = new LinkedList<Request>();
+ }
+
+ void add(Request req, boolean head) {
+ LinkedList l = mLowPriority;
+ if (req.mHighPriority) {
+ l = mHighPriority;
+ }
+ if (head) {
+ l.addFirst(req);
+ } else {
+ l.add(req);
+ }
+ }
+
+ Request removeFirst() {
+ if (!mHighPriority.isEmpty()) {
+ return mHighPriority.removeFirst();
+ } else if (!mLowPriority.isEmpty()) {
+ return mLowPriority.removeFirst();
+ }
+ return null;
+ }
+
+ boolean isEmpty() {
+ return mHighPriority.isEmpty() && mLowPriority.isEmpty();
+ }
+ };
/**
* Requests, indexed by HttpHost (scheme, host, port)
*/
- private LinkedHashMap<HttpHost, LinkedList<Request>> mPending;
+ private LinkedHashMap<HttpHost, RequestSet> mPending;
/* Support for notifying a client when queue is empty */
private boolean mClientWaiting = false;
@@ -344,7 +378,7 @@
public RequestQueue(Context context, int connectionCount) {
mContext = context;
- mPending = new LinkedHashMap<HttpHost, LinkedList<Request>>(32);
+ mPending = new LinkedHashMap<HttpHost, RequestSet>(32);
mActivePool = new ActivePool(connectionCount);
mActivePool.startup();
@@ -480,7 +514,7 @@
req = new Request(method, httpHost, mProxyHost, uri.mPath, bodyProvider,
bodyLength, eventHandler, headers, highPriority);
- queueRequest(req, highPriority);
+ queueRequest(req, false);
mActivePool.mTotalRequest++;
@@ -520,19 +554,24 @@
HttpLog.v("dump()");
StringBuilder dump = new StringBuilder();
int count = 0;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter;
+ Iterator<Map.Entry<HttpHost, RequestSet>> iter;
// mActivePool.log(dump);
if (!mPending.isEmpty()) {
iter = mPending.entrySet().iterator();
while (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
+ Map.Entry<HttpHost, RequestSet> entry = iter.next();
String hostName = entry.getKey().getHostName();
StringBuilder line = new StringBuilder("p" + count++ + " " + hostName + " ");
- LinkedList<Request> reqList = entry.getValue();
- ListIterator reqIter = reqList.listIterator(0);
+ RequestSet reqList = entry.getValue();
+ ListIterator reqIter = reqList.mHighPriority.listIterator(0);
+ while (iter.hasNext()) {
+ Request request = (Request)iter.next();
+ line.append(request + " ");
+ }
+ reqIter = reqList.mLowPriority.listIterator(0);
while (iter.hasNext()) {
Request request = (Request)iter.next();
line.append(request + " ");
@@ -564,7 +603,7 @@
Request ret = null;
if (mNetworkConnected && mPending.containsKey(host)) {
- LinkedList<Request> reqList = mPending.get(host);
+ RequestSet reqList = mPending.get(host);
ret = reqList.removeFirst();
if (reqList.isEmpty()) {
mPending.remove(host);
@@ -597,18 +636,14 @@
protected synchronized void queueRequest(Request request, boolean head) {
HttpHost host = request.mProxyHost == null ? request.mHost : request.mProxyHost;
- LinkedList<Request> reqList;
+ RequestSet reqList;
if (mPending.containsKey(host)) {
reqList = mPending.get(host);
} else {
- reqList = new LinkedList<Request>();
+ reqList = new RequestSet();
mPending.put(host, reqList);
}
- if (head) {
- reqList.addFirst(request);
- } else {
- reqList.add(request);
- }
+ reqList.add(request, head);
}
@@ -621,12 +656,12 @@
}
/* helper */
- private Request removeFirst(LinkedHashMap<HttpHost, LinkedList<Request>> requestQueue) {
+ private Request removeFirst(LinkedHashMap<HttpHost, RequestSet> requestQueue) {
Request ret = null;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter = requestQueue.entrySet().iterator();
+ Iterator<Map.Entry<HttpHost, RequestSet>> iter = requestQueue.entrySet().iterator();
if (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
- LinkedList<Request> reqList = entry.getValue();
+ Map.Entry<HttpHost, RequestSet> entry = iter.next();
+ RequestSet reqList = entry.getValue();
ret = reqList.removeFirst();
if (reqList.isEmpty()) {
requestQueue.remove(entry.getKey());
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 5487c54..101336b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -38,6 +38,9 @@
/** The name of the underlying board, like "goldfish". */
public static final String BOARD = getString("ro.product.board");
+ /** The manufacturer of the product/hardware. */
+ public static final String MANUFACTURER = getString("ro.product.manufacturer");
+
/** The brand (e.g., carrier) the software is customized for, if any. */
public static final String BRAND = getString("ro.product.brand");
@@ -87,6 +90,12 @@
*/
public static class VERSION_CODES {
/**
+ * Magic version number for a current development build, which has
+ * not yet turned into an official release.
+ */
+ public static final int CUR_DEVELOPMENT = 10000;
+
+ /**
* October 2008: The original, first, version of Android. Yay!
*/
public static final int BASE = 1;
@@ -98,6 +107,19 @@
* May 2009: Android 1.5.
*/
public static final int CUPCAKE = 3;
+ /**
+ * Current work on "Donut" development branch.
+ *
+ * <p>Applications targeting this or a later release will get these
+ * new changes in behavior:</p>
+ * <ul>
+ * <li> They must explicitly request the
+ * {@link android.Manifest.permission#WRITE_SDCARD} permission to be
+ * able to modify the contents of the SD card. (Apps targeting
+ * earlier versions will always request the permission.)
+ * </ul>
+ */
+ public static final int DONUT = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/LatencyTimer.java b/core/java/android/os/LatencyTimer.java
new file mode 100644
index 0000000..ed2f0f9
--- /dev/null
+++ b/core/java/android/os/LatencyTimer.java
@@ -0,0 +1,94 @@
+/*
+ * 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 android.os;
+
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * A class to help with measuring latency in your code.
+ *
+ * Suggested usage:
+ * 1) Instanciate a LatencyTimer as a class field.
+ * private [static] LatencyTimer mLt = new LatencyTimer(100, 1000);
+ * 2) At various points in the code call sample with a string and the time delta to some fixed time.
+ * The string should be unique at each point of the code you are measuring.
+ * mLt.sample("before processing event", System.nanoTime() - event.getEventTimeNano());
+ * processEvent(event);
+ * mLt.sample("after processing event ", System.nanoTime() - event.getEventTimeNano());
+ *
+ * @hide
+ */
+public final class LatencyTimer
+{
+ final String TAG = "LatencyTimer";
+ final int mSampleSize;
+ final int mScaleFactor;
+ volatile HashMap<String, long[]> store = new HashMap<String, long[]>();
+
+ /**
+ * Creates a LatencyTimer object
+ * @param sampleSize number of samples to collect before printing out the average
+ * @param scaleFactor divisor used to make each sample smaller to prevent overflow when
+ * (sampleSize * average sample value)/scaleFactor > Long.MAX_VALUE
+ */
+ public LatencyTimer(int sampleSize, int scaleFactor) {
+ if (scaleFactor == 0) {
+ scaleFactor = 1;
+ }
+ mScaleFactor = scaleFactor;
+ mSampleSize = sampleSize;
+ }
+
+ /**
+ * Add a sample delay for averaging.
+ * @param tag string used for printing out the result. This should be unique at each point of
+ * this called.
+ * @param delta time difference from an unique point of reference for a particular iteration
+ */
+ public void sample(String tag, long delta) {
+ long[] array = getArray(tag);
+
+ // array[mSampleSize] holds the number of used entries
+ final int index = (int) array[mSampleSize]++;
+ array[index] = delta;
+ if (array[mSampleSize] == mSampleSize) {
+ long totalDelta = 0;
+ for (long d : array) {
+ totalDelta += d/mScaleFactor;
+ }
+ array[mSampleSize] = 0;
+ Log.i(TAG, tag + " average = " + totalDelta / mSampleSize);
+ }
+ }
+
+ private long[] getArray(String tag) {
+ long[] data = store.get(tag);
+ if (data == null) {
+ synchronized(store) {
+ data = store.get(tag);
+ if (data == null) {
+ data = new long[mSampleSize + 1];
+ store.put(tag, data);
+ data[mSampleSize] = 0;
+ }
+ }
+ }
+ return data;
+ }
+}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 30acef9..333c7cb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -604,6 +604,20 @@
*/
public static final native void setThreadGroup(int tid, int group)
throws IllegalArgumentException, SecurityException;
+ /**
+ * Sets the scheduling group for a process and all child threads
+ * @hide
+ * @param pid The indentifier of the process to change.
+ * @param group The target group for this process.
+ *
+ * @throws IllegalArgumentException Throws IllegalArgumentException if
+ * <var>tid</var> does not exist.
+ * @throws SecurityException Throws SecurityException if your process does
+ * not have permission to modify the given thread, or to use the given
+ * priority.
+ */
+ public static final native void setProcessGroup(int pid, int group)
+ throws IllegalArgumentException, SecurityException;
/**
* Set the priority of the calling thread, based on Linux priorities. See
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
index edf69ee..3ea9b4a 100644
--- a/core/java/android/pim/EventRecurrence.java
+++ b/core/java/android/pim/EventRecurrence.java
@@ -408,13 +408,13 @@
private String dayToString(Resources r, int day) {
switch (day) {
- case SU: return r.getString(com.android.internal.R.string.sunday);
- case MO: return r.getString(com.android.internal.R.string.monday);
- case TU: return r.getString(com.android.internal.R.string.tuesday);
- case WE: return r.getString(com.android.internal.R.string.wednesday);
- case TH: return r.getString(com.android.internal.R.string.thursday);
- case FR: return r.getString(com.android.internal.R.string.friday);
- case SA: return r.getString(com.android.internal.R.string.saturday);
+ case SU: return r.getString(com.android.internal.R.string.day_of_week_long_sunday);
+ case MO: return r.getString(com.android.internal.R.string.day_of_week_long_monday);
+ case TU: return r.getString(com.android.internal.R.string.day_of_week_long_tuesday);
+ case WE: return r.getString(com.android.internal.R.string.day_of_week_long_wednesday);
+ case TH: return r.getString(com.android.internal.R.string.day_of_week_long_thursday);
+ case FR: return r.getString(com.android.internal.R.string.day_of_week_long_friday);
+ case SA: return r.getString(com.android.internal.R.string.day_of_week_long_saturday);
default: throw new IllegalArgumentException("bad day argument: " + day);
}
}
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index 3c23db0..f2c275e 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -137,6 +137,8 @@
CRASHES_TRUNCATED,
ELAPSED_REALTIME_SEC,
ELAPSED_UPTIME_SEC,
+ HTTP_REQUEST,
+ HTTP_REUSED,
HTTP_STATUS,
PHONE_GSM_REGISTERED,
PHONE_GPRS_ATTEMPTED,
@@ -351,6 +353,3 @@
}
}
}
-
-
-
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index a6450f3..0829cfb 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -349,27 +349,33 @@
}
/**
+ * @hide Used in vCard parser code.
+ */
+ public static long tryGetMyContactsGroupId(ContentResolver resolver) {
+ Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
+ Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);
+ if (groupsCursor != null) {
+ try {
+ if (groupsCursor.moveToFirst()) {
+ return groupsCursor.getLong(0);
+ }
+ } finally {
+ groupsCursor.close();
+ }
+ }
+ return 0;
+ }
+
+ /**
* Adds a person to the My Contacts group.
- *
+ *
* @param resolver the resolver to use
* @param personId the person to add to the group
* @return the URI of the group membership row
* @throws IllegalStateException if the My Contacts group can't be found
*/
public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) {
- long groupId = 0;
- Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
- Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);
- if (groupsCursor != null) {
- try {
- if (groupsCursor.moveToFirst()) {
- groupId = groupsCursor.getLong(0);
- }
- } finally {
- groupsCursor.close();
- }
- }
-
+ long groupId = tryGetMyContactsGroupId(resolver);
if (groupId == 0) {
throw new IllegalStateException("Failed to find the My Contacts group");
}
@@ -884,6 +890,17 @@
public static final int TYPE_OTHER = 3;
/**
+ * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future.
+ */
+ public static final int MOBILE_EMAIL_TYPE_INDEX = 2;
+
+ /**
+ * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future.
+ * This is not "mobile" but "CELL" since vCard uses it for identifying mobile phone.
+ */
+ public static final String MOBILE_EMAIL_TYPE_NAME = "_AUTO_CELL";
+
+ /**
* The user defined label for the the contact method.
* <P>Type: TEXT</P>
*/
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
index 898c321..c36f508 100644
--- a/core/java/android/provider/Im.java
+++ b/core/java/android/provider/Im.java
@@ -973,7 +973,7 @@
/**
* Gets the Uri to query messages by provider.
*
- * @param providerId the server provider id.
+ * @param providerId the service provider id.
* @return the Uri
*/
public static final Uri getContentUriByProvider(long providerId) {
@@ -983,21 +983,74 @@
}
/**
- * Gets the Uri to query groupchat messages by thread id.
+ * Gets the Uri to query off the record messages by account.
*
- * @param threadId the thread id of the groupchat message.
+ * @param accountId the account id.
* @return the Uri
*/
- public static final Uri getGroupChatContentUriByThreadId(long threadId) {
- Uri.Builder builder = GROUP_CHAT_CONTENT_URI_MESSAGES_BY_THREAD_ID.buildUpon();
+ public static final Uri getContentUriByAccount(long accountId) {
+ Uri.Builder builder = CONTENT_URI_BY_ACCOUNT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by thread id.
+ *
+ * @param threadId the thread id of the message.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByThreadId(long threadId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID.buildUpon();
ContentUris.appendId(builder, threadId);
return builder.build();
}
/**
+ * @deprecated
+ *
+ * Gets the Uri to query off the record messages by account and contact.
+ *
+ * @param accountId the account id of the contact.
+ * @param username the user name of the contact.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByContact(long accountId, String username) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ builder.appendPath(username);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by provider.
+ *
+ * @param providerId the service provider id.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByProvider(long providerId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_PROVIDER.buildUpon();
+ ContentUris.appendId(builder, providerId);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by account.
+ *
+ * @param accountId the account id.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByAccount(long accountId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ return builder.build();
+ }
+
+ /**
* The content:// style URL for this table
*/
- public static final Uri CONTENT_URI = Uri.parse("content://im/messages");
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://im/messages");
/**
* The content:// style URL for messages by thread id
@@ -1018,32 +1071,47 @@
Uri.parse("content://im/messagesByProvider");
/**
- * The content:// style URL for groupchat messages.
+ * The content:// style URL for messages by account
*/
- public static final Uri GROUP_CHAT_CONTENT_URI = Uri.parse("content://im/groupMessages");
+ public static final Uri CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://im/messagesByAccount");
/**
- * The content:// style URL for groupchat messages by thread id
+ * The content:// style url for off the record messages
*/
- public static final Uri GROUP_CHAT_CONTENT_URI_MESSAGES_BY_THREAD_ID =
- Uri.parse("content://im/groupMessagesByThreadId");
+ public static final Uri OTR_MESSAGES_CONTENT_URI =
+ Uri.parse("content://im/otrMessages");
/**
- * The MIME type of {@link #CONTENT_URI} providing a directory of groupchat messages.
+ * The content:// style url for off the record messages by thread id
*/
- public static final String GROUP_CHAT_CONTENT_TYPE =
- "vnd.android.cursor.dir/im-groupMessages";
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID =
+ Uri.parse("content://im/otrMessagesByThreadId");
/**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single groupchat message.
+ * The content:// style url for off the record messages by account and contact
*/
- public static final String GROUP_CHAT_CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-groupMessages";
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT =
+ Uri.parse("content://im/otrMessagesByAcctAndContact");
+
+ /**
+ * The content:// style URL for off the record messages by provider
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_PROVIDER =
+ Uri.parse("content://im/otrMessagesByProvider");
+
+ /**
+ * The content:// style URL for off the record messages by account
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://im/otrMessagesByAccount");
+
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-messages";
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/im-messages";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 79b4e97..abe3274 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -148,7 +148,7 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WIFI_SETTINGS =
"android.settings.WIFI_SETTINGS";
-
+
/**
* Activity Action: Show settings to allow configuration of a static IP
* address for Wi-Fi.
@@ -305,7 +305,7 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_QUICK_LAUNCH_SETTINGS =
"android.settings.QUICK_LAUNCH_SETTINGS";
-
+
/**
* Activity Action: Show settings to manage installed applications.
* <p>
@@ -319,7 +319,7 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS =
"android.settings.MANAGE_APPLICATIONS_SETTINGS";
-
+
/**
* Activity Action: Show settings for system update functionality.
* <p>
@@ -329,7 +329,7 @@
* Input: Nothing.
* <p>
* Output: Nothing.
- *
+ *
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -349,7 +349,7 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SYNC_SETTINGS =
"android.settings.SYNC_SETTINGS";
-
+
/**
* Activity Action: Show settings for selecting the network operator.
* <p>
@@ -404,7 +404,7 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MEMORY_CARD_SETTINGS =
"android.settings.MEMORY_CARD_SETTINGS";
-
+
// End of Intent actions for Settings
private static final String JID_RESOURCE_PREFIX = "android";
@@ -495,7 +495,7 @@
public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
private static volatile NameValueCache mNameValueCache = null;
-
+
private static final HashSet<String> MOVED_TO_SECURE;
static {
MOVED_TO_SECURE = new HashSet<String>(30);
@@ -901,12 +901,12 @@
* plugged in.
*/
public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
-
+
/**
* Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep.
*/
public static final int WIFI_SLEEP_POLICY_NEVER = 2;
-
+
/**
* Whether to use static IP and other static network attributes.
* <p>
@@ -1115,12 +1115,12 @@
* Note: This is a one-off setting that will be removed in the future
* when there is profile support. For this reason, it is kept hidden
* from the public APIs.
- *
+ *
* @hide
*/
- public static final String NOTIFICATIONS_USE_RING_VOLUME =
+ public static final String NOTIFICATIONS_USE_RING_VOLUME =
"notifications_use_ring_volume";
-
+
/**
* The mapping of stream type (integer) to its setting.
*/
@@ -1204,7 +1204,7 @@
* feature converts two spaces to a "." and space.
*/
public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
-
+
/**
* Setting to showing password characters in text editors. 1 = On, 0 = Off
*/
@@ -1286,13 +1286,13 @@
* boolean (1 or 0).
*/
public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
-
+
/**
* Whether the haptic feedback (long presses, ...) are enabled. The value is
* boolean (1 or 0).
*/
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
-
+
// Settings moved to Settings.Secure
/**
@@ -1337,7 +1337,7 @@
*/
@Deprecated
public static final String INSTALL_NON_MARKET_APPS = Secure.INSTALL_NON_MARKET_APPS;
-
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED}
* instead
@@ -1350,7 +1350,7 @@
*/
@Deprecated
public static final String LOGGING_ID = Secure.LOGGING_ID;
-
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#NETWORK_PREFERENCE} instead
*/
@@ -1390,7 +1390,7 @@
*/
@Deprecated
public static final String USB_MASS_STORAGE_ENABLED = Secure.USB_MASS_STORAGE_ENABLED;
-
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#USE_GOOGLE_MAIL} instead
*/
@@ -1428,7 +1428,7 @@
@Deprecated
public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
-
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#WIFI_NUM_OPEN_NETWORKS_KEPT}
* instead
@@ -1464,7 +1464,7 @@
@Deprecated
public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS;
-
+
/**
* @deprecated Use
* {@link android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED} instead
@@ -1840,19 +1840,19 @@
* Whether the device has been provisioned (0 = false, 1 = true)
*/
public static final String DEVICE_PROVISIONED = "device_provisioned";
-
+
/**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
*/
public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
-
+
/**
* Host name and port for a user-selected proxy.
*/
public static final String HTTP_PROXY = "http_proxy";
-
+
/**
* Whether the package installer should allow installation of apps downloaded from
* sources other than the Android Market (vending machine).
@@ -1861,12 +1861,12 @@
* 0 = only allow installing from the Android Market
*/
public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
-
+
/**
* Comma-separated list of location providers that activities may access.
*/
public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
-
+
/**
* The Logging ID (a unique 64-bit value) as a hex string.
* Used as a pseudonymous identifier for logging.
@@ -1888,19 +1888,19 @@
* connectivity service should touch this.
*/
public static final String NETWORK_PREFERENCE = "network_preference";
-
- /**
+
+ /**
*/
public static final String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
-
- /**
+
+ /**
*/
public static final String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
-
- /**
+
+ /**
*/
public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
-
+
/**
* Settings classname to launch when Settings is clicked from All
* Applications. Needed because of user testing between the old
@@ -1908,18 +1908,18 @@
*/
// TODO: 881807
public static final String SETTINGS_CLASSNAME = "settings_classname";
-
+
/**
* USB Mass Storage Enabled
*/
public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
-
+
/**
* If this setting is set (to anything), then all references
* to Gmail on the device must change to Google Mail.
*/
public static final String USE_GOOGLE_MAIL = "use_google_mail";
-
+
/**
* If accessibility is enabled.
*/
@@ -1942,64 +1942,64 @@
*/
public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
"wifi_networks_available_notification_on";
-
+
/**
* Delay (in seconds) before repeating the Wi-Fi networks available notification.
* Connecting to a network will reset the timer.
*/
public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
"wifi_networks_available_repeat_delay";
-
+
/**
* The number of radio channels that are allowed in the local
* 802.11 regulatory domain.
* @hide
*/
public static final String WIFI_NUM_ALLOWED_CHANNELS = "wifi_num_allowed_channels";
-
+
/**
* When the number of open networks exceeds this number, the
* least-recently-used excess networks will be removed.
*/
public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
-
+
/**
* Whether the Wi-Fi should be on. Only the Wi-Fi service should touch this.
*/
public static final String WIFI_ON = "wifi_on";
-
+
/**
* The acceptable packet loss percentage (range 0 - 100) before trying
* another AP on the same network.
*/
public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE =
"wifi_watchdog_acceptable_packet_loss_percentage";
-
+
/**
* The number of access points required for a network in order for the
* watchdog to monitor it.
*/
public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
-
+
/**
* The delay between background checks.
*/
public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
"wifi_watchdog_background_check_delay_ms";
-
+
/**
* Whether the Wi-Fi watchdog is enabled for background checking even
* after it thinks the user has connected to a good access point.
*/
public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED =
"wifi_watchdog_background_check_enabled";
-
+
/**
* The timeout for a background ping
*/
public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS =
"wifi_watchdog_background_check_timeout_ms";
-
+
/**
* The number of initial pings to perform that *may* be ignored if they
* fail. Again, if these fail, they will *not* be used in packet loss
@@ -2008,7 +2008,7 @@
*/
public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT =
"wifi_watchdog_initial_ignored_ping_count";
-
+
/**
* The maximum number of access points (per network) to attempt to test.
* If this number is reached, the watchdog will no longer monitor the
@@ -2016,7 +2016,7 @@
* networks containing multiple APs whose DNS does not respond to pings.
*/
public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
-
+
/**
* Whether the Wi-Fi watchdog is enabled.
*/
@@ -2031,24 +2031,24 @@
* The number of pings to test if an access point is a good connection.
*/
public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
-
+
/**
* The delay between pings.
*/
public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
-
+
/**
* The timeout per ping.
*/
public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
-
+
/**
* The maximum number of times we will retry a connection to an access
* point for which we have failed in acquiring an IP address from DHCP.
* A value of N means that we will make N+1 connection attempts in all.
*/
public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
-
+
/**
* Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile
* data connectivity to be established after a disconnect from Wi-Fi.
@@ -2078,22 +2078,31 @@
public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
/**
- * represents current active phone class
- * 1 = GSM-Phone, 0 = CDMA-Phone
- * @hide
- */
- public static final String CURRENT_ACTIVE_PHONE = "current_active_phone";
-
- /**
- * The preferred network mode 7 = Global, CDMA default
- * 4 = CDMA only
- * 3 = GSM/UMTS only
+ * The preferred network mode 7 = Global
+ * 6 = EvDo only
+ * 5 = CDMA w/o EvDo
+ * 4 = CDMA / EvDo auto
+ * 3 = GSM / WCDMA auto
+ * 2 = WCDMA only
+ * 1 = GSM only
+ * 0 = GSM / WCDMA preferred
* @hide
*/
public static final String PREFERRED_NETWORK_MODE =
"preferred_network_mode";
/**
+ * The preferred TTY mode 0 = TTy Off, CDMA default
+ * 1 = TTY Full
+ * 2 = TTY HCO
+ * 3 = TTY VCO
+ * @hide
+ */
+ public static final String PREFERRED_TTY_MODE =
+ "preferred_tty_mode";
+
+
+ /**
* CDMA Cell Broadcast SMS
* 0 = CDMA Cell Broadcast SMS disabled
* 1 = CDMA Cell Broadcast SMS enabled
@@ -2142,7 +2151,7 @@
allowedProviders.startsWith(provider + ",") ||
allowedProviders.endsWith("," + provider));
}
- return false;
+ return false;
}
/**
@@ -2166,7 +2175,7 @@
putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
}
}
-
+
/**
* Gservices settings, containing the network names for Google's
* various services. This table holds simple name/addr pairs.
@@ -2187,6 +2196,13 @@
public static final String CHANGED_ACTION =
"com.google.gservices.intent.action.GSERVICES_CHANGED";
+ /**
+ * Intent action to override Gservices for testing. (Requires WRITE_GSERVICES permission.)
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String OVERRIDE_ACTION =
+ "com.google.gservices.intent.action.GSERVICES_OVERRIDE";
+
private static volatile NameValueCache mNameValueCache = null;
private static final Object mNameValueCacheLock = new Object();
@@ -2287,7 +2303,7 @@
* Event tags from the kernel event log to upload during checkin.
*/
public static final String CHECKIN_EVENTS = "checkin_events";
-
+
/**
* Event tags for list of services to upload during checkin.
*/
@@ -2982,7 +2998,7 @@
public static final String BATTERY_DISCHARGE_DURATION_THRESHOLD =
"battery_discharge_duration_threshold";
public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold";
-
+
/**
* An email address that anr bugreports should be sent to.
*/
@@ -3126,7 +3142,7 @@
/**
* Add a new bookmark to the system.
- *
+ *
* @param cr The ContentResolver to query.
* @param intent The desired target of the bookmark.
* @param title Bookmark title that is shown to the user; null if none
@@ -3191,7 +3207,7 @@
/**
* Return the title as it should be displayed to the user. This takes
* care of localizing bookmarks that point to activities.
- *
+ *
* @param context A context.
* @param cursor A cursor pointing to the row whose title should be
* returned. The cursor must contain at least the {@link #TITLE}
@@ -3206,24 +3222,24 @@
throw new IllegalArgumentException(
"The cursor must contain the TITLE and INTENT columns.");
}
-
+
String title = cursor.getString(titleColumn);
if (!TextUtils.isEmpty(title)) {
return title;
}
-
+
String intentUri = cursor.getString(intentColumn);
if (TextUtils.isEmpty(intentUri)) {
return "";
}
-
+
Intent intent;
try {
intent = Intent.getIntent(intentUri);
} catch (URISyntaxException e) {
return "";
}
-
+
PackageManager packageManager = context.getPackageManager();
ResolveInfo info = packageManager.resolveActivity(intent, 0);
return info != null ? info.loadLabel(packageManager) : "";
@@ -3279,4 +3295,3 @@
return "android-" + Long.toHexString(androidId);
}
}
-
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 03623d6..952372f 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -37,9 +37,6 @@
// general debugging support
private static final String TAG = "SearchManagerService";
private static final boolean DEBUG = false;
-
- // configuration choices
- private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true;
// class maintenance and general shared data
private final Context mContext;
@@ -70,9 +67,7 @@
// After startup settles down, preload the searchables list,
// which will reduce the delay when the search UI is invoked.
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
+ mHandler.post(mRunUpdateSearchable);
}
/**
@@ -91,9 +86,7 @@
action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
mSearchablesDirty = true;
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
+ mHandler.post(mRunUpdateSearchable);
return;
}
}
@@ -104,9 +97,7 @@
*/
private Runnable mRunUpdateSearchable = new Runnable() {
public void run() {
- if (mSearchablesDirty) {
- updateSearchables();
- }
+ updateSearchablesIfDirty();
}
};
@@ -120,6 +111,15 @@
}
/**
+ * Updates the list of searchables if needed.
+ */
+ private void updateSearchablesIfDirty() {
+ if (mSearchablesDirty) {
+ updateSearchables();
+ }
+ }
+
+ /**
* Returns the SearchableInfo for a given activity
*
* @param launchActivity The activity from which we're launching this search.
@@ -131,11 +131,7 @@
* or null if no searchable metadata was available.
*/
public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
- // final check. however we should try to avoid this, because
- // it slows down the entry into the UI.
- if (mSearchablesDirty) {
- updateSearchables();
- }
+ updateSearchablesIfDirty();
SearchableInfo si = null;
if (globalSearch) {
si = mSearchables.getDefaultSearchable();
@@ -150,6 +146,7 @@
* Returns a list of the searchable activities that can be included in global search.
*/
public List<SearchableInfo> getSearchablesInGlobalSearch() {
+ updateSearchablesIfDirty();
return mSearchables.getSearchablesInGlobalSearchList();
}
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 9586d56..62631d6 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
@@ -34,6 +35,8 @@
*/
public class Searchables {
+ private static final String LOG_TAG = "Searchables";
+
// static strings used for XML lookups, etc.
// TODO how should these be documented for the developer, in a more structured way than
// the current long wordy javadoc in SearchManager.java ?
@@ -184,7 +187,6 @@
* TODO: sort the list somehow? UI choice.
*/
public void buildSearchableList() {
-
// These will become the new values at the end of the method
HashMap<ComponentName, SearchableInfo> newSearchablesMap
= new HashMap<ComponentName, SearchableInfo>();
@@ -223,6 +225,11 @@
ComponentName globalSearchActivity = globalSearchIntent.resolveActivity(pm);
SearchableInfo newDefaultSearchable = newSearchablesMap.get(globalSearchActivity);
+ if (newDefaultSearchable == null) {
+ Log.w(LOG_TAG, "No searchable info found for new default searchable activity "
+ + globalSearchActivity);
+ }
+
// Store a consistent set of new values
synchronized (this) {
mSearchablesMap = newSearchablesMap;
diff --git a/core/java/android/syncml/pim/PropertyNode.java b/core/java/android/syncml/pim/PropertyNode.java
index cc52499..983ecb8 100644
--- a/core/java/android/syncml/pim/PropertyNode.java
+++ b/core/java/android/syncml/pim/PropertyNode.java
@@ -17,12 +17,16 @@
package android.syncml.pim;
import android.content.ContentValues;
-import android.util.Log;
+import org.apache.commons.codec.binary.Base64;
+
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
public class PropertyNode {
@@ -52,7 +56,9 @@
public Set<String> propGroupSet;
public PropertyNode() {
+ propName = "";
propValue = "";
+ propValue_vector = new ArrayList<String>();
paramMap = new ContentValues();
paramMap_TYPE = new HashSet<String>();
propGroupSet = new HashSet<String>();
@@ -62,13 +68,21 @@
String propName, String propValue, List<String> propValue_vector,
byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE,
Set<String> propGroupSet) {
- this.propName = propName;
+ if (propName != null) {
+ this.propName = propName;
+ } else {
+ this.propName = "";
+ }
if (propValue != null) {
this.propValue = propValue;
} else {
this.propValue = "";
}
- this.propValue_vector = propValue_vector;
+ if (propValue_vector != null) {
+ this.propValue_vector = propValue_vector;
+ } else {
+ this.propValue_vector = new ArrayList<String>();
+ }
this.propValue_bytes = propValue_bytes;
if (paramMap != null) {
this.paramMap = paramMap;
@@ -117,17 +131,9 @@
// decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector
// is 1, the encoded value is stored in propValue, so we do not have to
// check it.
- if (propValue_vector != null) {
- // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector);
- return (propValue_vector.equals(node.propValue_vector) ||
- (propValue_vector.size() == 1));
- } else if (node.propValue_vector != null) {
- // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector);
- return (node.propValue_vector.equals(propValue_vector) ||
- (node.propValue_vector.size() == 1));
- } else {
- return true;
- }
+ return (propValue_vector.equals(node.propValue_vector) ||
+ propValue_vector.size() == 1 ||
+ node.propValue_vector.size() == 1);
}
}
@@ -154,4 +160,164 @@
builder.append(propValue);
return builder.toString();
}
+
+ /**
+ * Encode this object into a string which can be decoded.
+ */
+ public String encode() {
+ // PropertyNode#toString() is for reading, not for parsing in the future.
+ // We construct appropriate String here.
+ StringBuilder builder = new StringBuilder();
+ if (propName.length() > 0) {
+ builder.append("propName:[");
+ builder.append(propName);
+ builder.append("],");
+ }
+ int size = propGroupSet.size();
+ if (size > 0) {
+ Set<String> set = propGroupSet;
+ builder.append("propGroup:[");
+ int i = 0;
+ for (String group : set) {
+ // We do not need to double quote groups.
+ // group = 1*(ALPHA / DIGIT / "-")
+ builder.append(group);
+ if (i < size - 1) {
+ builder.append(",");
+ }
+ i++;
+ }
+ builder.append("],");
+ }
+
+ if (paramMap.size() > 0 || paramMap_TYPE.size() > 0) {
+ ContentValues values = paramMap;
+ builder.append("paramMap:[");
+ size = paramMap.size();
+ int i = 0;
+ for (Entry<String, Object> entry : values.valueSet()) {
+ // Assuming param-key does not contain NON-ASCII nor symbols.
+ //
+ // According to vCard 3.0:
+ // param-name = iana-token / x-name
+ builder.append(entry.getKey());
+
+ // param-value may contain any value including NON-ASCIIs.
+ // We use the following replacing rule.
+ // \ -> \\
+ // , -> \,
+ // In String#replaceAll(), "\\\\" means a single backslash.
+ builder.append("=");
+ builder.append(entry.getValue().toString()
+ .replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll(",", "\\\\,"));
+ if (i < size -1) {
+ builder.append(",");
+ }
+ i++;
+ }
+
+ Set<String> set = paramMap_TYPE;
+ size = paramMap_TYPE.size();
+ if (i > 0 && size > 0) {
+ builder.append(",");
+ }
+ i = 0;
+ for (String type : set) {
+ builder.append("TYPE=");
+ builder.append(type
+ .replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll(",", "\\\\,"));
+ if (i < size - 1) {
+ builder.append(",");
+ }
+ i++;
+ }
+ builder.append("],");
+ }
+
+ size = propValue_vector.size();
+ if (size > 0) {
+ builder.append("propValue:[");
+ List<String> list = propValue_vector;
+ for (int i = 0; i < size; i++) {
+ builder.append(list.get(i)
+ .replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll(",", "\\\\,"));
+ if (i < size -1) {
+ builder.append(",");
+ }
+ }
+ builder.append("],");
+ }
+
+ return builder.toString();
+ }
+
+ public static PropertyNode decode(String encodedString) {
+ PropertyNode propertyNode = new PropertyNode();
+ String trimed = encodedString.trim();
+ if (trimed.length() == 0) {
+ return propertyNode;
+ }
+ String[] elems = trimed.split("],");
+
+ for (String elem : elems) {
+ int index = elem.indexOf('[');
+ String name = elem.substring(0, index - 1);
+ Pattern pattern = Pattern.compile("(?<!\\\\),");
+ String[] values = pattern.split(elem.substring(index + 1), -1);
+ if (name.equals("propName")) {
+ propertyNode.propName = values[0];
+ } else if (name.equals("propGroupSet")) {
+ for (String value : values) {
+ propertyNode.propGroupSet.add(value);
+ }
+ } else if (name.equals("paramMap")) {
+ ContentValues paramMap = propertyNode.paramMap;
+ Set<String> paramMap_TYPE = propertyNode.paramMap_TYPE;
+ for (String value : values) {
+ String[] tmp = value.split("=", 2);
+ String mapKey = tmp[0];
+ // \, -> ,
+ // \\ -> \
+ // In String#replaceAll(), "\\\\" means a single backslash.
+ String mapValue =
+ tmp[1].replaceAll("\\\\,", ",").replaceAll("\\\\\\\\", "\\\\");
+ if (mapKey.equalsIgnoreCase("TYPE")) {
+ paramMap_TYPE.add(mapValue);
+ } else {
+ paramMap.put(mapKey, mapValue);
+ }
+ }
+ } else if (name.equals("propValue")) {
+ StringBuilder builder = new StringBuilder();
+ List<String> list = propertyNode.propValue_vector;
+ int length = values.length;
+ for (int i = 0; i < length; i++) {
+ String normValue = values[i]
+ .replaceAll("\\\\,", ",")
+ .replaceAll("\\\\\\\\", "\\\\");
+ list.add(normValue);
+ builder.append(normValue);
+ if (i < length - 1) {
+ builder.append(";");
+ }
+ }
+ propertyNode.propValue = builder.toString();
+ }
+ }
+
+ // At this time, QUOTED-PRINTABLE is already decoded to Java String.
+ // We just need to decode BASE64 String to binary.
+ String encoding = propertyNode.paramMap.getAsString("ENCODING");
+ if (encoding != null &&
+ (encoding.equalsIgnoreCase("BASE64") ||
+ encoding.equalsIgnoreCase("B"))) {
+ propertyNode.propValue_bytes =
+ Base64.decodeBase64(propertyNode.propValue_vector.get(0).getBytes());
+ }
+
+ return propertyNode;
+ }
}
diff --git a/core/java/android/syncml/pim/VBuilderCollection.java b/core/java/android/syncml/pim/VBuilderCollection.java
new file mode 100644
index 0000000..f09c1c4
--- /dev/null
+++ b/core/java/android/syncml/pim/VBuilderCollection.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.syncml.pim;
+
+import java.util.Collection;
+import java.util.List;
+
+public class VBuilderCollection implements VBuilder {
+
+ private final Collection<VBuilder> mVBuilderCollection;
+
+ public VBuilderCollection(Collection<VBuilder> vBuilderCollection) {
+ mVBuilderCollection = vBuilderCollection;
+ }
+
+ public Collection<VBuilder> getVBuilderCollection() {
+ return mVBuilderCollection;
+ }
+
+ public void start() {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.start();
+ }
+ }
+
+ public void end() {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.end();
+ }
+ }
+
+ public void startRecord(String type) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.startRecord(type);
+ }
+ }
+
+ public void endRecord() {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.endRecord();
+ }
+ }
+
+ public void startProperty() {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.startProperty();
+ }
+ }
+
+
+ public void endProperty() {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.endProperty();
+ }
+ }
+
+ public void propertyGroup(String group) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.propertyGroup(group);
+ }
+ }
+
+ public void propertyName(String name) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.propertyName(name);
+ }
+ }
+
+ public void propertyParamType(String type) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.propertyParamType(type);
+ }
+ }
+
+ public void propertyParamValue(String value) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.propertyParamValue(value);
+ }
+ }
+
+ public void propertyValues(List<String> values) {
+ for (VBuilder builder : mVBuilderCollection) {
+ builder.propertyValues(values);
+ }
+ }
+}
diff --git a/core/java/android/syncml/pim/VDataBuilder.java b/core/java/android/syncml/pim/VDataBuilder.java
index 8c67cf5..f6e5b65 100644
--- a/core/java/android/syncml/pim/VDataBuilder.java
+++ b/core/java/android/syncml/pim/VDataBuilder.java
@@ -17,8 +17,10 @@
package android.syncml.pim;
import android.content.ContentValues;
+import android.util.CharsetUtils;
import android.util.Log;
+import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.net.QuotedPrintableCodec;
@@ -26,9 +28,7 @@
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
-import java.util.Vector;
/**
* Store the parse result to custom datastruct: VNode, PropertyNode
@@ -38,7 +38,13 @@
*/
public class VDataBuilder implements VBuilder {
static private String LOG_TAG = "VDATABuilder";
-
+
+ /**
+ * If there's no other information available, this class uses this charset for encoding
+ * byte arrays.
+ */
+ static public String DEFAULT_CHARSET = "UTF-8";
+
/** type=VNode */
public List<VNode> vNodeList = new ArrayList<VNode>();
private int mNodeListPos = 0;
@@ -47,34 +53,74 @@
private String mCurrentParamType;
/**
- * Assumes that each String can be encoded into byte array using this encoding.
+ * The charset using which VParser parses the text.
*/
- private String mCharset;
+ private String mSourceCharset;
+
+ /**
+ * The charset with which byte array is encoded to String.
+ */
+ private String mTargetCharset;
private boolean mStrictLineBreakParsing;
public VDataBuilder() {
- mCharset = "ISO-8859-1";
- mStrictLineBreakParsing = false;
+ this(VParser.DEFAULT_CHARSET, DEFAULT_CHARSET, false);
}
- public VDataBuilder(String encoding, boolean strictLineBreakParsing) {
- mCharset = encoding;
- mStrictLineBreakParsing = strictLineBreakParsing;
+ public VDataBuilder(String charset, boolean strictLineBreakParsing) {
+ this(null, charset, strictLineBreakParsing);
}
+ /**
+ * @hide sourceCharset is temporal.
+ */
+ public VDataBuilder(String sourceCharset, String targetCharset,
+ boolean strictLineBreakParsing) {
+ if (sourceCharset != null) {
+ mSourceCharset = sourceCharset;
+ } else {
+ mSourceCharset = VParser.DEFAULT_CHARSET;
+ }
+ if (targetCharset != null) {
+ mTargetCharset = targetCharset;
+ } else {
+ mTargetCharset = DEFAULT_CHARSET;
+ }
+ mStrictLineBreakParsing = strictLineBreakParsing;
+ }
+
public void start() {
}
public void end() {
}
+ // Note: I guess that this code assumes the Record may nest like this:
+ // START:VPOS
+ // ...
+ // START:VPOS2
+ // ...
+ // END:VPOS2
+ // ...
+ // END:VPOS
+ //
+ // However the following code has a bug.
+ // When error occurs after calling startRecord(), the entry which is probably
+ // the cause of the error remains to be in vNodeList, while endRecord() is not called.
+ //
+ // I leave this code as is since I'm not familiar with vcalendar specification.
+ // But I believe we should refactor this code in the future.
+ // Until this, the last entry has to be removed when some error occurs.
public void startRecord(String type) {
+
VNode vnode = new VNode();
vnode.parseStatus = 1;
vnode.VName = type;
+ // I feel this should be done in endRecord(), but it cannot be done because of
+ // the reason above.
vNodeList.add(vnode);
- mNodeListPos = vNodeList.size()-1;
+ mNodeListPos = vNodeList.size() - 1;
mCurrentVNode = vNodeList.get(mNodeListPos);
}
@@ -90,15 +136,14 @@
}
public void startProperty() {
- // System.out.println("+ startProperty. ");
+ mCurrentPropNode = new PropertyNode();
}
public void endProperty() {
- // System.out.println("- endProperty. ");
+ mCurrentVNode.propList.add(mCurrentPropNode);
}
public void propertyName(String name) {
- mCurrentPropNode = new PropertyNode();
mCurrentPropNode.propName = name;
}
@@ -122,139 +167,145 @@
mCurrentParamType = null;
}
- private String encodeString(String originalString, String targetEncoding) {
- Charset charset = Charset.forName(mCharset);
+ private String encodeString(String originalString, String targetCharset) {
+ if (mSourceCharset.equalsIgnoreCase(targetCharset)) {
+ return originalString;
+ }
+ Charset charset = Charset.forName(mSourceCharset);
ByteBuffer byteBuffer = charset.encode(originalString);
// byteBuffer.array() "may" return byte array which is larger than
// byteBuffer.remaining(). Here, we keep on the safe side.
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
try {
- return new String(bytes, targetEncoding);
+ return new String(bytes, targetCharset);
} catch (UnsupportedEncodingException e) {
- return null;
+ Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
+ return new String(bytes);
}
}
+ private String handleOneValue(String value, String targetCharset, String encoding) {
+ if (encoding != null) {
+ if (encoding.equals("BASE64") || encoding.equals("B")) {
+ // Assume BASE64 is used only when the number of values is 1.
+ mCurrentPropNode.propValue_bytes =
+ Base64.decodeBase64(value.getBytes());
+ return value;
+ } else if (encoding.equals("QUOTED-PRINTABLE")) {
+ String quotedPrintable = value
+ .replaceAll("= ", " ").replaceAll("=\t", "\t");
+ String[] lines;
+ if (mStrictLineBreakParsing) {
+ lines = quotedPrintable.split("\r\n");
+ } else {
+ StringBuilder builder = new StringBuilder();
+ int length = quotedPrintable.length();
+ ArrayList<String> list = new ArrayList<String>();
+ for (int i = 0; i < length; i++) {
+ char ch = quotedPrintable.charAt(i);
+ if (ch == '\n') {
+ list.add(builder.toString());
+ builder = new StringBuilder();
+ } else if (ch == '\r') {
+ list.add(builder.toString());
+ builder = new StringBuilder();
+ if (i < length - 1) {
+ char nextCh = quotedPrintable.charAt(i + 1);
+ if (nextCh == '\n') {
+ i++;
+ }
+ }
+ } else {
+ builder.append(ch);
+ }
+ }
+ String finalLine = builder.toString();
+ if (finalLine.length() > 0) {
+ list.add(finalLine);
+ }
+ lines = list.toArray(new String[0]);
+ }
+ StringBuilder builder = new StringBuilder();
+ for (String line : lines) {
+ if (line.endsWith("=")) {
+ line = line.substring(0, line.length() - 1);
+ }
+ builder.append(line);
+ }
+ byte[] bytes;
+ try {
+ bytes = builder.toString().getBytes(mSourceCharset);
+ } catch (UnsupportedEncodingException e1) {
+ Log.e(LOG_TAG, "Failed to encode: charset=" + mSourceCharset);
+ bytes = builder.toString().getBytes();
+ }
+
+ try {
+ bytes = QuotedPrintableCodec.decodeQuotedPrintable(bytes);
+ } catch (DecoderException e) {
+ Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e);
+ return "";
+ }
+
+ try {
+ return new String(bytes, targetCharset);
+ } catch (UnsupportedEncodingException e) {
+ Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
+ return new String(bytes);
+ }
+ }
+ // Unknown encoding. Fall back to default.
+ }
+ return encodeString(value, targetCharset);
+ }
+
public void propertyValues(List<String> values) {
+ if (values == null || values.size() == 0) {
+ mCurrentPropNode.propValue_bytes = null;
+ mCurrentPropNode.propValue_vector.clear();
+ mCurrentPropNode.propValue_vector.add("");
+ mCurrentPropNode.propValue = "";
+ return;
+ }
+
ContentValues paramMap = mCurrentPropNode.paramMap;
- String charsetString = paramMap.getAsString("CHARSET");
-
- boolean setupParamValues = false;
- //decode value string to propValue_bytes
- if (paramMap.containsKey("ENCODING")) {
- String encoding = paramMap.getAsString("ENCODING");
- if (encoding.equalsIgnoreCase("BASE64") ||
- encoding.equalsIgnoreCase("B")) {
- if (values.size() > 1) {
- Log.e(LOG_TAG,
- ("BASE64 encoding is used while " +
- "there are multiple values (" + values.size()));
- }
- mCurrentPropNode.propValue_bytes =
- Base64.decodeBase64(values.get(0).
- replaceAll(" ","").replaceAll("\t","").
- replaceAll("\r\n","").
- getBytes());
- }
-
- if(encoding.equalsIgnoreCase("QUOTED-PRINTABLE")){
- // if CHARSET is defined, we translate each String into the Charset.
- List<String> tmpValues = new ArrayList<String>();
- Vector<byte[]> byteVector = new Vector<byte[]>();
- int size = 0;
- try{
- for (String value : values) {
- String quotedPrintable = value
- .replaceAll("= ", " ").replaceAll("=\t", "\t");
- String[] lines;
- if (mStrictLineBreakParsing) {
- lines = quotedPrintable.split("\r\n");
- } else {
- lines = quotedPrintable
- .replace("\r\n", "\n").replace("\r", "\n").split("\n");
- }
- StringBuilder builder = new StringBuilder();
- for (String line : lines) {
- if (line.endsWith("=")) {
- line = line.substring(0, line.length() - 1);
- }
- builder.append(line);
- }
- byte[] bytes = QuotedPrintableCodec.decodeQuotedPrintable(
- builder.toString().getBytes());
- if (charsetString != null) {
- try {
- tmpValues.add(new String(bytes, charsetString));
- } catch (UnsupportedEncodingException e) {
- Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString);
- tmpValues.add(new String(bytes));
- }
- } else {
- tmpValues.add(new String(bytes));
- }
- byteVector.add(bytes);
- size += bytes.length;
- } // for (String value : values) {
- mCurrentPropNode.propValue_vector = tmpValues;
- mCurrentPropNode.propValue = listToString(tmpValues);
-
- mCurrentPropNode.propValue_bytes = new byte[size];
-
- {
- byte[] tmpBytes = mCurrentPropNode.propValue_bytes;
- int index = 0;
- for (byte[] bytes : byteVector) {
- int length = bytes.length;
- for (int i = 0; i < length; i++, index++) {
- tmpBytes[index] = bytes[i];
- }
- }
- }
- setupParamValues = true;
- } catch(Exception e) {
- Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e);
- }
- } // QUOTED-PRINTABLE
- } // ENCODING
+ String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET"));
+ String encoding = paramMap.getAsString("ENCODING");
- if (!setupParamValues) {
- // if CHARSET is defined, we translate each String into the Charset.
- if (charsetString != null) {
- List<String> tmpValues = new ArrayList<String>();
- for (String value : values) {
- String result = encodeString(value, charsetString);
- if (result != null) {
- tmpValues.add(result);
- } else {
- Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString);
- tmpValues.add(value);
- }
- }
- values = tmpValues;
- }
-
- mCurrentPropNode.propValue_vector = values;
- mCurrentPropNode.propValue = listToString(values);
+ if (targetCharset == null || targetCharset.length() == 0) {
+ targetCharset = mTargetCharset;
}
- mCurrentVNode.propList.add(mCurrentPropNode);
+
+ for (String value : values) {
+ mCurrentPropNode.propValue_vector.add(
+ handleOneValue(value, targetCharset, encoding));
+ }
+
+ mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector);
}
- private String listToString(Collection<String> list){
- StringBuilder typeListB = new StringBuilder();
- for (String type : list) {
- typeListB.append(type).append(";");
+ private String listToString(List<String> list){
+ int size = list.size();
+ if (size > 1) {
+ StringBuilder typeListB = new StringBuilder();
+ for (String type : list) {
+ typeListB.append(type).append(";");
+ }
+ int len = typeListB.length();
+ if (len > 0 && typeListB.charAt(len - 1) == ';') {
+ return typeListB.substring(0, len - 1);
+ }
+ return typeListB.toString();
+ } else if (size == 1) {
+ return list.get(0);
+ } else {
+ return "";
}
- int len = typeListB.length();
- if (len > 0 && typeListB.charAt(len - 1) == ';') {
- return typeListB.substring(0, len - 1);
- }
- return typeListB.toString();
}
public String getResult(){
return null;
}
}
-
diff --git a/core/java/android/syncml/pim/VParser.java b/core/java/android/syncml/pim/VParser.java
index df93f38..57c5f7a 100644
--- a/core/java/android/syncml/pim/VParser.java
+++ b/core/java/android/syncml/pim/VParser.java
@@ -26,6 +26,9 @@
*
*/
abstract public class VParser {
+ // Assume that "iso-8859-1" is able to map "all" 8bit characters to some unicode and
+ // decode the unicode to the original charset. If not, this setting will cause some bug.
+ public static String DEFAULT_CHARSET = "iso-8859-1";
/**
* The buffer used to store input stream
@@ -96,6 +99,20 @@
}
/**
+ * Parse the given stream with the default encoding.
+ *
+ * @param is
+ * The source to parse.
+ * @param builder
+ * The v builder which used to construct data.
+ * @return Return true for success, otherwise false.
+ * @throws IOException
+ */
+ public boolean parse(InputStream is, VBuilder builder) throws IOException {
+ return parse(is, DEFAULT_CHARSET, builder);
+ }
+
+ /**
* Copy the content of input stream and filter the "folding"
*/
protected void setInputStream(InputStream is, String encoding)
diff --git a/core/java/android/syncml/pim/vcard/ContactStruct.java b/core/java/android/syncml/pim/vcard/ContactStruct.java
index 8d9b7fa..5a29112 100644
--- a/core/java/android/syncml/pim/vcard/ContactStruct.java
+++ b/core/java/android/syncml/pim/vcard/ContactStruct.java
@@ -16,45 +16,103 @@
package android.syncml.pim.vcard;
-import java.util.List;
+import android.content.AbstractSyncableContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.Contacts;
+import android.provider.Contacts.ContactMethods;
+import android.provider.Contacts.Extensions;
+import android.provider.Contacts.GroupMembership;
+import android.provider.Contacts.Organizations;
+import android.provider.Contacts.People;
+import android.provider.Contacts.Phones;
+import android.provider.Contacts.Photos;
+import android.syncml.pim.PropertyNode;
+import android.syncml.pim.VNode;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+import android.util.Log;
+
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
/**
- * The parameter class of VCardCreator.
+ * The parameter class of VCardComposer.
* This class standy by the person-contact in
* Android system, we must use this class instance as parameter to transmit to
- * VCardCreator so that create vCard string.
+ * VCardComposer so that create vCard string.
*/
// TODO: rename the class name, next step
public class ContactStruct {
- public String company;
+ private static final String LOG_TAG = "ContactStruct";
+
+ // Note: phonetic name probably should be "LAST FIRST MIDDLE" for European languages, and
+ // space should be added between each element while it should not be in Japanese.
+ // But unfortunately, we currently do not have the data and are not sure whether we should
+ // support European version of name ordering.
+ //
+ // TODO: Implement the logic described above if we really need European version of
+ // phonetic name handling. Also, adding the appropriate test case of vCard would be
+ // highly appreciated.
+ public static final int NAME_ORDER_TYPE_ENGLISH = 0;
+ public static final int NAME_ORDER_TYPE_JAPANESE = 1;
+
/** MUST exist */
public String name;
+ public String phoneticName;
/** maybe folding */
- public String notes;
+ public List<String> notes = new ArrayList<String>();
/** maybe folding */
public String title;
/** binary bytes of pic. */
public byte[] photoBytes;
- /** mime_type col of images table */
+ /** The type of Photo (e.g. JPEG, BMP, etc.) */
public String photoType;
/** Only for GET. Use addPhoneList() to PUT. */
public List<PhoneData> phoneList;
/** Only for GET. Use addContactmethodList() to PUT. */
public List<ContactMethod> contactmethodList;
+ /** Only for GET. Use addOrgList() to PUT. */
+ public List<OrganizationData> organizationList;
+ /** Only for GET. Use addExtension() to PUT */
+ public Map<String, List<String>> extensionMap;
- public static class PhoneData{
+ // Use organizationList instead when handling ORG.
+ @Deprecated
+ public String company;
+
+ public static class PhoneData {
+ public int type;
/** maybe folding */
public String data;
- public String type;
public String label;
+ public boolean isPrimary;
}
- public static class ContactMethod{
- public String kind;
- public String type;
+ public static class ContactMethod {
+ // Contacts.KIND_EMAIL, Contacts.KIND_POSTAL
+ public int kind;
+ // e.g. Contacts.ContactMethods.TYPE_HOME, Contacts.PhoneColumns.TYPE_HOME
+ // If type == Contacts.PhoneColumns.TYPE_CUSTOM, label is used.
+ public int type;
public String data;
+ // Used only when TYPE is TYPE_CUSTOM.
public String label;
+ public boolean isPrimary;
+ }
+
+ public static class OrganizationData {
+ public int type;
+ public String companyName;
+ public String positionName;
+ public boolean isPrimary;
}
/**
@@ -63,29 +121,837 @@
* @param type type col of content://contacts/phones
* @param label lable col of content://contacts/phones
*/
- public void addPhone(String data, String type, String label){
- if(phoneList == null)
+ public void addPhone(int type, String data, String label, boolean isPrimary){
+ if (phoneList == null) {
phoneList = new ArrayList<PhoneData>();
- PhoneData st = new PhoneData();
- st.data = data;
- st.type = type;
- st.label = label;
- phoneList.add(st);
+ }
+ PhoneData phoneData = new PhoneData();
+ phoneData.type = type;
+
+ StringBuilder builder = new StringBuilder();
+ String trimed = data.trim();
+ int length = trimed.length();
+ for (int i = 0; i < length; i++) {
+ char ch = trimed.charAt(i);
+ if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {
+ builder.append(ch);
+ }
+ }
+ phoneData.data = PhoneNumberUtils.formatNumber(builder.toString());
+ phoneData.label = label;
+ phoneData.isPrimary = isPrimary;
+ phoneList.add(phoneData);
}
+
/**
* Add a contactmethod info to contactmethodList.
- * @param data contact data
+ * @param kind integer value defined in Contacts.java
+ * (e.g. Contacts.KIND_EMAIL)
* @param type type col of content://contacts/contact_methods
+ * @param data contact data
+ * @param label extra string used only when kind is Contacts.KIND_CUSTOM.
*/
- public void addContactmethod(String kind, String data, String type,
- String label){
- if(contactmethodList == null)
+ public void addContactmethod(int kind, int type, String data,
+ String label, boolean isPrimary){
+ if (contactmethodList == null) {
contactmethodList = new ArrayList<ContactMethod>();
- ContactMethod st = new ContactMethod();
- st.kind = kind;
- st.data = data;
- st.type = type;
- st.label = label;
- contactmethodList.add(st);
+ }
+ ContactMethod contactMethod = new ContactMethod();
+ contactMethod.kind = kind;
+ contactMethod.type = type;
+ contactMethod.data = data;
+ contactMethod.label = label;
+ contactMethod.isPrimary = isPrimary;
+ contactmethodList.add(contactMethod);
+ }
+
+ /**
+ * Add a Organization info to organizationList.
+ */
+ public void addOrganization(int type, String companyName, String positionName,
+ boolean isPrimary) {
+ if (organizationList == null) {
+ organizationList = new ArrayList<OrganizationData>();
+ }
+ OrganizationData organizationData = new OrganizationData();
+ organizationData.type = type;
+ organizationData.companyName = companyName;
+ organizationData.positionName = positionName;
+ organizationData.isPrimary = isPrimary;
+ organizationList.add(organizationData);
+ }
+
+ public void addExtension(PropertyNode propertyNode) {
+ if (propertyNode.propValue.length() == 0) {
+ return;
+ }
+ // Now store the string into extensionMap.
+ List<String> list;
+ String name = propertyNode.propName;
+ if (extensionMap == null) {
+ extensionMap = new HashMap<String, List<String>>();
+ }
+ if (!extensionMap.containsKey(name)){
+ list = new ArrayList<String>();
+ extensionMap.put(name, list);
+ } else {
+ list = extensionMap.get(name);
+ }
+
+ list.add(propertyNode.encode());
+ }
+
+ private static String getNameFromNProperty(List<String> elems, int nameOrderType) {
+ // Family, Given, Middle, Prefix, Suffix. (1 - 5)
+ int size = elems.size();
+ if (size > 1) {
+ StringBuilder builder = new StringBuilder();
+ boolean builderIsEmpty = true;
+ // Prefix
+ if (size > 3 && elems.get(3).length() > 0) {
+ builder.append(elems.get(3));
+ builderIsEmpty = false;
+ }
+ String first, second;
+ if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {
+ first = elems.get(0);
+ second = elems.get(1);
+ } else {
+ first = elems.get(1);
+ second = elems.get(0);
+ }
+ if (first.length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(first);
+ builderIsEmpty = false;
+ }
+ // Middle name
+ if (size > 2 && elems.get(2).length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(elems.get(2));
+ builderIsEmpty = false;
+ }
+ if (second.length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(second);
+ builderIsEmpty = false;
+ }
+ // Suffix
+ if (size > 4 && elems.get(4).length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(elems.get(4));
+ builderIsEmpty = false;
+ }
+ return builder.toString();
+ } else if (size == 1) {
+ return elems.get(0);
+ } else {
+ return "";
+ }
+ }
+
+ public static ContactStruct constructContactFromVNode(VNode node,
+ int nameOrderType) {
+ if (!node.VName.equals("VCARD")) {
+ // Impossible in current implementation. Just for safety.
+ Log.e(LOG_TAG, "Non VCARD data is inserted.");
+ return null;
+ }
+
+ // For name, there are three fields in vCard: FN, N, NAME.
+ // We prefer FN, which is a required field in vCard 3.0 , but not in vCard 2.1.
+ // Next, we prefer NAME, which is defined only in vCard 3.0.
+ // Finally, we use N, which is a little difficult to parse.
+ String fullName = null;
+ String nameFromNProperty = null;
+
+ // Some vCard has "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", and
+ // "X-PHONETIC-LAST-NAME"
+ String xPhoneticFirstName = null;
+ String xPhoneticMiddleName = null;
+ String xPhoneticLastName = null;
+
+ ContactStruct contact = new ContactStruct();
+
+ // Each Column of four properties has ISPRIMARY field
+ // (See android.provider.Contacts)
+ // If false even after the following loop, we choose the first
+ // entry as a "primary" entry.
+ boolean prefIsSetAddress = false;
+ boolean prefIsSetPhone = false;
+ boolean prefIsSetEmail = false;
+ boolean prefIsSetOrganization = false;
+
+ for (PropertyNode propertyNode: node.propList) {
+ String name = propertyNode.propName;
+
+ if (TextUtils.isEmpty(propertyNode.propValue)) {
+ continue;
+ }
+
+ if (name.equals("VERSION")) {
+ // vCard version. Ignore this.
+ } else if (name.equals("FN")) {
+ fullName = propertyNode.propValue;
+ } else if (name.equals("NAME") && fullName == null) {
+ // Only in vCard 3.0. Use this if FN does not exist.
+ // Though, note that vCard 3.0 requires FN.
+ fullName = propertyNode.propValue;
+ } else if (name.equals("N")) {
+ nameFromNProperty = getNameFromNProperty(propertyNode.propValue_vector,
+ nameOrderType);
+ } else if (name.equals("SORT-STRING")) {
+ contact.phoneticName = propertyNode.propValue;
+ } else if (name.equals("SOUND")) {
+ if (propertyNode.paramMap_TYPE.contains("X-IRMC-N") &&
+ contact.phoneticName == null) {
+ // Some Japanese mobile phones use this field for phonetic name,
+ // since vCard 2.1 does not have "SORT-STRING" type.
+ // Also, in some cases, the field has some ';' in it.
+ // We remove them.
+ StringBuilder builder = new StringBuilder();
+ String value = propertyNode.propValue;
+ int length = value.length();
+ for (int i = 0; i < length; i++) {
+ char ch = value.charAt(i);
+ if (ch != ';') {
+ builder.append(ch);
+ }
+ }
+ contact.phoneticName = builder.toString();
+ } else {
+ contact.addExtension(propertyNode);
+ }
+ } else if (name.equals("ADR")) {
+ List<String> values = propertyNode.propValue_vector;
+ boolean valuesAreAllEmpty = true;
+ for (String value : values) {
+ if (value.length() > 0) {
+ valuesAreAllEmpty = false;
+ break;
+ }
+ }
+ if (valuesAreAllEmpty) {
+ continue;
+ }
+
+ int kind = Contacts.KIND_POSTAL;
+ int type = -1;
+ String label = "";
+ boolean isPrimary = false;
+ for (String typeString : propertyNode.paramMap_TYPE) {
+ if (typeString.equals("PREF") && !prefIsSetAddress) {
+ // Only first "PREF" is considered.
+ prefIsSetAddress = true;
+ isPrimary = true;
+ } else if (typeString.equalsIgnoreCase("HOME")) {
+ type = Contacts.ContactMethodsColumns.TYPE_HOME;
+ label = "";
+ } else if (typeString.equalsIgnoreCase("WORK") ||
+ typeString.equalsIgnoreCase("COMPANY")) {
+ // "COMPANY" seems emitted by Windows Mobile, which is not
+ // specifically supported by vCard 2.1. We assume this is same
+ // as "WORK".
+ type = Contacts.ContactMethodsColumns.TYPE_WORK;
+ label = "";
+ } else if (typeString.equalsIgnoreCase("POSTAL")) {
+ kind = Contacts.KIND_POSTAL;
+ } else if (typeString.equalsIgnoreCase("PARCEL") ||
+ typeString.equalsIgnoreCase("DOM") ||
+ typeString.equalsIgnoreCase("INTL")) {
+ // We do not have a kind or type matching these.
+ // TODO: fix this. We may need to split entries into two.
+ // (e.g. entries for KIND_POSTAL and KIND_PERCEL)
+ } else if (typeString.toUpperCase().startsWith("X-") &&
+ type < 0) {
+ type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;
+ label = typeString.substring(2);
+ } else if (type < 0) {
+ // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters
+ // emit non-standard types. We do not handle their values now.
+ type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;
+ label = typeString;
+ }
+ }
+ // We use "HOME" as default
+ if (type < 0) {
+ type = Contacts.ContactMethodsColumns.TYPE_HOME;
+ }
+
+ // adr-value = 0*6(text-value ";") text-value
+ // ; PO Box, Extended Address, Street, Locality, Region, Postal
+ // ; Code, Country Name
+ String address;
+ List<String> list = propertyNode.propValue_vector;
+ int size = list.size();
+ if (size > 1) {
+ StringBuilder builder = new StringBuilder();
+ boolean builderIsEmpty = true;
+ if (Locale.getDefault().getCountry().equals(Locale.JAPAN.getCountry())) {
+ // In Japan, the order is reversed.
+ for (int i = size - 1; i >= 0; i--) {
+ String addressPart = list.get(i);
+ if (addressPart.length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(addressPart);
+ builderIsEmpty = false;
+ }
+ }
+ } else {
+ for (int i = 0; i < size; i++) {
+ String addressPart = list.get(i);
+ if (addressPart.length() > 0) {
+ if (!builderIsEmpty) {
+ builder.append(' ');
+ }
+ builder.append(addressPart);
+ builderIsEmpty = false;
+ }
+ }
+ }
+ address = builder.toString().trim();
+ } else {
+ address = propertyNode.propValue;
+ }
+ contact.addContactmethod(kind, type, address, label, isPrimary);
+ } else if (name.equals("ORG")) {
+ // vCard specification does not specify other types.
+ int type = Contacts.OrganizationColumns.TYPE_WORK;
+ String companyName = "";
+ String positionName = "";
+ boolean isPrimary = false;
+
+ for (String typeString : propertyNode.paramMap_TYPE) {
+ if (typeString.equals("PREF") && !prefIsSetOrganization) {
+ // vCard specification officially does not have PREF in ORG.
+ // This is just for safety.
+ prefIsSetOrganization = true;
+ isPrimary = true;
+ }
+ // XXX: Should we cope with X- words?
+ }
+
+ List<String> list = propertyNode.propValue_vector;
+ int size = list.size();
+ if (size > 1) {
+ companyName = list.get(0);
+ StringBuilder builder = new StringBuilder();
+ for (int i = 1; i < size; i++) {
+ builder.append(list.get(1));
+ if (i != size - 1) {
+ builder.append(", ");
+ }
+ }
+ positionName = builder.toString();
+ } else if (size == 1) {
+ companyName = propertyNode.propValue;
+ positionName = "";
+ }
+ contact.addOrganization(type, companyName, positionName, isPrimary);
+ } else if (name.equals("TITLE")) {
+ contact.title = propertyNode.propValue;
+ // XXX: What to do this? Isn't ORG enough?
+ contact.addExtension(propertyNode);
+ } else if (name.equals("ROLE")) {
+ // XXX: What to do this? Isn't ORG enough?
+ contact.addExtension(propertyNode);
+ } else if (name.equals("PHOTO")) {
+ // We prefer PHOTO to LOGO.
+ String valueType = propertyNode.paramMap.getAsString("VALUE");
+ if (valueType != null && valueType.equals("URL")) {
+ // TODO: do something.
+ } else {
+ // Assume PHOTO is stored in BASE64. In that case,
+ // data is already stored in propValue_bytes in binary form.
+ // It should be automatically done by VBuilder (VDataBuilder/VCardDatabuilder)
+ contact.photoBytes = propertyNode.propValue_bytes;
+ String type = propertyNode.paramMap.getAsString("TYPE");
+ if (type != null) {
+ contact.photoType = type;
+ }
+ }
+ } else if (name.equals("LOGO")) {
+ // When PHOTO is not available this is not URL,
+ // we use this instead of PHOTO.
+ String valueType = propertyNode.paramMap.getAsString("VALUE");
+ if (valueType != null && valueType.equals("URL")) {
+ // TODO: do something.
+ } else if (contact.photoBytes == null) {
+ contact.photoBytes = propertyNode.propValue_bytes;
+ String type = propertyNode.paramMap.getAsString("TYPE");
+ if (type != null) {
+ contact.photoType = type;
+ }
+ }
+ } else if (name.equals("EMAIL")) {
+ int type = -1;
+ String label = null;
+ boolean isPrimary = false;
+ for (String typeString : propertyNode.paramMap_TYPE) {
+ if (typeString.equals("PREF") && !prefIsSetEmail) {
+ // Only first "PREF" is considered.
+ prefIsSetEmail = true;
+ isPrimary = true;
+ } else if (typeString.equalsIgnoreCase("HOME")) {
+ type = Contacts.ContactMethodsColumns.TYPE_HOME;
+ } else if (typeString.equalsIgnoreCase("WORK")) {
+ type = Contacts.ContactMethodsColumns.TYPE_WORK;
+ } else if (typeString.equalsIgnoreCase("CELL")) {
+ // We do not have Contacts.ContactMethodsColumns.TYPE_MOBILE yet.
+ type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;
+ label = Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME;
+ } else if (typeString.toUpperCase().startsWith("X-") &&
+ type < 0) {
+ type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;
+ label = typeString.substring(2);
+ } else if (type < 0) {
+ // vCard 3.0 allows iana-token.
+ // We may have INTERNET (specified in vCard spec),
+ // SCHOOL, etc.
+ type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;
+ label = typeString;
+ }
+ }
+ // We use "OTHER" as default.
+ if (type < 0) {
+ type = Contacts.ContactMethodsColumns.TYPE_OTHER;
+ }
+ contact.addContactmethod(Contacts.KIND_EMAIL,
+ type, propertyNode.propValue,label, isPrimary);
+ } else if (name.equals("TEL")) {
+ int type = -1;
+ String label = null;
+ boolean isPrimary = false;
+ boolean isFax = false;
+ for (String typeString : propertyNode.paramMap_TYPE) {
+ if (typeString.equals("PREF") && !prefIsSetPhone) {
+ // Only first "PREF" is considered.
+ prefIsSetPhone = true;
+ isPrimary = true;
+ } else if (typeString.equalsIgnoreCase("HOME")) {
+ type = Contacts.PhonesColumns.TYPE_HOME;
+ } else if (typeString.equalsIgnoreCase("WORK")) {
+ type = Contacts.PhonesColumns.TYPE_WORK;
+ } else if (typeString.equalsIgnoreCase("CELL")) {
+ type = Contacts.PhonesColumns.TYPE_MOBILE;
+ } else if (typeString.equalsIgnoreCase("PAGER")) {
+ type = Contacts.PhonesColumns.TYPE_PAGER;
+ } else if (typeString.equalsIgnoreCase("FAX")) {
+ isFax = true;
+ } else if (typeString.equalsIgnoreCase("VOICE") ||
+ typeString.equalsIgnoreCase("MSG")) {
+ // Defined in vCard 3.0. Ignore these because they
+ // conflict with "HOME", "WORK", etc.
+ // XXX: do something?
+ } else if (typeString.toUpperCase().startsWith("X-") &&
+ type < 0) {
+ type = Contacts.PhonesColumns.TYPE_CUSTOM;
+ label = typeString.substring(2);
+ } else if (type < 0){
+ // We may have MODEM, CAR, ISDN, etc...
+ type = Contacts.PhonesColumns.TYPE_CUSTOM;
+ label = typeString;
+ }
+ }
+ // We use "HOME" as default
+ if (type < 0) {
+ type = Contacts.PhonesColumns.TYPE_HOME;
+ }
+ if (isFax) {
+ if (type == Contacts.PhonesColumns.TYPE_HOME) {
+ type = Contacts.PhonesColumns.TYPE_FAX_HOME;
+ } else if (type == Contacts.PhonesColumns.TYPE_WORK) {
+ type = Contacts.PhonesColumns.TYPE_FAX_WORK;
+ }
+ }
+
+ contact.addPhone(type, propertyNode.propValue, label, isPrimary);
+ } else if (name.equals("NOTE")) {
+ contact.notes.add(propertyNode.propValue);
+ } else if (name.equals("BDAY")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("URL")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("REV")) {
+ // Revision of this VCard entry. I think we can ignore this.
+ contact.addExtension(propertyNode);
+ } else if (name.equals("UID")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("KEY")) {
+ // Type is X509 or PGP? I don't know how to handle this...
+ contact.addExtension(propertyNode);
+ } else if (name.equals("MAILER")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("TZ")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("GEO")) {
+ contact.addExtension(propertyNode);
+ } else if (name.equals("NICKNAME")) {
+ // vCard 3.0 only.
+ contact.addExtension(propertyNode);
+ } else if (name.equals("CLASS")) {
+ // vCard 3.0 only.
+ // e.g. CLASS:CONFIDENTIAL
+ contact.addExtension(propertyNode);
+ } else if (name.equals("PROFILE")) {
+ // VCard 3.0 only. Must be "VCARD". I think we can ignore this.
+ contact.addExtension(propertyNode);
+ } else if (name.equals("CATEGORIES")) {
+ // VCard 3.0 only.
+ // e.g. CATEGORIES:INTERNET,IETF,INDUSTRY,INFORMATION TECHNOLOGY
+ contact.addExtension(propertyNode);
+ } else if (name.equals("SOURCE")) {
+ // VCard 3.0 only.
+ contact.addExtension(propertyNode);
+ } else if (name.equals("PRODID")) {
+ // VCard 3.0 only.
+ // To specify the identifier for the product that created
+ // the vCard object.
+ contact.addExtension(propertyNode);
+ } else if (name.equals("X-PHONETIC-FIRST-NAME")) {
+ xPhoneticFirstName = propertyNode.propValue;
+ } else if (name.equals("X-PHONETIC-MIDDLE-NAME")) {
+ xPhoneticMiddleName = propertyNode.propValue;
+ } else if (name.equals("X-PHONETIC-LAST-NAME")) {
+ xPhoneticLastName = propertyNode.propValue;
+ } else {
+ // Unknown X- words and IANA token.
+ contact.addExtension(propertyNode);
+ }
+ }
+
+ if (fullName != null) {
+ contact.name = fullName;
+ } else if(nameFromNProperty != null) {
+ contact.name = nameFromNProperty;
+ } else {
+ contact.name = "";
+ }
+
+ if (contact.phoneticName == null &&
+ (xPhoneticFirstName != null || xPhoneticMiddleName != null ||
+ xPhoneticLastName != null)) {
+ // Note: In Europe, this order should be "LAST FIRST MIDDLE". See the comment around
+ // NAME_ORDER_TYPE_* for more detail.
+ String first;
+ String second;
+ if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {
+ first = xPhoneticLastName;
+ second = xPhoneticFirstName;
+ } else {
+ first = xPhoneticFirstName;
+ second = xPhoneticLastName;
+ }
+ StringBuilder builder = new StringBuilder();
+ if (first != null) {
+ builder.append(first);
+ }
+ if (xPhoneticMiddleName != null) {
+ builder.append(xPhoneticMiddleName);
+ }
+ if (second != null) {
+ builder.append(second);
+ }
+ contact.phoneticName = builder.toString();
+ }
+
+ // Remove unnecessary white spaces.
+ // It is found that some mobile phone emits phonetic name with just one white space
+ // when a user does not specify one.
+ // This logic is effective toward such kind of weird data.
+ if (contact.phoneticName != null) {
+ contact.phoneticName = contact.phoneticName.trim();
+ }
+
+ // If there is no "PREF", we choose the first entries as primary.
+ if (!prefIsSetPhone &&
+ contact.phoneList != null &&
+ contact.phoneList.size() > 0) {
+ contact.phoneList.get(0).isPrimary = true;
+ }
+
+ if (!prefIsSetAddress && contact.contactmethodList != null) {
+ for (ContactMethod contactMethod : contact.contactmethodList) {
+ if (contactMethod.kind == Contacts.KIND_POSTAL) {
+ contactMethod.isPrimary = true;
+ break;
+ }
+ }
+ }
+ if (!prefIsSetEmail && contact.contactmethodList != null) {
+ for (ContactMethod contactMethod : contact.contactmethodList) {
+ if (contactMethod.kind == Contacts.KIND_EMAIL) {
+ contactMethod.isPrimary = true;
+ break;
+ }
+ }
+ }
+ if (!prefIsSetOrganization &&
+ contact.organizationList != null &&
+ contact.organizationList.size() > 0) {
+ contact.organizationList.get(0).isPrimary = true;
+ }
+
+ return contact;
+ }
+
+ public String displayString() {
+ if (name.length() > 0) {
+ return name;
+ }
+ if (contactmethodList != null && contactmethodList.size() > 0) {
+ for (ContactMethod contactMethod : contactmethodList) {
+ if (contactMethod.kind == Contacts.KIND_EMAIL && contactMethod.isPrimary) {
+ return contactMethod.data;
+ }
+ }
+ }
+ if (phoneList != null && phoneList.size() > 0) {
+ for (PhoneData phoneData : phoneList) {
+ if (phoneData.isPrimary) {
+ return phoneData.data;
+ }
+ }
+ }
+ return "";
+ }
+
+ private void pushIntoContentProviderOrResolver(Object contentSomething,
+ long myContactsGroupId) {
+ ContentResolver resolver = null;
+ AbstractSyncableContentProvider provider = null;
+ if (contentSomething instanceof ContentResolver) {
+ resolver = (ContentResolver)contentSomething;
+ } else if (contentSomething instanceof AbstractSyncableContentProvider) {
+ provider = (AbstractSyncableContentProvider)contentSomething;
+ } else {
+ Log.e(LOG_TAG, "Unsupported object came.");
+ return;
+ }
+
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(People.NAME, name);
+ contentValues.put(People.PHONETIC_NAME, phoneticName);
+
+ if (notes.size() > 1) {
+ StringBuilder builder = new StringBuilder();
+ for (String note : notes) {
+ builder.append(note);
+ builder.append("\n");
+ }
+ contentValues.put(People.NOTES, builder.toString());
+ } else if (notes.size() == 1){
+ contentValues.put(People.NOTES, notes.get(0));
+ }
+
+ Uri personUri;
+ long personId = 0;
+ if (resolver != null) {
+ personUri = Contacts.People.createPersonInMyContactsGroup(
+ resolver, contentValues);
+ if (personUri != null) {
+ personId = ContentUris.parseId(personUri);
+ }
+ } else {
+ personUri = provider.insert(People.CONTENT_URI, contentValues);
+ if (personUri != null) {
+ personId = ContentUris.parseId(personUri);
+ ContentValues values = new ContentValues();
+ values.put(GroupMembership.PERSON_ID, personId);
+ values.put(GroupMembership.GROUP_ID, myContactsGroupId);
+ Uri resultUri = provider.insert(GroupMembership.CONTENT_URI, values);
+ if (resultUri == null) {
+ Log.e(LOG_TAG, "Faild to insert the person to MyContact.");
+ provider.delete(personUri, null, null);
+ personUri = null;
+ }
+ }
+ }
+
+ if (personUri == null) {
+ Log.e(LOG_TAG, "Failed to create the contact.");
+ return;
+ }
+
+ if (photoBytes != null) {
+ if (resolver != null) {
+ People.setPhotoData(resolver, personUri, photoBytes);
+ } else {
+ Uri photoUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY);
+ ContentValues values = new ContentValues();
+ values.put(Photos.DATA, photoBytes);
+ provider.update(photoUri, values, null, null);
+ }
+ }
+
+ long primaryPhoneId = -1;
+ if (phoneList != null && phoneList.size() > 0) {
+ for (PhoneData phoneData : phoneList) {
+ ContentValues values = new ContentValues();
+ values.put(Contacts.PhonesColumns.TYPE, phoneData.type);
+ if (phoneData.type == Contacts.PhonesColumns.TYPE_CUSTOM) {
+ values.put(Contacts.PhonesColumns.LABEL, phoneData.label);
+ }
+ // Already formatted.
+ values.put(Contacts.PhonesColumns.NUMBER, phoneData.data);
+
+ // Not sure about Contacts.PhonesColumns.NUMBER_KEY ...
+ values.put(Contacts.PhonesColumns.ISPRIMARY, 1);
+ values.put(Contacts.Phones.PERSON_ID, personId);
+ Uri phoneUri;
+ if (resolver != null) {
+ phoneUri = resolver.insert(Phones.CONTENT_URI, values);
+ } else {
+ phoneUri = provider.insert(Phones.CONTENT_URI, values);
+ }
+ if (phoneData.isPrimary) {
+ primaryPhoneId = Long.parseLong(phoneUri.getLastPathSegment());
+ }
+ }
+ }
+
+ long primaryOrganizationId = -1;
+ if (organizationList != null && organizationList.size() > 0) {
+ for (OrganizationData organizationData : organizationList) {
+ ContentValues values = new ContentValues();
+ // Currently, we do not use TYPE_CUSTOM.
+ values.put(Contacts.OrganizationColumns.TYPE,
+ organizationData.type);
+ values.put(Contacts.OrganizationColumns.COMPANY,
+ organizationData.companyName);
+ values.put(Contacts.OrganizationColumns.TITLE,
+ organizationData.positionName);
+ values.put(Contacts.OrganizationColumns.ISPRIMARY, 1);
+ values.put(Contacts.OrganizationColumns.PERSON_ID, personId);
+
+ Uri organizationUri;
+ if (resolver != null) {
+ organizationUri = resolver.insert(Organizations.CONTENT_URI, values);
+ } else {
+ organizationUri = provider.insert(Organizations.CONTENT_URI, values);
+ }
+ if (organizationData.isPrimary) {
+ primaryOrganizationId = Long.parseLong(organizationUri.getLastPathSegment());
+ }
+ }
+ }
+
+ long primaryEmailId = -1;
+ if (contactmethodList != null && contactmethodList.size() > 0) {
+ for (ContactMethod contactMethod : contactmethodList) {
+ ContentValues values = new ContentValues();
+ values.put(Contacts.ContactMethodsColumns.KIND, contactMethod.kind);
+ values.put(Contacts.ContactMethodsColumns.TYPE, contactMethod.type);
+ if (contactMethod.type == Contacts.ContactMethodsColumns.TYPE_CUSTOM) {
+ values.put(Contacts.ContactMethodsColumns.LABEL, contactMethod.label);
+ }
+ values.put(Contacts.ContactMethodsColumns.DATA, contactMethod.data);
+ values.put(Contacts.ContactMethodsColumns.ISPRIMARY, 1);
+ values.put(Contacts.ContactMethods.PERSON_ID, personId);
+
+ if (contactMethod.kind == Contacts.KIND_EMAIL) {
+ Uri emailUri;
+ if (resolver != null) {
+ emailUri = resolver.insert(ContactMethods.CONTENT_URI, values);
+ } else {
+ emailUri = provider.insert(ContactMethods.CONTENT_URI, values);
+ }
+ if (contactMethod.isPrimary) {
+ primaryEmailId = Long.parseLong(emailUri.getLastPathSegment());
+ }
+ } else { // probably KIND_POSTAL
+ if (resolver != null) {
+ resolver.insert(ContactMethods.CONTENT_URI, values);
+ } else {
+ provider.insert(ContactMethods.CONTENT_URI, values);
+ }
+ }
+ }
+ }
+
+ if (extensionMap != null && extensionMap.size() > 0) {
+ ArrayList<ContentValues> contentValuesArray;
+ if (resolver != null) {
+ contentValuesArray = new ArrayList<ContentValues>();
+ } else {
+ contentValuesArray = null;
+ }
+ for (Entry<String, List<String>> entry : extensionMap.entrySet()) {
+ String key = entry.getKey();
+ List<String> list = entry.getValue();
+ for (String value : list) {
+ ContentValues values = new ContentValues();
+ values.put(Extensions.NAME, key);
+ values.put(Extensions.VALUE, value);
+ values.put(Extensions.PERSON_ID, personId);
+ if (resolver != null) {
+ contentValuesArray.add(values);
+ } else {
+ provider.insert(Extensions.CONTENT_URI, values);
+ }
+ }
+ }
+ if (resolver != null) {
+ resolver.bulkInsert(Extensions.CONTENT_URI,
+ contentValuesArray.toArray(new ContentValues[0]));
+ }
+ }
+
+ if (primaryPhoneId >= 0 || primaryOrganizationId >= 0 || primaryEmailId >= 0) {
+ ContentValues values = new ContentValues();
+ if (primaryPhoneId >= 0) {
+ values.put(People.PRIMARY_PHONE_ID, primaryPhoneId);
+ }
+ if (primaryOrganizationId >= 0) {
+ values.put(People.PRIMARY_ORGANIZATION_ID, primaryOrganizationId);
+ }
+ if (primaryEmailId >= 0) {
+ values.put(People.PRIMARY_EMAIL_ID, primaryEmailId);
+ }
+ if (resolver != null) {
+ resolver.update(personUri, values, null, null);
+ } else {
+ provider.update(personUri, values, null, null);
+ }
+ }
+ }
+
+ /**
+ * Push this object into database in the resolver.
+ */
+ public void pushIntoContentResolver(ContentResolver resolver) {
+ pushIntoContentProviderOrResolver(resolver, 0);
+ }
+
+ /**
+ * Push this object into AbstractSyncableContentProvider object.
+ */
+ public void pushIntoAbstractSyncableContentProvider(
+ AbstractSyncableContentProvider provider, long myContactsGroupId) {
+ boolean successful = false;
+ provider.beginBatch();
+ try {
+ pushIntoContentProviderOrResolver(provider, myContactsGroupId);
+ successful = true;
+ } finally {
+ provider.endBatch(successful);
+ }
+ }
+
+ public boolean isIgnorable() {
+ return TextUtils.isEmpty(name) &&
+ TextUtils.isEmpty(phoneticName) &&
+ (phoneList == null || phoneList.size() == 0) &&
+ (contactmethodList == null || contactmethodList.size() == 0);
}
}
diff --git a/core/java/android/syncml/pim/vcard/VCardComposer.java b/core/java/android/syncml/pim/vcard/VCardComposer.java
index 05e8f40..192736a 100644
--- a/core/java/android/syncml/pim/vcard/VCardComposer.java
+++ b/core/java/android/syncml/pim/vcard/VCardComposer.java
@@ -124,9 +124,9 @@
mResult.append("ORG:").append(struct.company).append(mNewline);
}
- if (!isNull(struct.notes)) {
+ if (struct.notes.size() > 0 && !isNull(struct.notes.get(0))) {
mResult.append("NOTE:").append(
- foldingString(struct.notes, vcardversion)).append(mNewline);
+ foldingString(struct.notes.get(0), vcardversion)).append(mNewline);
}
if (!isNull(struct.title)) {
@@ -190,7 +190,7 @@
*/
private void appendPhotoStr(byte[] bytes, String type, int version)
throws VCardException {
- String value, apptype, encodingStr;
+ String value, encodingStr;
try {
value = foldingString(new String(Base64.encodeBase64(bytes, true)),
version);
@@ -198,20 +198,23 @@
throw new VCardException(e.getMessage());
}
- if (isNull(type)) {
- type = "image/jpeg";
- }
- if (type.indexOf("jpeg") > 0) {
- apptype = "JPEG";
- } else if (type.indexOf("gif") > 0) {
- apptype = "GIF";
- } else if (type.indexOf("bmp") > 0) {
- apptype = "BMP";
+ if (isNull(type) || type.toUpperCase().indexOf("JPEG") >= 0) {
+ type = "JPEG";
+ } else if (type.toUpperCase().indexOf("GIF") >= 0) {
+ type = "GIF";
+ } else if (type.toUpperCase().indexOf("BMP") >= 0) {
+ type = "BMP";
} else {
- apptype = type.substring(type.indexOf("/")).toUpperCase();
+ // Handle the string like "image/tiff".
+ int indexOfSlash = type.indexOf("/");
+ if (indexOfSlash >= 0) {
+ type = type.substring(indexOfSlash + 1).toUpperCase();
+ } else {
+ type = type.toUpperCase();
+ }
}
- mResult.append("LOGO;TYPE=").append(apptype);
+ mResult.append("LOGO;TYPE=").append(type);
if (version == VERSION_VCARD21_INT) {
encodingStr = ";ENCODING=BASE64:";
value = value + mNewline;
@@ -281,7 +284,7 @@
private String getPhoneTypeStr(PhoneData phone) {
- int phoneType = Integer.parseInt(phone.type);
+ int phoneType = phone.type;
String typeStr, label;
if (phoneTypeMap.containsKey(phoneType)) {
@@ -308,7 +311,7 @@
String joinMark = version == VERSION_VCARD21_INT ? ";" : ",";
for (ContactStruct.ContactMethod contactMethod : contactMList) {
// same with v2.1 and v3.0
- switch (Integer.parseInt(contactMethod.kind)) {
+ switch (contactMethod.kind) {
case Contacts.KIND_EMAIL:
String mailType = "INTERNET";
if (!isNull(contactMethod.data)) {
diff --git a/core/java/android/syncml/pim/vcard/VCardDataBuilder.java b/core/java/android/syncml/pim/vcard/VCardDataBuilder.java
new file mode 100644
index 0000000..a0513f1
--- /dev/null
+++ b/core/java/android/syncml/pim/vcard/VCardDataBuilder.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2007 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 android.syncml.pim.vcard;
+
+import android.app.ProgressDialog;
+import android.content.AbstractSyncableContentProvider;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.IContentProvider;
+import android.os.Handler;
+import android.provider.Contacts;
+import android.syncml.pim.PropertyNode;
+import android.syncml.pim.VBuilder;
+import android.syncml.pim.VNode;
+import android.syncml.pim.VParser;
+import android.util.CharsetUtils;
+import android.util.Log;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.net.QuotedPrintableCodec;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * VBuilder for VCard. VCard may contain big photo images encoded by BASE64,
+ * If we store all VNode entries in memory like VDataBuilder.java,
+ * OutOfMemoryError may be thrown. Thus, this class push each VCard entry into
+ * ContentResolver immediately.
+ */
+public class VCardDataBuilder implements VBuilder {
+ static private String LOG_TAG = "VCardDataBuilder";
+
+ /**
+ * If there's no other information available, this class uses this charset for encoding
+ * byte arrays.
+ */
+ static public String DEFAULT_CHARSET = "UTF-8";
+
+ private class ProgressShower implements Runnable {
+ private ContactStruct mContact;
+
+ public ProgressShower(ContactStruct contact) {
+ mContact = contact;
+ }
+
+ public void run () {
+ mProgressDialog.setMessage(mProgressMessage + "\n" +
+ mContact.displayString());
+ }
+ }
+
+ /** type=VNode */
+ private VNode mCurrentVNode;
+ private PropertyNode mCurrentPropNode;
+ private String mCurrentParamType;
+
+ /**
+ * The charset using which VParser parses the text.
+ */
+ private String mSourceCharset;
+
+ /**
+ * The charset with which byte array is encoded to String.
+ */
+ private String mTargetCharset;
+ private boolean mStrictLineBreakParsing;
+ private ContentResolver mContentResolver;
+
+ // For letting VCardDataBuilder show the display name of VCard while handling it.
+ private Handler mHandler;
+ private ProgressDialog mProgressDialog;
+ private String mProgressMessage;
+ private Runnable mOnProgressRunnable;
+ private boolean mLastNameComesBeforeFirstName;
+
+ // Just for testing.
+ private long mTimeCreateContactStruct;
+ private long mTimePushIntoContentResolver;
+
+ // Ideally, this should be ContactsProvider but it seems Class loader cannot find it,
+ // even when it is subclass of ContactsProvider...
+ private AbstractSyncableContentProvider mProvider;
+ private long mMyContactsGroupId;
+
+ public VCardDataBuilder(ContentResolver resolver) {
+ mTargetCharset = DEFAULT_CHARSET;
+ mContentResolver = resolver;
+ }
+
+ /**
+ * Constructor which requires minimum requiredvariables.
+ *
+ * @param resolver insert each data into this ContentResolver
+ * @param progressDialog
+ * @param progressMessage
+ * @param handler if this importer works on the different thread than main one,
+ * set appropriate handler object. If not, it is ok to set this null.
+ */
+ public VCardDataBuilder(ContentResolver resolver,
+ ProgressDialog progressDialog,
+ String progressMessage,
+ Handler handler) {
+ this(resolver, progressDialog, progressMessage, handler,
+ null, null, false, false);
+ }
+
+ public VCardDataBuilder(ContentResolver resolver,
+ ProgressDialog progressDialog,
+ String progressMessage,
+ Handler handler,
+ String charset,
+ boolean strictLineBreakParsing,
+ boolean lastNameComesBeforeFirstName) {
+ this(resolver, progressDialog, progressMessage, handler,
+ null, charset, strictLineBreakParsing,
+ lastNameComesBeforeFirstName);
+ }
+
+ /**
+ * @hide
+ */
+ public VCardDataBuilder(ContentResolver resolver,
+ ProgressDialog progressDialog,
+ String progressMessage,
+ Handler handler,
+ String sourceCharset,
+ String targetCharset,
+ boolean strictLineBreakParsing,
+ boolean lastNameComesBeforeFirstName) {
+ if (sourceCharset != null) {
+ mSourceCharset = sourceCharset;
+ } else {
+ mSourceCharset = VParser.DEFAULT_CHARSET;
+ }
+ if (targetCharset != null) {
+ mTargetCharset = targetCharset;
+ } else {
+ mTargetCharset = DEFAULT_CHARSET;
+ }
+ mContentResolver = resolver;
+ mStrictLineBreakParsing = strictLineBreakParsing;
+ mHandler = handler;
+ mProgressDialog = progressDialog;
+ mProgressMessage = progressMessage;
+ mLastNameComesBeforeFirstName = lastNameComesBeforeFirstName;
+
+ tryGetOriginalProvider();
+ }
+
+ private void tryGetOriginalProvider() {
+ final ContentResolver resolver = mContentResolver;
+
+ if ((mMyContactsGroupId = Contacts.People.tryGetMyContactsGroupId(resolver)) == 0) {
+ Log.e(LOG_TAG, "Could not get group id of MyContact");
+ return;
+ }
+
+ IContentProvider iProviderForName = resolver.acquireProvider(Contacts.CONTENT_URI);
+ ContentProvider contentProvider =
+ ContentProvider.coerceToLocalContentProvider(iProviderForName);
+ if (contentProvider == null) {
+ Log.e(LOG_TAG, "Fail to get ContentProvider object.");
+ return;
+ }
+
+ if (!(contentProvider instanceof AbstractSyncableContentProvider)) {
+ Log.e(LOG_TAG,
+ "Acquired ContentProvider object is not AbstractSyncableContentProvider.");
+ return;
+ }
+
+ mProvider = (AbstractSyncableContentProvider)contentProvider;
+ }
+
+ public void setOnProgressRunnable(Runnable runnable) {
+ mOnProgressRunnable = runnable;
+ }
+
+ public void start() {
+ }
+
+ public void end() {
+ }
+
+ /**
+ * Assume that VCard is not nested. In other words, this code does not accept
+ */
+ public void startRecord(String type) {
+ if (mCurrentVNode != null) {
+ // This means startRecord() is called inside startRecord() - endRecord() block.
+ // TODO: should throw some Exception
+ Log.e(LOG_TAG, "Nested VCard code is not supported now.");
+ }
+ mCurrentVNode = new VNode();
+ mCurrentVNode.parseStatus = 1;
+ mCurrentVNode.VName = type;
+ }
+
+ public void endRecord() {
+ mCurrentVNode.parseStatus = 0;
+ long start = System.currentTimeMillis();
+ ContactStruct contact = ContactStruct.constructContactFromVNode(mCurrentVNode,
+ mLastNameComesBeforeFirstName ? ContactStruct.NAME_ORDER_TYPE_JAPANESE :
+ ContactStruct.NAME_ORDER_TYPE_ENGLISH);
+ mTimeCreateContactStruct += System.currentTimeMillis() - start;
+ if (!contact.isIgnorable()) {
+ if (mProgressDialog != null && mProgressMessage != null) {
+ if (mHandler != null) {
+ mHandler.post(new ProgressShower(contact));
+ } else {
+ mProgressDialog.setMessage(mProgressMessage + "\n" +
+ contact.displayString());
+ }
+ }
+ start = System.currentTimeMillis();
+ if (mProvider != null) {
+ contact.pushIntoAbstractSyncableContentProvider(
+ mProvider, mMyContactsGroupId);
+ } else {
+ contact.pushIntoContentResolver(mContentResolver);
+ }
+ mTimePushIntoContentResolver += System.currentTimeMillis() - start;
+ }
+ if (mOnProgressRunnable != null) {
+ mOnProgressRunnable.run();
+ }
+ mCurrentVNode = null;
+ }
+
+ public void startProperty() {
+ mCurrentPropNode = new PropertyNode();
+ }
+
+ public void endProperty() {
+ mCurrentVNode.propList.add(mCurrentPropNode);
+ mCurrentPropNode = null;
+ }
+
+ public void propertyName(String name) {
+ mCurrentPropNode.propName = name;
+ }
+
+ public void propertyGroup(String group) {
+ mCurrentPropNode.propGroupSet.add(group);
+ }
+
+ public void propertyParamType(String type) {
+ mCurrentParamType = type;
+ }
+
+ public void propertyParamValue(String value) {
+ if (mCurrentParamType == null ||
+ mCurrentParamType.equalsIgnoreCase("TYPE")) {
+ mCurrentPropNode.paramMap_TYPE.add(value);
+ } else {
+ mCurrentPropNode.paramMap.put(mCurrentParamType, value);
+ }
+
+ mCurrentParamType = null;
+ }
+
+ private String encodeString(String originalString, String targetCharset) {
+ if (mSourceCharset.equalsIgnoreCase(targetCharset)) {
+ return originalString;
+ }
+ Charset charset = Charset.forName(mSourceCharset);
+ ByteBuffer byteBuffer = charset.encode(originalString);
+ // byteBuffer.array() "may" return byte array which is larger than
+ // byteBuffer.remaining(). Here, we keep on the safe side.
+ byte[] bytes = new byte[byteBuffer.remaining()];
+ byteBuffer.get(bytes);
+ try {
+ return new String(bytes, targetCharset);
+ } catch (UnsupportedEncodingException e) {
+ Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
+ return new String(bytes);
+ }
+ }
+
+ private String handleOneValue(String value, String targetCharset, String encoding) {
+ if (encoding != null) {
+ if (encoding.equals("BASE64") || encoding.equals("B")) {
+ mCurrentPropNode.propValue_bytes =
+ Base64.decodeBase64(value.getBytes());
+ return value;
+ } else if (encoding.equals("QUOTED-PRINTABLE")) {
+ // "= " -> " ", "=\t" -> "\t".
+ // Previous code had done this replacement. Keep on the safe side.
+ StringBuilder builder = new StringBuilder();
+ int length = value.length();
+ for (int i = 0; i < length; i++) {
+ char ch = value.charAt(i);
+ if (ch == '=' && i < length - 1) {
+ char nextCh = value.charAt(i + 1);
+ if (nextCh == ' ' || nextCh == '\t') {
+
+ builder.append(nextCh);
+ i++;
+ continue;
+ }
+ }
+ builder.append(ch);
+ }
+ String quotedPrintable = builder.toString();
+
+ String[] lines;
+ if (mStrictLineBreakParsing) {
+ lines = quotedPrintable.split("\r\n");
+ } else {
+ builder = new StringBuilder();
+ length = quotedPrintable.length();
+ ArrayList<String> list = new ArrayList<String>();
+ for (int i = 0; i < length; i++) {
+ char ch = quotedPrintable.charAt(i);
+ if (ch == '\n') {
+ list.add(builder.toString());
+ builder = new StringBuilder();
+ } else if (ch == '\r') {
+ list.add(builder.toString());
+ builder = new StringBuilder();
+ if (i < length - 1) {
+ char nextCh = quotedPrintable.charAt(i + 1);
+ if (nextCh == '\n') {
+ i++;
+ }
+ }
+ } else {
+ builder.append(ch);
+ }
+ }
+ String finalLine = builder.toString();
+ if (finalLine.length() > 0) {
+ list.add(finalLine);
+ }
+ lines = list.toArray(new String[0]);
+ }
+
+ builder = new StringBuilder();
+ for (String line : lines) {
+ if (line.endsWith("=")) {
+ line = line.substring(0, line.length() - 1);
+ }
+ builder.append(line);
+ }
+ byte[] bytes;
+ try {
+ bytes = builder.toString().getBytes(mSourceCharset);
+ } catch (UnsupportedEncodingException e1) {
+ Log.e(LOG_TAG, "Failed to encode: charset=" + mSourceCharset);
+ bytes = builder.toString().getBytes();
+ }
+
+ try {
+ bytes = QuotedPrintableCodec.decodeQuotedPrintable(bytes);
+ } catch (DecoderException e) {
+ Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e);
+ return "";
+ }
+
+ try {
+ return new String(bytes, targetCharset);
+ } catch (UnsupportedEncodingException e) {
+ Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
+ return new String(bytes);
+ }
+ }
+ // Unknown encoding. Fall back to default.
+ }
+ return encodeString(value, targetCharset);
+ }
+
+ public void propertyValues(List<String> values) {
+ if (values == null || values.size() == 0) {
+ mCurrentPropNode.propValue_bytes = null;
+ mCurrentPropNode.propValue_vector.clear();
+ mCurrentPropNode.propValue_vector.add("");
+ mCurrentPropNode.propValue = "";
+ return;
+ }
+
+ ContentValues paramMap = mCurrentPropNode.paramMap;
+
+ String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET"));
+ String encoding = paramMap.getAsString("ENCODING");
+
+ if (targetCharset == null || targetCharset.length() == 0) {
+ targetCharset = mTargetCharset;
+ }
+
+ for (String value : values) {
+ mCurrentPropNode.propValue_vector.add(
+ handleOneValue(value, targetCharset, encoding));
+ }
+
+ mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector);
+ }
+
+ public void showDebugInfo() {
+ Log.d(LOG_TAG, "time for creating ContactStruct: " + mTimeCreateContactStruct + " ms");
+ Log.d(LOG_TAG, "time for insert ContactStruct to database: " +
+ mTimePushIntoContentResolver + " ms");
+ }
+
+ private String listToString(List<String> list){
+ int size = list.size();
+ if (size > 1) {
+ StringBuilder builder = new StringBuilder();
+ int i = 0;
+ for (String type : list) {
+ builder.append(type);
+ if (i < size - 1) {
+ builder.append(";");
+ }
+ }
+ return builder.toString();
+ } else if (size == 1) {
+ return list.get(0);
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/core/java/android/syncml/pim/vcard/VCardEntryCounter.java b/core/java/android/syncml/pim/vcard/VCardEntryCounter.java
new file mode 100644
index 0000000..03cd1d9
--- /dev/null
+++ b/core/java/android/syncml/pim/vcard/VCardEntryCounter.java
@@ -0,0 +1,63 @@
+/*
+ * 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 android.syncml.pim.vcard;
+
+import java.util.List;
+
+import android.syncml.pim.VBuilder;
+
+public class VCardEntryCounter implements VBuilder {
+ private int mCount;
+
+ public int getCount() {
+ return mCount;
+ }
+
+ public void start() {
+ }
+
+ public void end() {
+ }
+
+ public void startRecord(String type) {
+ }
+
+ public void endRecord() {
+ mCount++;
+ }
+
+ public void startProperty() {
+ }
+
+ public void endProperty() {
+ }
+
+ public void propertyGroup(String group) {
+ }
+
+ public void propertyName(String name) {
+ }
+
+ public void propertyParamType(String type) {
+ }
+
+ public void propertyParamValue(String value) {
+ }
+
+ public void propertyValues(List<String> values) {
+ }
+}
\ No newline at end of file
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/core/java/android/syncml/pim/vcard/VCardNestedException.java
old mode 100755
new mode 100644
similarity index 61%
copy from tests/sketch/src/com/android/gesture/GestureListener.java
copy to core/java/android/syncml/pim/vcard/VCardNestedException.java
index ebb4149..def6f3b7
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/core/java/android/syncml/pim/vcard/VCardNestedException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * 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.
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.gesture;
+package android.syncml.pim.vcard;
-import android.view.MotionEvent;
-
-public interface GestureListener {
- public void onStartGesture(GesturePad pad, MotionEvent event);
- public void onGesture(GesturePad pad, MotionEvent event);
- public void onFinishGesture(GesturePad pad, MotionEvent event);
+/**
+ * VCardException thrown when VCard is nested without VCardParser's being notified.
+ */
+public class VCardNestedException extends VCardException {
+ public VCardNestedException() {}
+ public VCardNestedException(String message) {
+ super(message);
+ }
}
diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V21.java b/core/java/android/syncml/pim/vcard/VCardParser_V21.java
index f853c5e..d865668 100644
--- a/core/java/android/syncml/pim/vcard/VCardParser_V21.java
+++ b/core/java/android/syncml/pim/vcard/VCardParser_V21.java
@@ -17,21 +17,26 @@
package android.syncml.pim.vcard;
import android.syncml.pim.VBuilder;
+import android.syncml.pim.VParser;
+import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.regex.Pattern;
/**
- * This class is used to parse vcard. Please refer to vCard Specification 2.1
+ * This class is used to parse vcard. Please refer to vCard Specification 2.1.
*/
public class VCardParser_V21 {
-
+ private static final String LOG_TAG = "VCardParser_V21";
+
+ public static final String DEFAULT_CHARSET = VParser.DEFAULT_CHARSET;
+
/** Store the known-type */
private static final HashSet<String> sKnownTypeSet = new HashSet<String>(
Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK",
@@ -42,19 +47,17 @@
"CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF",
"PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI",
"WAVE", "AIFF", "PCM", "X509", "PGP"));
-
+
/** Store the known-value */
private static final HashSet<String> sKnownValueSet = new HashSet<String>(
Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID"));
- /** Store the property name available in vCard 2.1 */
- // NICKNAME is not supported in vCard 2.1, but some vCard may contain.
+ /** Store the property names available in vCard 2.1 */
private static final HashSet<String> sAvailablePropertyNameV21 =
new HashSet<String>(Arrays.asList(
- "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
+ "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
"VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
- "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER",
- "NICKNAME"));
+ "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER"));
// Though vCard 2.1 specification does not allow "B" encoding, some data may have it.
// We allow it for safety...
@@ -76,6 +79,30 @@
// Should not directly read a line from this. Use getLine() instead.
protected BufferedReader mReader;
+ private boolean mCanceled;
+
+ // In some cases, vCard is nested. Currently, we only consider the most interior vCard data.
+ // See v21_foma_1.vcf in test directory for more information.
+ private int mNestCount;
+
+ // In order to reduce warning message as much as possible, we hold the value which made Logger
+ // emit a warning message.
+ protected HashSet<String> mWarningValueMap = new HashSet<String>();
+
+ // Just for debugging
+ private long mTimeTotal;
+ private long mTimeStartRecord;
+ private long mTimeEndRecord;
+ private long mTimeStartProperty;
+ private long mTimeEndProperty;
+ private long mTimeParseItems;
+ private long mTimeParseItem1;
+ private long mTimeParseItem2;
+ private long mTimeParseItem3;
+ private long mTimeHandlePropertyValue1;
+ private long mTimeHandlePropertyValue2;
+ private long mTimeHandlePropertyValue3;
+
/**
* Create a new VCard parser.
*/
@@ -83,12 +110,35 @@
super();
}
+ public VCardParser_V21(VCardSourceDetector detector) {
+ super();
+ if (detector != null && detector.getType() == VCardSourceDetector.TYPE_FOMA) {
+ mNestCount = 1;
+ }
+ }
+
/**
* Parse the file at the given position
* vcard_file = [wsls] vcard [wsls]
*/
protected void parseVCardFile() throws IOException, VCardException {
- while (parseOneVCard()) {
+ boolean firstReading = true;
+ while (true) {
+ if (mCanceled) {
+ break;
+ }
+ if (!parseOneVCard(firstReading)) {
+ break;
+ }
+ firstReading = false;
+ }
+
+ if (mNestCount > 0) {
+ boolean useCache = true;
+ for (int i = 0; i < mNestCount; i++) {
+ readEndVCard(useCache, true);
+ useCache = false;
+ }
}
}
@@ -100,7 +150,13 @@
* @return true when the propertyName is a valid property name.
*/
protected boolean isValidPropertyName(String propertyName) {
- return sAvailablePropertyNameV21.contains(propertyName.toUpperCase());
+ if (!(sAvailablePropertyNameV21.contains(propertyName.toUpperCase()) ||
+ propertyName.startsWith("X-")) &&
+ !mWarningValueMap.contains(propertyName)) {
+ mWarningValueMap.add(propertyName);
+ Log.w(LOG_TAG, "Property name unsupported by vCard 2.1: " + propertyName);
+ }
+ return true;
}
/**
@@ -129,7 +185,7 @@
line = getLine();
if (line == null) {
throw new VCardException("Reached end of buffer.");
- } else if (line.trim().length() > 0) {
+ } else if (line.trim().length() > 0) {
return line;
}
}
@@ -140,12 +196,37 @@
* items *CRLF
* "END" [ws] ":" [ws] "VCARD"
*/
- private boolean parseOneVCard() throws IOException, VCardException {
- if (!readBeginVCard()) {
+ private boolean parseOneVCard(boolean firstReading) throws IOException, VCardException {
+ boolean allowGarbage = false;
+ if (firstReading) {
+ if (mNestCount > 0) {
+ for (int i = 0; i < mNestCount; i++) {
+ if (!readBeginVCard(allowGarbage)) {
+ return false;
+ }
+ allowGarbage = true;
+ }
+ }
+ }
+
+ if (!readBeginVCard(allowGarbage)) {
return false;
}
+ long start;
+ if (mBuilder != null) {
+ start = System.currentTimeMillis();
+ mBuilder.startRecord("VCARD");
+ mTimeStartRecord += System.currentTimeMillis() - start;
+ }
+ start = System.currentTimeMillis();
parseItems();
- readEndVCard();
+ mTimeParseItems += System.currentTimeMillis() - start;
+ readEndVCard(true, false);
+ if (mBuilder != null) {
+ start = System.currentTimeMillis();
+ mBuilder.endRecord();
+ mTimeEndRecord += System.currentTimeMillis() - start;
+ }
return true;
}
@@ -154,46 +235,102 @@
* @throws IOException
* @throws VCardException
*/
- protected boolean readBeginVCard() throws IOException, VCardException {
+ protected boolean readBeginVCard(boolean allowGarbage)
+ throws IOException, VCardException {
String line;
- while (true) {
- line = getLine();
- if (line == null) {
- return false;
- } else if (line.trim().length() > 0) {
- break;
+ do {
+ while (true) {
+ line = getLine();
+ if (line == null) {
+ return false;
+ } else if (line.trim().length() > 0) {
+ break;
+ }
}
- }
- String[] strArray = line.split(":", 2);
-
- // Though vCard specification does not allow lower cases,
- // some data may have them, so we allow it.
- if (!(strArray.length == 2 &&
- strArray[0].trim().equalsIgnoreCase("BEGIN") &&
- strArray[1].trim().equalsIgnoreCase("VCARD"))) {
- throw new VCardException("BEGIN:VCARD != \"" + line + "\"");
- }
-
- if (mBuilder != null) {
- mBuilder.startRecord("VCARD");
- }
+ String[] strArray = line.split(":", 2);
+ int length = strArray.length;
- return true;
+ // Though vCard 2.1/3.0 specification does not allow lower cases,
+ // some data may have them, so we allow it (Actually, previous code
+ // had explicitly allowed "BEGIN:vCard" though there's no example).
+ //
+ // TODO: ignore non vCard entry (e.g. vcalendar).
+ // XXX: Not sure, but according to VDataBuilder.java, vcalendar
+ // entry
+ // may be nested. Just seeking "END:SOMETHING" may not be enough.
+ // e.g.
+ // BEGIN:VCARD
+ // ... (Valid. Must parse this)
+ // END:VCARD
+ // BEGIN:VSOMETHING
+ // ... (Must ignore this)
+ // BEGIN:VSOMETHING2
+ // ... (Must ignore this)
+ // END:VSOMETHING2
+ // ... (Must ignore this!)
+ // END:VSOMETHING
+ // BEGIN:VCARD
+ // ... (Valid. Must parse this)
+ // END:VCARD
+ // INVALID_STRING (VCardException should be thrown)
+ if (length == 2 &&
+ strArray[0].trim().equalsIgnoreCase("BEGIN") &&
+ strArray[1].trim().equalsIgnoreCase("VCARD")) {
+ return true;
+ } else if (!allowGarbage) {
+ if (mNestCount > 0) {
+ mPreviousLine = line;
+ return false;
+ } else {
+ throw new VCardException(
+ "Expected String \"BEGIN:VCARD\" did not come "
+ + "(Instead, \"" + line + "\" came)");
+ }
+ }
+ } while(allowGarbage);
+
+ throw new VCardException("Reached where must not be reached.");
}
-
- protected void readEndVCard() throws VCardException {
- // Though vCard specification does not allow lower cases,
- // some data may have them, so we allow it.
- String[] strArray = mPreviousLine.split(":", 2);
- if (!(strArray.length == 2 &&
- strArray[0].trim().equalsIgnoreCase("END") &&
- strArray[1].trim().equalsIgnoreCase("VCARD"))) {
- throw new VCardException("END:VCARD != \"" + mPreviousLine + "\"");
- }
-
- if (mBuilder != null) {
- mBuilder.endRecord();
- }
+
+ /**
+ * The arguments useCache and allowGarbase are usually true and false accordingly when
+ * this function is called outside this function itself.
+ *
+ * @param useCache When true, line is obtained from mPreviousline. Otherwise, getLine()
+ * is used.
+ * @param allowGarbage When true, ignore non "END:VCARD" line.
+ * @throws IOException
+ * @throws VCardException
+ */
+ protected void readEndVCard(boolean useCache, boolean allowGarbage)
+ throws IOException, VCardException {
+ String line;
+ do {
+ if (useCache) {
+ // Though vCard specification does not allow lower cases,
+ // some data may have them, so we allow it.
+ line = mPreviousLine;
+ } else {
+ while (true) {
+ line = getLine();
+ if (line == null) {
+ throw new VCardException("Expected END:VCARD was not found.");
+ } else if (line.trim().length() > 0) {
+ break;
+ }
+ }
+ }
+
+ String[] strArray = line.split(":", 2);
+ if (strArray.length == 2 &&
+ strArray[0].trim().equalsIgnoreCase("END") &&
+ strArray[1].trim().equalsIgnoreCase("VCARD")) {
+ return;
+ } else if (!allowGarbage) {
+ throw new VCardException("END:VCARD != \"" + mPreviousLine + "\"");
+ }
+ useCache = false;
+ } while (allowGarbage);
}
/**
@@ -205,32 +342,33 @@
boolean ended = false;
if (mBuilder != null) {
+ long start = System.currentTimeMillis();
mBuilder.startProperty();
+ mTimeStartProperty += System.currentTimeMillis() - start;
}
-
- try {
- ended = parseItem();
- } finally {
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
+ ended = parseItem();
+ if (mBuilder != null && !ended) {
+ long start = System.currentTimeMillis();
+ mBuilder.endProperty();
+ mTimeEndProperty += System.currentTimeMillis() - start;
}
while (!ended) {
// follow VCARD ,it wont reach endProperty
if (mBuilder != null) {
+ long start = System.currentTimeMillis();
mBuilder.startProperty();
+ mTimeStartProperty += System.currentTimeMillis() - start;
}
- try {
- ended = parseItem();
- } finally {
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
+ ended = parseItem();
+ if (mBuilder != null && !ended) {
+ long start = System.currentTimeMillis();
+ mBuilder.endProperty();
+ mTimeEndProperty += System.currentTimeMillis() - start;
}
}
}
-
+
/**
* item = [groups "."] name [params] ":" value CRLF
* / [groups "."] "ADR" [params] ":" addressparts CRLF
@@ -241,50 +379,46 @@
protected boolean parseItem() throws IOException, VCardException {
mEncoding = sDefaultEncoding;
- // params = ";" [ws] paramlist
String line = getNonEmptyLine();
- String[] strArray = line.split(":", 2);
- if (strArray.length < 2) {
- throw new VCardException("Invalid line(\":\" does not exist): " + line);
- }
- String propertyValue = strArray[1];
- String[] groupNameParamsArray = strArray[0].split(";");
- String groupAndName = groupNameParamsArray[0].trim();
- String[] groupNameArray = groupAndName.split("\\.");
- int length = groupNameArray.length;
- String propertyName = groupNameArray[length - 1];
- if (mBuilder != null) {
- mBuilder.propertyName(propertyName);
- for (int i = 0; i < length - 1; i++) {
- mBuilder.propertyGroup(groupNameArray[i]);
- }
- }
- if (propertyName.equalsIgnoreCase("END")) {
- mPreviousLine = line;
+ long start = System.currentTimeMillis();
+
+ String[] propertyNameAndValue = separateLineAndHandleGroup(line);
+ if (propertyNameAndValue == null) {
return true;
}
-
- length = groupNameParamsArray.length;
- for (int i = 1; i < length; i++) {
- handleParams(groupNameParamsArray[i]);
+ if (propertyNameAndValue.length != 2) {
+ throw new VCardException("Invalid line \"" + line + "\"");
}
-
- if (isValidPropertyName(propertyName) ||
- propertyName.startsWith("X-")) {
- if (propertyName.equals("VERSION") &&
+ String propertyName = propertyNameAndValue[0].toUpperCase();
+ String propertyValue = propertyNameAndValue[1];
+
+ mTimeParseItem1 += System.currentTimeMillis() - start;
+
+ if (propertyName.equals("ADR") ||
+ propertyName.equals("ORG") ||
+ propertyName.equals("N")) {
+ start = System.currentTimeMillis();
+ handleMultiplePropertyValue(propertyName, propertyValue);
+ mTimeParseItem3 += System.currentTimeMillis() - start;
+ return false;
+ } else if (propertyName.equals("AGENT")) {
+ handleAgent(propertyValue);
+ return false;
+ } else if (isValidPropertyName(propertyName)) {
+ if (propertyName.equals("BEGIN")) {
+ if (propertyValue.equals("VCARD")) {
+ throw new VCardNestedException("This vCard has nested vCard data in it.");
+ } else {
+ throw new VCardException("Unknown BEGIN type: " + propertyValue);
+ }
+ } else if (propertyName.equals("VERSION") &&
!propertyValue.equals(getVersion())) {
throw new VCardVersionException("Incompatible version: " +
propertyValue + " != " + getVersion());
}
+ start = System.currentTimeMillis();
handlePropertyValue(propertyName, propertyValue);
- return false;
- } else if (propertyName.equals("ADR") ||
- propertyName.equals("ORG") ||
- propertyName.equals("N")) {
- handleMultiplePropertyValue(propertyName, propertyValue);
- return false;
- } else if (propertyName.equals("AGENT")) {
- handleAgent(propertyValue);
+ mTimeParseItem2 += System.currentTimeMillis() - start;
return false;
}
@@ -292,6 +426,87 @@
propertyName + "\"");
}
+ static private final int STATE_GROUP_OR_PROPNAME = 0;
+ static private final int STATE_PARAMS = 1;
+ // vCard 3.1 specification allows double-quoted param-value, while vCard 2.1 does not.
+ // This is just for safety.
+ static private final int STATE_PARAMS_IN_DQUOTE = 2;
+
+ protected String[] separateLineAndHandleGroup(String line) throws VCardException {
+ int length = line.length();
+ int state = STATE_GROUP_OR_PROPNAME;
+ int nameIndex = 0;
+
+ String[] propertyNameAndValue = new String[2];
+
+ for (int i = 0; i < length; i++) {
+ char ch = line.charAt(i);
+ switch (state) {
+ case STATE_GROUP_OR_PROPNAME:
+ if (ch == ':') {
+ String propertyName = line.substring(nameIndex, i);
+ if (propertyName.equalsIgnoreCase("END")) {
+ mPreviousLine = line;
+ return null;
+ }
+ if (mBuilder != null) {
+ mBuilder.propertyName(propertyName);
+ }
+ propertyNameAndValue[0] = propertyName;
+ if (i < length - 1) {
+ propertyNameAndValue[1] = line.substring(i + 1);
+ } else {
+ propertyNameAndValue[1] = "";
+ }
+ return propertyNameAndValue;
+ } else if (ch == '.') {
+ String groupName = line.substring(nameIndex, i);
+ if (mBuilder != null) {
+ mBuilder.propertyGroup(groupName);
+ }
+ nameIndex = i + 1;
+ } else if (ch == ';') {
+ String propertyName = line.substring(nameIndex, i);
+ if (propertyName.equalsIgnoreCase("END")) {
+ mPreviousLine = line;
+ return null;
+ }
+ if (mBuilder != null) {
+ mBuilder.propertyName(propertyName);
+ }
+ propertyNameAndValue[0] = propertyName;
+ nameIndex = i + 1;
+ state = STATE_PARAMS;
+ }
+ break;
+ case STATE_PARAMS:
+ if (ch == '"') {
+ state = STATE_PARAMS_IN_DQUOTE;
+ } else if (ch == ';') {
+ handleParams(line.substring(nameIndex, i));
+ nameIndex = i + 1;
+ } else if (ch == ':') {
+ handleParams(line.substring(nameIndex, i));
+ if (i < length - 1) {
+ propertyNameAndValue[1] = line.substring(i + 1);
+ } else {
+ propertyNameAndValue[1] = "";
+ }
+ return propertyNameAndValue;
+ }
+ break;
+ case STATE_PARAMS_IN_DQUOTE:
+ if (ch == '"') {
+ state = STATE_PARAMS;
+ }
+ break;
+ }
+ }
+
+ throw new VCardException("Invalid line: \"" + line + "\"");
+ }
+
+
/**
* params = ";" [ws] paramlist
* paramlist = paramlist [ws] ";" [ws] param
@@ -330,18 +545,19 @@
}
/**
- * typeval = knowntype / "X-" word
+ * ptypeval = knowntype / "X-" word
*/
- protected void handleType(String ptypeval) throws VCardException {
- if (sKnownTypeSet.contains(ptypeval.toUpperCase()) ||
- ptypeval.startsWith("X-")) {
- if (mBuilder != null) {
- mBuilder.propertyParamType("TYPE");
- mBuilder.propertyParamValue(ptypeval.toUpperCase());
- }
- } else {
- throw new VCardException("Unknown type: \"" + ptypeval + "\"");
- }
+ protected void handleType(String ptypeval) {
+ String upperTypeValue = ptypeval;
+ if (!(sKnownTypeSet.contains(upperTypeValue) || upperTypeValue.startsWith("X-")) &&
+ !mWarningValueMap.contains(ptypeval)) {
+ mWarningValueMap.add(ptypeval);
+ Log.w(LOG_TAG, "Type unsupported by vCard 2.1: " + ptypeval);
+ }
+ if (mBuilder != null) {
+ mBuilder.propertyParamType("TYPE");
+ mBuilder.propertyParamValue(upperTypeValue);
+ }
}
/**
@@ -427,31 +643,48 @@
protected void handlePropertyValue(
String propertyName, String propertyValue) throws
IOException, VCardException {
- if (mEncoding == null || mEncoding.equalsIgnoreCase("7BIT")
- || mEncoding.equalsIgnoreCase("8BIT")
- || mEncoding.toUpperCase().startsWith("X-")) {
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add(maybeUnescapeText(propertyValue));
- mBuilder.propertyValues(v);
- }
- } else if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
+ if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
+ long start = System.currentTimeMillis();
String result = getQuotedPrintable(propertyValue);
if (mBuilder != null) {
ArrayList<String> v = new ArrayList<String>();
v.add(result);
mBuilder.propertyValues(v);
}
+ mTimeHandlePropertyValue2 += System.currentTimeMillis() - start;
} else if (mEncoding.equalsIgnoreCase("BASE64") ||
mEncoding.equalsIgnoreCase("B")) {
- String result = getBase64(propertyValue);
+ long start = System.currentTimeMillis();
+ // It is very rare, but some BASE64 data may be so big that
+ // OutOfMemoryError occurs. To ignore such cases, use try-catch.
+ try {
+ String result = getBase64(propertyValue);
+ if (mBuilder != null) {
+ ArrayList<String> v = new ArrayList<String>();
+ v.add(result);
+ mBuilder.propertyValues(v);
+ }
+ } catch (OutOfMemoryError error) {
+ Log.e(LOG_TAG, "OutOfMemoryError happened during parsing BASE64 data!");
+ if (mBuilder != null) {
+ mBuilder.propertyValues(null);
+ }
+ }
+ mTimeHandlePropertyValue3 += System.currentTimeMillis() - start;
+ } else {
+ if (!(mEncoding == null || mEncoding.equalsIgnoreCase("7BIT")
+ || mEncoding.equalsIgnoreCase("8BIT")
+ || mEncoding.toUpperCase().startsWith("X-"))) {
+ Log.w(LOG_TAG, "The encoding unsupported by vCard spec: \"" + mEncoding + "\".");
+ }
+
+ long start = System.currentTimeMillis();
if (mBuilder != null) {
ArrayList<String> v = new ArrayList<String>();
- v.add(result);
+ v.add(maybeUnescapeText(propertyValue));
mBuilder.propertyValues(v);
- }
- } else {
- throw new VCardException("Unknown encoding: \"" + mEncoding + "\"");
+ }
+ mTimeHandlePropertyValue1 += System.currentTimeMillis() - start;
}
}
@@ -546,57 +779,51 @@
if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
propertyValue = getQuotedPrintable(propertyValue);
}
-
- if (propertyValue.endsWith("\\")) {
- StringBuilder builder = new StringBuilder();
- // builder.append(propertyValue);
- builder.append(propertyValue.substring(0, propertyValue.length() - 1));
- try {
- String line;
- while (true) {
- line = getNonEmptyLine();
- // builder.append("\r\n");
- // builder.append(line);
- if (!line.endsWith("\\")) {
- builder.append(line);
- break;
- } else {
- builder.append(line.substring(0, line.length() - 1));
- }
- }
- } catch (IOException e) {
- throw new VCardException(
- "IOException is throw during reading propertyValue" + e);
- }
- // Now, propertyValue may contain "\r\n"
- propertyValue = builder.toString();
- }
if (mBuilder != null) {
- // In String#replaceAll() and Pattern class, "\\\\" means single slash.
-
- final String IMPOSSIBLE_STRING = "\0";
- // First replace two backslashes with impossible strings.
- propertyValue = propertyValue.replaceAll("\\\\\\\\", IMPOSSIBLE_STRING);
-
- // Now, split propertyValue with ; whose previous char is not back slash.
- Pattern pattern = Pattern.compile("(?<!\\\\);");
// TODO: limit should be set in accordance with propertyName?
- String[] strArray = pattern.split(propertyValue, -1);
- ArrayList<String> arrayList = new ArrayList<String>();
- for (String str : strArray) {
- // Replace impossible strings with original two backslashes
- arrayList.add(
- unescapeText(str.replaceAll(IMPOSSIBLE_STRING, "\\\\\\\\")));
+ StringBuilder builder = new StringBuilder();
+ ArrayList<String> list = new ArrayList<String>();
+ int length = propertyValue.length();
+ for (int i = 0; i < length; i++) {
+ char ch = propertyValue.charAt(i);
+ if (ch == '\\' && i < length - 1) {
+ char nextCh = propertyValue.charAt(i + 1);
+ String unescapedString = maybeUnescape(nextCh);
+ if (unescapedString != null) {
+ builder.append(unescapedString);
+ i++;
+ } else {
+ builder.append(ch);
+ }
+ } else if (ch == ';') {
+ list.add(builder.toString());
+ builder = new StringBuilder();
+ } else {
+ builder.append(ch);
+ }
}
- mBuilder.propertyValues(arrayList);
+ list.add(builder.toString());
+ mBuilder.propertyValues(list);
}
}
/**
* vCard 2.1 specifies AGENT allows one vcard entry. It is not encoded at all.
+ *
+ * item = ...
+ * / [groups "."] "AGENT"
+ * [params] ":" vcard CRLF
+ * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
+ * items *CRLF "END" [ws] ":" [ws] "VCARD"
+ *
*/
- protected void handleAgent(String propertyValue) throws IOException, VCardException {
+ protected void handleAgent(String propertyValue) throws VCardException {
+ throw new VCardException("AGENT Property is not supported.");
+ /* This is insufficient support. Also, AGENT Property is very rare.
+ Ignore it for now.
+ TODO: fix this.
+
String[] strArray = propertyValue.split(":", 2);
if (!(strArray.length == 2 ||
strArray[0].trim().equalsIgnoreCase("BEGIN") &&
@@ -605,6 +832,7 @@
}
parseItems();
readEndVCard();
+ */
}
/**
@@ -615,17 +843,18 @@
}
/**
- * Convert escaped text into unescaped text.
+ * Returns unescaped String if the character should be unescaped. Return null otherwise.
+ * e.g. In vCard 2.1, "\;" should be unescaped into ";" while "\x" should not be.
*/
- protected String unescapeText(String text) {
+ protected String maybeUnescape(char ch) {
// Original vCard 2.1 specification does not allow transformation
// "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous implementation of
// this class allowed them, so keep it as is.
- // In String#replaceAll(), "\\\\" means single slash.
- return text.replaceAll("\\\\;", ";")
- .replaceAll("\\\\:", ":")
- .replaceAll("\\\\,", ",")
- .replaceAll("\\\\\\\\", "\\\\");
+ if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') {
+ return String.valueOf(ch);
+ } else {
+ return null;
+ }
}
/**
@@ -656,12 +885,15 @@
*/
public boolean parse(InputStream is, String charset, VBuilder builder)
throws IOException, VCardException {
+ // TODO: make this count error entries instead of just throwing VCardException.
+
// TODO: If we really need to allow only CRLF as line break,
// we will have to develop our own BufferedReader().
- mReader = new BufferedReader(new InputStreamReader(is, charset));
+ mReader = new CustomBufferedReader(new InputStreamReader(is, charset));
mBuilder = builder;
+ long start = System.currentTimeMillis();
if (mBuilder != null) {
mBuilder.start();
}
@@ -669,9 +901,50 @@
if (mBuilder != null) {
mBuilder.end();
}
+ mTimeTotal += System.currentTimeMillis() - start;
+
return true;
}
+ public boolean parse(InputStream is, VBuilder builder) throws IOException, VCardException {
+ return parse(is, DEFAULT_CHARSET, builder);
+ }
+
+ /**
+ * Cancel parsing.
+ * Actual cancel is done after the end of the current one vcard entry parsing.
+ */
+ public void cancel() {
+ mCanceled = true;
+ }
+
+ /**
+ * It is very, very rare case, but there is a case where
+ * canceled may be already true outside this object.
+ * @hide
+ */
+ public void parse(InputStream is, String charset, VBuilder builder, boolean canceled)
+ throws IOException, VCardException {
+ mCanceled = canceled;
+ parse(is, charset, builder);
+ }
+
+ public void showDebugInfo() {
+ Log.d(LOG_TAG, "total parsing time: " + mTimeTotal + " ms");
+ if (mReader instanceof CustomBufferedReader) {
+ Log.d(LOG_TAG, "total readLine time: " +
+ ((CustomBufferedReader)mReader).getTotalmillisecond() + " ms");
+ }
+ Log.d(LOG_TAG, "mTimeStartRecord: " + mTimeStartRecord + " ms");
+ Log.d(LOG_TAG, "mTimeEndRecord: " + mTimeEndRecord + " ms");
+ Log.d(LOG_TAG, "mTimeParseItem1: " + mTimeParseItem1 + " ms");
+ Log.d(LOG_TAG, "mTimeParseItem2: " + mTimeParseItem2 + " ms");
+ Log.d(LOG_TAG, "mTimeParseItem3: " + mTimeParseItem3 + " ms");
+ Log.d(LOG_TAG, "mTimeHandlePropertyValue1: " + mTimeHandlePropertyValue1 + " ms");
+ Log.d(LOG_TAG, "mTimeHandlePropertyValue2: " + mTimeHandlePropertyValue2 + " ms");
+ Log.d(LOG_TAG, "mTimeHandlePropertyValue3: " + mTimeHandlePropertyValue3 + " ms");
+ }
+
private boolean isLetter(char ch) {
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
return true;
@@ -679,3 +952,24 @@
return false;
}
}
+
+class CustomBufferedReader extends BufferedReader {
+ private long mTime;
+
+ public CustomBufferedReader(Reader in) {
+ super(in);
+ }
+
+ @Override
+ public String readLine() throws IOException {
+ long start = System.currentTimeMillis();
+ String ret = super.readLine();
+ long end = System.currentTimeMillis();
+ mTime += end - start;
+ return ret;
+ }
+
+ public long getTotalmillisecond() {
+ return mTime;
+ }
+}
diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V30.java b/core/java/android/syncml/pim/vcard/VCardParser_V30.java
index 901bd49..e67525e 100644
--- a/core/java/android/syncml/pim/vcard/VCardParser_V30.java
+++ b/core/java/android/syncml/pim/vcard/VCardParser_V30.java
@@ -16,8 +16,9 @@
package android.syncml.pim.vcard;
+import android.util.Log;
+
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -26,9 +27,11 @@
* Please refer to vCard Specification 3.0 (http://tools.ietf.org/html/rfc2426)
*/
public class VCardParser_V30 extends VCardParser_V21 {
+ private static final String LOG_TAG = "VCardParser_V30";
+
private static final HashSet<String> acceptablePropsWithParam = new HashSet<String>(
Arrays.asList(
- "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
+ "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
"VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
"BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", // 2.1
"NAME", "PROFILE", "SOURCE", "NICKNAME", "CLASS",
@@ -51,8 +54,14 @@
@Override
protected boolean isValidPropertyName(String propertyName) {
- return acceptablePropsWithParam.contains(propertyName) ||
- acceptablePropsWithoutParam.contains(propertyName);
+ if (!(acceptablePropsWithParam.contains(propertyName) ||
+ acceptablePropsWithoutParam.contains(propertyName) ||
+ propertyName.startsWith("X-")) &&
+ !mWarningValueMap.contains(propertyName)) {
+ mWarningValueMap.add(propertyName);
+ Log.w(LOG_TAG, "Property name unsupported by vCard 3.0: " + propertyName);
+ }
+ return true;
}
@Override
@@ -100,7 +109,21 @@
}
} else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') {
if (builder != null) {
- // TODO: Check whether MIME requires only one whitespace.
+ // See Section 5.8.1 of RFC 2425 (MIME-DIR document).
+ // Following is the excerpts from it.
+ //
+ // DESCRIPTION:This is a long description that exists on a long line.
+ //
+ // Can be represented as:
+ //
+ // DESCRIPTION:This is a long description
+ // that exists on a long line.
+ //
+ // It could also be represented as:
+ //
+ // DESCRIPTION:This is a long descrip
+ // tion that exists o
+ // n a long line.
builder.append(line.substring(1));
} else if (mPreviousLine != null) {
builder = new StringBuilder();
@@ -113,10 +136,13 @@
} else {
if (mPreviousLine == null) {
mPreviousLine = line;
+ if (builder != null) {
+ return builder.toString();
+ }
} else {
String ret = mPreviousLine;
mPreviousLine = line;
- return ret;
+ return ret;
}
}
}
@@ -130,15 +156,16 @@
* [group "."] "END" ":" "VCARD" 1*CRLF
*/
@Override
- protected boolean readBeginVCard() throws IOException, VCardException {
+ protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {
// TODO: vCard 3.0 supports group.
- return super.readBeginVCard();
+ return super.readBeginVCard(allowGarbage);
}
@Override
- protected void readEndVCard() throws VCardException {
+ protected void readEndVCard(boolean useCache, boolean allowGarbage)
+ throws IOException, VCardException {
// TODO: vCard 3.0 supports group.
- super.readEndVCard();
+ super.readEndVCard(useCache, allowGarbage);
}
/**
@@ -214,23 +241,6 @@
throw new VCardException("AGENT in vCard 3.0 is not supported yet.");
}
- // vCard 3.0 supports "B" as BASE64 encoding.
- @Override
- protected void handlePropertyValue(
- String propertyName, String propertyValue) throws
- IOException, VCardException {
- if (mEncoding != null && mEncoding.equalsIgnoreCase("B")) {
- String result = getBase64(propertyValue);
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add(result);
- mBuilder.propertyValues(v);
- }
- }
-
- super.handlePropertyValue(propertyName, propertyValue);
- }
-
/**
* vCard 3.0 does not require two CRLF at the last of BASE64 data.
* It only requires that data should be MIME-encoded.
@@ -259,27 +269,38 @@
}
/**
- * Return unescapeText(text).
- * In vCard 3.0, 8bit text is always encoded.
- */
- @Override
- protected String maybeUnescapeText(String text) {
- return unescapeText(text);
- }
-
- /**
* ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N")
* ; \\ encodes \, \n or \N encodes newline
* ; \; encodes ;, \, encodes ,
- */
+ *
+ * Note: Apple escape ':' into '\:' while does not escape '\'
+ */
@Override
- protected String unescapeText(String text) {
- // In String#replaceAll(), "\\\\" means single slash.
- return text.replaceAll("\\\\;", ";")
- .replaceAll("\\\\:", ":")
- .replaceAll("\\\\,", ",")
- .replaceAll("\\\\n", "\r\n")
- .replaceAll("\\\\N", "\r\n")
- .replaceAll("\\\\\\\\", "\\\\");
+ protected String maybeUnescapeText(String text) {
+ StringBuilder builder = new StringBuilder();
+ int length = text.length();
+ for (int i = 0; i < length; i++) {
+ char ch = text.charAt(i);
+ if (ch == '\\' && i < length - 1) {
+ char next_ch = text.charAt(++i);
+ if (next_ch == 'n' || next_ch == 'N') {
+ builder.append("\r\n");
+ } else {
+ builder.append(next_ch);
+ }
+ } else {
+ builder.append(ch);
+ }
+ }
+ return builder.toString();
+ }
+
+ @Override
+ protected String maybeUnescape(char ch) {
+ if (ch == 'n' || ch == 'N') {
+ return "\r\n";
+ } else {
+ return String.valueOf(ch);
+ }
}
}
diff --git a/core/java/android/syncml/pim/vcard/VCardSourceDetector.java b/core/java/android/syncml/pim/vcard/VCardSourceDetector.java
new file mode 100644
index 0000000..8c48391
--- /dev/null
+++ b/core/java/android/syncml/pim/vcard/VCardSourceDetector.java
@@ -0,0 +1,140 @@
+/*
+ * 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 android.syncml.pim.vcard;
+
+import android.syncml.pim.VBuilder;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Class which tries to detects the source of the vCard from its properties.
+ * Currently this implementation is very premature.
+ * @hide
+ */
+public class VCardSourceDetector implements VBuilder {
+ // Should only be used in package.
+ static final int TYPE_UNKNOWN = 0;
+ static final int TYPE_APPLE = 1;
+ static final int TYPE_JAPANESE_MOBILE_PHONE = 2; // Used in Japanese mobile phones.
+ static final int TYPE_FOMA = 3; // Used in some Japanese FOMA mobile phones.
+ static final int TYPE_WINDOWS_MOBILE_JP = 4;
+ // TODO: Excel, etc.
+
+ private static Set<String> APPLE_SIGNS = new HashSet<String>(Arrays.asList(
+ "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", "X-PHONETIC-LAST-NAME",
+ "X-ABADR", "X-ABUID"));
+
+ private static Set<String> JAPANESE_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList(
+ "X-GNO", "X-GN", "X-REDUCTION"));
+
+ private static Set<String> WINDOWS_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList(
+ "X-MICROSOFT-ASST_TEL", "X-MICROSOFT-ASSISTANT", "X-MICROSOFT-OFFICELOC"));
+
+ // Note: these signes appears before the signs of the other type (e.g. "X-GN").
+ // In other words, Japanese FOMA mobile phones are detected as FOMA, not JAPANESE_MOBILE_PHONES.
+ private static Set<String> FOMA_SIGNS = new HashSet<String>(Arrays.asList(
+ "X-SD-VERN", "X-SD-FORMAT_VER", "X-SD-CATEGORIES", "X-SD-CLASS", "X-SD-DCREATED",
+ "X-SD-DESCRIPTION"));
+ private static String TYPE_FOMA_CHARSET_SIGN = "X-SD-CHAR_CODE";
+
+ private int mType = TYPE_UNKNOWN;
+ // Some mobile phones (like FOMA) tells us the charset of the data.
+ private boolean mNeedParseSpecifiedCharset;
+ private String mSpecifiedCharset;
+
+ public void start() {
+ }
+
+ public void end() {
+ }
+
+ public void startRecord(String type) {
+ }
+
+ public void startProperty() {
+ mNeedParseSpecifiedCharset = false;
+ }
+
+ public void endProperty() {
+ }
+
+ public void endRecord() {
+ }
+
+ public void propertyGroup(String group) {
+ }
+
+ public void propertyName(String name) {
+ if (name.equalsIgnoreCase(TYPE_FOMA_CHARSET_SIGN)) {
+ mType = TYPE_FOMA;
+ mNeedParseSpecifiedCharset = true;
+ return;
+ }
+ if (mType != TYPE_UNKNOWN) {
+ return;
+ }
+ if (WINDOWS_MOBILE_PHONE_SIGNS.contains(name)) {
+ mType = TYPE_WINDOWS_MOBILE_JP;
+ } else if (FOMA_SIGNS.contains(name)) {
+ mType = TYPE_FOMA;
+ } else if (JAPANESE_MOBILE_PHONE_SIGNS.contains(name)) {
+ mType = TYPE_JAPANESE_MOBILE_PHONE;
+ } else if (APPLE_SIGNS.contains(name)) {
+ mType = TYPE_APPLE;
+ }
+ }
+
+ public void propertyParamType(String type) {
+ }
+
+ public void propertyParamValue(String value) {
+ }
+
+ public void propertyValues(List<String> values) {
+ if (mNeedParseSpecifiedCharset && values.size() > 0) {
+ mSpecifiedCharset = values.get(0);
+ }
+ }
+
+ int getType() {
+ return mType;
+ }
+
+ /**
+ * Return charset String guessed from the source's properties.
+ * This method must be called after parsing target file(s).
+ * @return Charset String. Null is returned if guessing the source fails.
+ */
+ public String getEstimatedCharset() {
+ if (mSpecifiedCharset != null) {
+ return mSpecifiedCharset;
+ }
+ switch (mType) {
+ case TYPE_WINDOWS_MOBILE_JP:
+ case TYPE_FOMA:
+ case TYPE_JAPANESE_MOBILE_PHONE:
+ return "SHIFT_JIS";
+ case TYPE_APPLE:
+ return "UTF-8";
+ default:
+ return null;
+ }
+ }
+}
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 0dc96c3..3156d8b 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -242,64 +242,48 @@
/**
* Returns a {@link java.text.DateFormat} object that can format the time according
- * to the current user preference.
+ * to the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that properly formats the time.
*/
public static final java.text.DateFormat getTimeFormat(Context context) {
- boolean b24 = is24HourFormat(context);
- int res;
-
- if (b24) {
- res = R.string.twenty_four_hour_time_format;
- } else {
- res = R.string.twelve_hour_time_format;
- }
-
- return new java.text.SimpleDateFormat(context.getString(res));
+ return java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
}
/**
- * Returns a {@link java.text.DateFormat} object that can format the date according
- * to the current user preference.
+ * Returns a {@link java.text.DateFormat} object that can format the date
+ * in short form (such as 12/31/1999) according
+ * to the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that properly formats the date.
*/
public static final java.text.DateFormat getDateFormat(Context context) {
- String value = getDateFormatString(context);
+ /*
+ * We use a resource string here instead of just DateFormat.SHORT
+ * so that we get a four-digit year instead a two-digit year.
+ */
+ String value = context.getString(R.string.numeric_date_format);
return new java.text.SimpleDateFormat(value);
}
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in long form (such as December 31, 1999) based on user preference.
+ * in long form (such as December 31, 1999) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
public static final java.text.DateFormat getLongDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.full_date_month_first);
- } else {
- value = context.getString(R.string.full_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
+ return java.text.DateFormat.getDateInstance(java.text.DateFormat.LONG);
}
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in medium form (such as Dec. 31, 1999) based on user preference.
+ * in medium form (such as Dec. 31, 1999) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
public static final java.text.DateFormat getMediumDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.medium_date_month_first);
- } else {
- value = context.getString(R.string.medium_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
+ return java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM);
}
/**
@@ -338,6 +322,12 @@
}
private static String getDateFormatString(Context context) {
+ java.text.DateFormat df;
+ df = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);
+ if (df instanceof SimpleDateFormat) {
+ return ((SimpleDateFormat) df).toPattern();
+ }
+
String value = Settings.System.getString(context.getContentResolver(),
Settings.System.DATE_FORMAT);
if (value == null || value.length() < 6) {
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 8a7cdd9..9073d82 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -62,15 +62,6 @@
com.android.internal.R.string.day_of_week_short_friday,
com.android.internal.R.string.day_of_week_short_saturday,
};
- private static final int[] sDaysShorter = new int[] {
- com.android.internal.R.string.day_of_week_shorter_sunday,
- com.android.internal.R.string.day_of_week_shorter_monday,
- com.android.internal.R.string.day_of_week_shorter_tuesday,
- com.android.internal.R.string.day_of_week_shorter_wednesday,
- com.android.internal.R.string.day_of_week_shorter_thursday,
- com.android.internal.R.string.day_of_week_shorter_friday,
- com.android.internal.R.string.day_of_week_shorter_saturday,
- };
private static final int[] sDaysShortest = new int[] {
com.android.internal.R.string.day_of_week_shortest_sunday,
com.android.internal.R.string.day_of_week_shortest_monday,
@@ -80,6 +71,20 @@
com.android.internal.R.string.day_of_week_shortest_friday,
com.android.internal.R.string.day_of_week_shortest_saturday,
};
+ private static final int[] sMonthsStandaloneLong = new int [] {
+ com.android.internal.R.string.month_long_standalone_january,
+ com.android.internal.R.string.month_long_standalone_february,
+ com.android.internal.R.string.month_long_standalone_march,
+ com.android.internal.R.string.month_long_standalone_april,
+ com.android.internal.R.string.month_long_standalone_may,
+ com.android.internal.R.string.month_long_standalone_june,
+ com.android.internal.R.string.month_long_standalone_july,
+ com.android.internal.R.string.month_long_standalone_august,
+ com.android.internal.R.string.month_long_standalone_september,
+ com.android.internal.R.string.month_long_standalone_october,
+ com.android.internal.R.string.month_long_standalone_november,
+ com.android.internal.R.string.month_long_standalone_december,
+ };
private static final int[] sMonthsLong = new int [] {
com.android.internal.R.string.month_long_january,
com.android.internal.R.string.month_long_february,
@@ -127,7 +132,7 @@
com.android.internal.R.string.pm,
};
private static Configuration sLastConfig;
- private static String sStatusTimeFormat;
+ private static java.text.DateFormat sStatusTimeFormat;
private static String sElapsedFormatMMSS;
private static String sElapsedFormatHMMSS;
@@ -255,18 +260,15 @@
* For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
* @more
* <p>e.g. "Su" or "Jan"
- * <p>In some languages, the results returned for LENGTH_SHORT may be the same as
- * return for {@link #LENGTH_MEDIUM}.
+ * <p>In most languages, the results returned for LENGTH_SHORT will be the same as
+ * the results returned for {@link #LENGTH_MEDIUM}.
*/
public static final int LENGTH_SHORT = 30;
/**
* Request an even shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "M", "Tu", "Th" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
+ * Do not use this. Currently this will always return the same result
+ * as {@link #LENGTH_SHORT}.
*/
public static final int LENGTH_SHORTER = 40;
@@ -275,8 +277,8 @@
* For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
* @more
* <p>e.g. "S", "T", "T" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
+ * <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as
+ * the results returned for {@link #LENGTH_SHORT}.
*/
public static final int LENGTH_SHORTEST = 50;
@@ -284,9 +286,12 @@
* Return a string for the day of the week.
* @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY},
* {@link Calendar#MONDAY Calendar.MONDAY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
+ * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT},
+ * {@link #LENGTH_MEDIUM}, or {@link #LENGTH_SHORTEST}.
+ * Note that in most languages, {@link #LENGTH_SHORT}
+ * will return the same as {@link #LENGTH_MEDIUM}.
+ * Undefined lengths will return {@link #LENGTH_MEDIUM}
+ * but may return something different in the future.
* @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
*/
public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
@@ -295,7 +300,7 @@
case LENGTH_LONG: list = sDaysLong; break;
case LENGTH_MEDIUM: list = sDaysMedium; break;
case LENGTH_SHORT: list = sDaysShort; break;
- case LENGTH_SHORTER: list = sDaysShorter; break;
+ case LENGTH_SHORTER: list = sDaysShort; break;
case LENGTH_SHORTEST: list = sDaysShortest; break;
default: list = sDaysMedium; break;
}
@@ -316,13 +321,14 @@
}
/**
- * Return a localized string for the day of the week.
+ * Return a localized string for the month of the year.
* @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
* {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
- * @return Localized day of the week.
+ * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
+ * or {@link #LENGTH_SHORTEST}.
+ * Undefined lengths will return {@link #LENGTH_MEDIUM}
+ * but may return something different in the future.
+ * @return Localized month of the year.
*/
public static String getMonthString(int month, int abbrev) {
// Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
@@ -344,6 +350,40 @@
}
/**
+ * Return a localized string for the month of the year, for
+ * contexts where the month is not formatted together with
+ * a day of the month.
+ *
+ * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
+ * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
+ * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
+ * or {@link #LENGTH_SHORTEST}.
+ * Undefined lengths will return {@link #LENGTH_MEDIUM}
+ * but may return something different in the future.
+ * @return Localized month of the year.
+ * @hide Pending API council approval
+ */
+ public static String getStandaloneMonthString(int month, int abbrev) {
+ // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
+ // This is a shortcut to not spam the translators with too many variations
+ // of the same string. If we find that in a language the distinction
+ // is necessary, we can can add more without changing this API.
+ int[] list;
+ switch (abbrev) {
+ case LENGTH_LONG: list = sMonthsStandaloneLong;
+ break;
+ case LENGTH_MEDIUM: list = sMonthsMedium; break;
+ case LENGTH_SHORT: list = sMonthsMedium; break;
+ case LENGTH_SHORTER: list = sMonthsMedium; break;
+ case LENGTH_SHORTEST: list = sMonthsShortest; break;
+ default: list = sMonthsMedium; break;
+ }
+
+ Resources r = Resources.getSystem();
+ return r.getString(list[month - Calendar.JANUARY]);
+ }
+
+ /**
* Returns a string describing the elapsed time since startTime.
* @param startTime some time in the past.
* @return a String object containing the elapsed time.
@@ -572,7 +612,7 @@
Configuration cfg = r.getConfiguration();
if (sLastConfig == null || !sLastConfig.equals(cfg)) {
sLastConfig = cfg;
- sStatusTimeFormat = r.getString(com.android.internal.R.string.status_bar_time_format);
+ sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
}
@@ -586,7 +626,7 @@
*/
public static final CharSequence timeString(long millis) {
initFormatStrings();
- return DateFormat.format(sStatusTimeFormat, millis);
+ return sStatusTimeFormat.format(millis);
}
/**
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 8f12355..8eae111 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -135,6 +135,7 @@
private static Locale sLocale;
private static String[] sShortMonths;
private static String[] sLongMonths;
+ private static String[] sLongStandaloneMonths;
private static String[] sShortWeekdays;
private static String[] sLongWeekdays;
private static String sTimeOnlyFormat;
@@ -321,6 +322,20 @@
r.getString(com.android.internal.R.string.month_long_november),
r.getString(com.android.internal.R.string.month_long_december),
};
+ sLongStandaloneMonths = new String[] {
+ r.getString(com.android.internal.R.string.month_long_standalone_january),
+ r.getString(com.android.internal.R.string.month_long_standalone_february),
+ r.getString(com.android.internal.R.string.month_long_standalone_march),
+ r.getString(com.android.internal.R.string.month_long_standalone_april),
+ r.getString(com.android.internal.R.string.month_long_standalone_may),
+ r.getString(com.android.internal.R.string.month_long_standalone_june),
+ r.getString(com.android.internal.R.string.month_long_standalone_july),
+ r.getString(com.android.internal.R.string.month_long_standalone_august),
+ r.getString(com.android.internal.R.string.month_long_standalone_september),
+ r.getString(com.android.internal.R.string.month_long_standalone_october),
+ r.getString(com.android.internal.R.string.month_long_standalone_november),
+ r.getString(com.android.internal.R.string.month_long_standalone_december),
+ };
sShortWeekdays = new String[] {
r.getString(com.android.internal.R.string.day_of_week_medium_sunday),
r.getString(com.android.internal.R.string.day_of_week_medium_monday),
diff --git a/core/java/android/util/CharsetUtils.java b/core/java/android/util/CharsetUtils.java
index 7553029..9d91aca 100644
--- a/core/java/android/util/CharsetUtils.java
+++ b/core/java/android/util/CharsetUtils.java
@@ -142,20 +142,25 @@
/**
* Returns whether the given character set name indicates the Shift-JIS
- * encoding.
+ * encoding. Returns false if the name is null.
*
* @param charsetName the character set name
* @return {@code true} if the name corresponds to Shift-JIS or
* {@code false} if not
*/
private static boolean isShiftJis(String charsetName) {
- if (charsetName.length() != 9) {
- // Bail quickly if the length doesn't match.
+ // Bail quickly if the length doesn't match.
+ if (charsetName == null) {
+ return false;
+ }
+ int length = charsetName.length();
+ if (length != 4 && length != 9) {
return false;
}
return charsetName.equalsIgnoreCase("shift_jis")
- || charsetName.equalsIgnoreCase("shift-jis");
+ || charsetName.equalsIgnoreCase("shift-jis")
+ || charsetName.equalsIgnoreCase("sjis");
}
/**
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 86261c4..f1bf0f4 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -19,7 +19,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.util.Config;
/**
* Object used to report movement (mouse, pen, finger, trackball) events. This
@@ -87,6 +86,7 @@
private long mDownTime;
private long mEventTime;
+ private long mEventTimeNano;
private int mAction;
private float mX;
private float mY;
@@ -123,6 +123,62 @@
return ev;
}
}
+
+ /**
+ * Create a new MotionEvent, filling in all of the basic values that
+ * define the motion.
+ *
+ * @param downTime The time (in ms) when the user originally pressed down to start
+ * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
+ * @param eventTime The the time (in ms) when this specific event was generated. This
+ * must be obtained from {@link SystemClock#uptimeMillis()}.
+ * @param eventTimeNano The the time (in ns) when this specific event was generated. This
+ * must be obtained from {@link System#nanoTime()}.
+ * @param action The kind of action being performed -- one of either
+ * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
+ * {@link #ACTION_CANCEL}.
+ * @param x The X coordinate of this event.
+ * @param y The Y coordinate of this event.
+ * @param pressure The current pressure of this event. The pressure generally
+ * ranges from 0 (no pressure at all) to 1 (normal pressure), however
+ * values higher than 1 may be generated depending on the calibration of
+ * the input device.
+ * @param size A scaled value of the approximate size of the area being pressed when
+ * touched with the finger. The actual value in pixels corresponding to the finger
+ * touch is normalized with a device specific range of values
+ * and scaled to a value between 0 and 1.
+ * @param metaState The state of any meta / modifier keys that were in effect when
+ * the event was generated.
+ * @param xPrecision The precision of the X coordinate being reported.
+ * @param yPrecision The precision of the Y coordinate being reported.
+ * @param deviceId The id for the device that this event came from. An id of
+ * zero indicates that the event didn't come from a physical device; other
+ * numbers are arbitrary and you shouldn't depend on the values.
+ * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+ * MotionEvent.
+ *
+ * @hide
+ */
+ static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
+ int action, float x, float y, float pressure, float size, int metaState,
+ float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
+ MotionEvent ev = obtain();
+ ev.mDeviceId = deviceId;
+ ev.mEdgeFlags = edgeFlags;
+ ev.mDownTime = downTime;
+ ev.mEventTime = eventTime;
+ ev.mEventTimeNano = eventTimeNano;
+ ev.mAction = action;
+ ev.mX = ev.mRawX = x;
+ ev.mY = ev.mRawY = y;
+ ev.mPressure = pressure;
+ ev.mSize = size;
+ ev.mMetaState = metaState;
+ ev.mXPrecision = xPrecision;
+ ev.mYPrecision = yPrecision;
+
+ return ev;
+ }
/**
* Create a new MotionEvent, filling in all of the basic values that
@@ -163,6 +219,7 @@
ev.mEdgeFlags = edgeFlags;
ev.mDownTime = downTime;
ev.mEventTime = eventTime;
+ ev.mEventTimeNano = eventTime * 1000000;
ev.mAction = action;
ev.mX = ev.mRawX = x;
ev.mY = ev.mRawY = y;
@@ -199,6 +256,7 @@
ev.mEdgeFlags = 0;
ev.mDownTime = downTime;
ev.mEventTime = eventTime;
+ ev.mEventTimeNano = eventTime * 1000000;
ev.mAction = action;
ev.mX = ev.mRawX = x;
ev.mY = ev.mRawY = y;
@@ -246,6 +304,7 @@
ev.mEdgeFlags = o.mEdgeFlags;
ev.mDownTime = o.mDownTime;
ev.mEventTime = o.mEventTime;
+ ev.mEventTimeNano = o.mEventTimeNano;
ev.mAction = o.mAction;
ev.mX = o.mX;
ev.mRawX = o.mRawX;
@@ -317,6 +376,16 @@
}
/**
+ * Returns the time (in ns) when this specific event was generated.
+ * The value is in nanosecond precision but it may not have nanosecond accuracy.
+ *
+ * @hide
+ */
+ public final long getEventTimeNano() {
+ return mEventTimeNano;
+ }
+
+ /**
* Returns the X coordinate of this event. Whole numbers are pixels; the
* value may have a fraction for input devices that are sub-pixel precise.
*/
@@ -644,6 +713,7 @@
public void writeToParcel(Parcel out, int flags) {
out.writeLong(mDownTime);
out.writeLong(mEventTime);
+ out.writeLong(mEventTimeNano);
out.writeInt(mAction);
out.writeFloat(mX);
out.writeFloat(mY);
@@ -675,6 +745,7 @@
private void readFromParcel(Parcel in) {
mDownTime = in.readLong();
mEventTime = in.readLong();
+ mEventTimeNano = in.readLong();
mAction = in.readInt();
mX = in.readFloat();
mY = in.readFloat();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 49e4e4c..e70c94c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -101,6 +101,8 @@
static final int KEEP_SCREEN_ON_MSG = 1;
static final int GET_NEW_SURFACE_MSG = 2;
+ int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+
boolean mIsCreating = false;
final Handler mHandler = new Handler() {
@@ -286,6 +288,15 @@
super.dispatchDraw(canvas);
}
+ /**
+ * Hack to allow special layering of windows. The type is one of the
+ * types in WindowManager.LayoutParams. This is a hack so:
+ * @hide
+ */
+ public void setWindowType(int type) {
+ mWindowType = type;
+ }
+
private void updateWindow(boolean force) {
if (!mHaveFrame) {
return;
@@ -343,7 +354,7 @@
if (mWindow == null) {
mWindow = new MyWindow(this);
- mLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ mLayout.type = mWindowType;
mLayout.gravity = Gravity.LEFT|Gravity.TOP;
mSession.add(mWindow, mLayout,
mVisible ? VISIBLE : GONE, mContentInsets);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1564fd0..1f72eea 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1443,6 +1443,27 @@
static final int DIRTY_MASK = 0x00600000;
/**
+ * Indicates whether the background is opaque.
+ *
+ * @hide
+ */
+ static final int OPAQUE_BACKGROUND = 0x00800000;
+
+ /**
+ * Indicates whether the scrollbars are opaque.
+ *
+ * @hide
+ */
+ static final int OPAQUE_SCROLLBARS = 0x01000000;
+
+ /**
+ * Indicates whether the view is opaque.
+ *
+ * @hide
+ */
+ static final int OPAQUE_MASK = 0x01800000;
+
+ /**
* The parent this view is attached to.
* {@hide}
*
@@ -1721,7 +1742,7 @@
public View(Context context) {
mContext = context;
mResources = context != null ? context.getResources() : null;
- mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
+ mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
++sInstanceCount;
}
@@ -2013,7 +2034,9 @@
if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
setScrollContainer(true);
}
-
+
+ computeOpaqueFlags();
+
a.recycle();
}
@@ -4700,7 +4723,35 @@
*/
@ViewDebug.ExportedProperty
public boolean isOpaque() {
- return mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE;
+ return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
+ }
+
+ private void computeOpaqueFlags() {
+ // Opaque if:
+ // - Has a background
+ // - Background is opaque
+ // - Doesn't have scrollbars or scrollbars are inside overlay
+
+ if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
+ mPrivateFlags |= OPAQUE_BACKGROUND;
+ } else {
+ mPrivateFlags &= ~OPAQUE_BACKGROUND;
+ }
+
+ final int flags = mViewFlags;
+ if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
+ (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
+ mPrivateFlags |= OPAQUE_SCROLLBARS;
+ } else {
+ mPrivateFlags &= ~OPAQUE_SCROLLBARS;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ protected boolean hasOpaqueScrollbars() {
+ return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
}
/**
@@ -5027,6 +5078,7 @@
public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_HORIZONTAL;
+ computeOpaqueFlags();
recomputePadding();
}
}
@@ -5056,6 +5108,7 @@
public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_VERTICAL;
+ computeOpaqueFlags();
recomputePadding();
}
}
@@ -5084,6 +5137,7 @@
public void setScrollBarStyle(int style) {
if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
+ computeOpaqueFlags();
recomputePadding();
}
}
@@ -6848,6 +6902,8 @@
requestLayout = true;
}
+ computeOpaqueFlags();
+
if (requestLayout) {
requestLayout();
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 7cd65e2..d999119 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -77,6 +77,9 @@
private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
private static final boolean WATCH_POINTER = false;
+ private static final boolean MEASURE_LATENCY = false;
+ private static LatencyTimer lt;
+
/**
* Maximum time we allow the user to roll the trackball enough to generate
* a key event, before resetting the counters.
@@ -192,6 +195,10 @@
public ViewRoot(Context context) {
super();
+ if (MEASURE_LATENCY && lt == null) {
+ lt = new LatencyTimer(100, 1000);
+ }
+
++sInstanceCount;
// Initialize the statics when this class is first instantiated. This is
@@ -1579,7 +1586,17 @@
boolean didFinish;
if (event == null) {
try {
+ long timeBeforeGettingEvents;
+ if (MEASURE_LATENCY) {
+ timeBeforeGettingEvents = System.nanoTime();
+ }
+
event = sWindowSession.getPendingPointerMove(mWindow);
+
+ if (MEASURE_LATENCY && event != null) {
+ lt.sample("9 Client got events ", System.nanoTime() - event.getEventTimeNano());
+ lt.sample("8 Client getting events ", timeBeforeGettingEvents - event.getEventTimeNano());
+ }
} catch (RemoteException e) {
}
didFinish = true;
@@ -1603,7 +1620,13 @@
captureMotionLog("captureDispatchPointer", event);
}
event.offsetLocation(0, mCurScrollY);
+ if (MEASURE_LATENCY) {
+ lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
+ }
handled = mView.dispatchTouchEvent(event);
+ if (MEASURE_LATENCY) {
+ lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
+ }
if (!handled && isDown) {
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
@@ -2685,7 +2708,11 @@
public void dispatchPointer(MotionEvent event, long eventTime) {
final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
+ if (viewRoot != null) {
+ if (MEASURE_LATENCY) {
+ // Note: eventTime is in milliseconds
+ ViewRoot.lt.sample("* ViewRoot b4 dispatchPtr", System.nanoTime() - eventTime * 1000000);
+ }
viewRoot.dispatchPointer(event, eventTime);
} else {
new EventCompletion(mMainLooper, this, null, true, event);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b0e738c..d7457a0 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -376,8 +376,14 @@
String title;
if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
title="Media";
+ } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
+ title="MediaOvr";
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
title="Panel";
+ } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
+ title="SubPanel";
+ } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
+ title="AtchDlg";
} else {
title=Integer.toString(wp.type);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c69c281..ec2069c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -210,6 +210,15 @@
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
/**
+ * Window type: window for showing overlays on top of media windows.
+ * These windows are displayed between TYPE_APPLICATION_MEDIA and the
+ * application window. They should be translucent to be useful. This
+ * is a big ugly hack so:
+ * @hide
+ */
+ public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4;
+
+ /**
* End of types of sub-windows.
*/
public static final int LAST_SUB_WINDOW = 1999;
@@ -466,6 +475,15 @@
*/
public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
+ /** Window flag: special flag to let windows be shown when the screen
+ * is locked. This will let application windows take precedence over
+ * key guard or any other lock screens. Can be used with
+ * {@link #FLAG_KEEP_SCREEN_ON} to turn screen on and display windows
+ * directly before showing the key guard window
+ *
+ * {@hide} */
+ public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
+
/** Window flag: a special option intended for system dialogs. When
* this flag is set, the window will demand focus unconditionally when
* it is created.
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
index 2d431a8..1384042 100644
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
@@ -28,6 +28,7 @@
import android.content.Context;
import android.telephony.CellLocation;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.gsm.GsmCellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
@@ -54,6 +55,7 @@
public static final class RadioData {
public int cellId = -1;
public int locationAreaCode = -1;
+ // TODO: use new SignalStrength instead of asu
public int signalStrength = -1;
public int mobileCountryCode = -1;
public int mobileNetworkCode = -1;
@@ -179,6 +181,7 @@
private CellLocation cellLocation = null;
/** The last known signal strength */
+ // TODO: use new SignalStrength instead of asu
private int signalStrength = -1;
/** The last known serviceState */
@@ -207,7 +210,7 @@
// Register for cell id, signal strength and service state changed
// notifications.
telephonyManager.listen(this, PhoneStateListener.LISTEN_CELL_LOCATION
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_SERVICE_STATE);
}
@@ -226,8 +229,9 @@
}
@Override
- public void onSignalStrengthChanged(int asu) {
- signalStrength = asu;
+ public void onSignalStrengthsChanged(SignalStrength ss) {
+ int gsmSignalStrength = ss.getGsmSignalStrength();
+ signalStrength = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
notifyListeners();
}
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 0fc8f49..5360621 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -1083,6 +1083,11 @@
@Override
public void onRestoreInstanceState(Parcelable state) {
+ if (!(state instanceof SavedState)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
index 4c1cbf6..d417e40 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -27,9 +27,35 @@
/**
* <p>
- * An image button displays an image that can be pressed, or clicked, by the
- * user.
- * </p>
+ * Displays a button with an image (instead of text) that can be pressed
+ * or clicked by the user. By default, an ImageButton looks like a regular
+ * {@link android.widget.Button}, with the standard button background
+ * that changes color during different button states. The image on the surface
+ * of the button is defined either by the {@code android:src} attribute in the
+ * {@code <ImageButton>} XML element or by the
+ * {@link #setImageResource(int)} method.</p>
+ *
+ * <p>To remove the standard button background image, define your own
+ * background image or set the background color to be transparent.</p>
+ * <p>To indicate the different button states (focused, selected, etc.), you can
+ * define a different image for each state. E.g., a blue image by default, an
+ * orange one for when focused, and a yellow one for when pressed. An easy way to
+ * do this is with an XML drawable "selector." For example:</p>
+ * <pre>
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <selector xmlns:android="http://schemas.android.com/apk/res/android">
+ * <item android:drawable="@drawable/button_normal" /> <!-- default -->
+ * <item android:state_pressed="true"
+ * android:drawable="@drawable/button_pressed" /> <!-- pressed -->
+ * <item android:state_focused="true"
+ * android:drawable="@drawable/button_focused" /> <!-- focused -->
+ * </selector></pre>
+ *
+ * <p>Save the XML file in your project {@code res/drawable/} folder and then
+ * reference it as a drawable for the source of your ImageButton (in the
+ * {@code android:src} attribute). Android will automatically change the image
+ * based on the state of the button and the corresponding images
+ * defined in the XML.</p>
*
* <p><strong>XML attributes</strong></p>
* <p>
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index c21c7fa..6686f75 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -21,6 +21,7 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.PixelFormat;
+import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Parcel;
@@ -133,6 +134,7 @@
// used for temporary calculations.
private final Rect mTempRect = new Rect();
+ private Paint mDividerPaint;
// the single allocated result per list view; kinda cheesey but avoids
// allocating these thingies too often.
@@ -2813,12 +2815,20 @@
*/
@Override
public boolean isOpaque() {
- return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque) || super.isOpaque();
+ return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque &&
+ hasOpaqueScrollbars()) || super.isOpaque();
}
@Override
public void setCacheColorHint(int color) {
- mIsCacheColorOpaque = (color >>> 24) == 0xFF;
+ final boolean opaque = (color >>> 24) == 0xFF;
+ mIsCacheColorOpaque = opaque;
+ if (opaque) {
+ if (mDividerPaint == null) {
+ mDividerPaint = new Paint();
+ }
+ mDividerPaint.setColor(color);
+ }
super.setCacheColorHint(color);
}
@@ -2841,6 +2851,8 @@
final int first = mFirstPosition;
final boolean areAllItemsSelectable = mAreAllItemsSelectable;
final ListAdapter adapter = mAdapter;
+ final boolean isOpaque = isOpaque();
+ final Paint paint = mDividerPaint;
if (!mStackFromBottom) {
int bottom;
@@ -2852,12 +2864,18 @@
View child = getChildAt(i);
bottom = child.getBottom();
// Don't draw dividers next to items that are not enabled
- if (bottom < listBottom && (areAllItemsSelectable ||
- (adapter.isEnabled(first + i) && (i == count - 1 ||
- adapter.isEnabled(first + i + 1))))) {
- bounds.top = bottom;
- bounds.bottom = bottom + dividerHeight;
- drawDivider(canvas, bounds, i);
+ if (bottom < listBottom) {
+ if ((areAllItemsSelectable ||
+ (adapter.isEnabled(first + i) && (i == count - 1 ||
+ adapter.isEnabled(first + i + 1))))) {
+ bounds.top = bottom;
+ bounds.bottom = bottom + dividerHeight;
+ drawDivider(canvas, bounds, i);
+ } else if (isOpaque) {
+ bounds.top = bottom;
+ bounds.bottom = bottom + dividerHeight;
+ canvas.drawRect(bounds, paint);
+ }
}
}
}
@@ -2871,16 +2889,22 @@
View child = getChildAt(i);
top = child.getTop();
// Don't draw dividers next to items that are not enabled
- if (top > listTop && (areAllItemsSelectable ||
- (adapter.isEnabled(first + i) && (i == count - 1 ||
- adapter.isEnabled(first + i + 1))))) {
- bounds.top = top - dividerHeight;
- bounds.bottom = top;
- // Give the method the child ABOVE the divider, so we
- // subtract one from our child
- // position. Give -1 when there is no child above the
- // divider.
- drawDivider(canvas, bounds, i - 1);
+ if (top > listTop) {
+ if ((areAllItemsSelectable ||
+ (adapter.isEnabled(first + i) && (i == count - 1 ||
+ adapter.isEnabled(first + i + 1))))) {
+ bounds.top = top - dividerHeight;
+ bounds.bottom = top;
+ // Give the method the child ABOVE the divider, so we
+ // subtract one from our child
+ // position. Give -1 when there is no child above the
+ // divider.
+ drawDivider(canvas, bounds, i - 1);
+ } else if (isOpaque) {
+ bounds.top = top - dividerHeight;
+ bounds.bottom = top;
+ canvas.drawRect(bounds, paint);
+ }
}
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 219afec..40a72a4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1329,9 +1329,13 @@
} else {
// We need to retain the last set padding, so just clear
// out all of the fields in the existing structure.
+ if (dr.mDrawableLeft != null) dr.mDrawableLeft.setCallback(null);
dr.mDrawableLeft = null;
+ if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null);
dr.mDrawableTop = null;
+ if (dr.mDrawableRight != null) dr.mDrawableRight.setCallback(null);
dr.mDrawableRight = null;
+ if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null);
dr.mDrawableBottom = null;
dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
@@ -1344,19 +1348,32 @@
mDrawables = dr = new Drawables();
}
+ if (dr.mDrawableLeft != left && dr.mDrawableLeft != null) {
+ dr.mDrawableLeft.setCallback(null);
+ }
dr.mDrawableLeft = left;
+ if (dr.mDrawableTop != left && dr.mDrawableTop != null) {
+ dr.mDrawableTop.setCallback(null);
+ }
dr.mDrawableTop = top;
+ if (dr.mDrawableRight != left && dr.mDrawableRight != null) {
+ dr.mDrawableRight.setCallback(null);
+ }
dr.mDrawableRight = right;
+ if (dr.mDrawableBottom != left && dr.mDrawableBottom != null) {
+ dr.mDrawableBottom.setCallback(null);
+ }
dr.mDrawableBottom = bottom;
final Rect compoundRect = dr.mCompoundRect;
- int[] state = null;
+ int[] state;
state = getDrawableState();
if (left != null) {
left.setState(state);
left.copyBounds(compoundRect);
+ left.setCallback(this);
dr.mDrawableSizeLeft = compoundRect.width();
dr.mDrawableHeightLeft = compoundRect.height();
} else {
@@ -1366,6 +1383,7 @@
if (right != null) {
right.setState(state);
right.copyBounds(compoundRect);
+ right.setCallback(this);
dr.mDrawableSizeRight = compoundRect.width();
dr.mDrawableHeightRight = compoundRect.height();
} else {
@@ -1375,6 +1393,7 @@
if (top != null) {
top.setState(state);
top.copyBounds(compoundRect);
+ top.setCallback(this);
dr.mDrawableSizeTop = compoundRect.height();
dr.mDrawableWidthTop = compoundRect.width();
} else {
@@ -1384,6 +1403,7 @@
if (bottom != null) {
bottom.setState(state);
bottom.copyBounds(compoundRect);
+ bottom.setCallback(this);
dr.mDrawableSizeBottom = compoundRect.height();
dr.mDrawableWidthBottom = compoundRect.width();
} else {
@@ -3681,6 +3701,54 @@
}
@Override
+ public void invalidateDrawable(Drawable drawable) {
+ if (verifyDrawable(drawable)) {
+ final Rect dirty = drawable.getBounds();
+ int scrollX = mScrollX;
+ int scrollY = mScrollY;
+
+ // IMPORTANT: The coordinates below are based on the coordinates computed
+ // for each compound drawable in onDraw(). Make sure to update each section
+ // accordingly.
+ final TextView.Drawables drawables = mDrawables;
+ if (drawables != null) {
+ if (drawable == drawables.mDrawableLeft) {
+ final int compoundPaddingTop = getCompoundPaddingTop();
+ final int compoundPaddingBottom = getCompoundPaddingBottom();
+ final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
+
+ scrollX += mPaddingLeft;
+ scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightLeft) / 2;
+ } else if (drawable == drawables.mDrawableRight) {
+ final int compoundPaddingTop = getCompoundPaddingTop();
+ final int compoundPaddingBottom = getCompoundPaddingBottom();
+ final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
+
+ scrollX += (mRight - mLeft - mPaddingRight - drawables.mDrawableSizeRight);
+ scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightRight) / 2;
+ } else if (drawable == drawables.mDrawableTop) {
+ final int compoundPaddingLeft = getCompoundPaddingLeft();
+ final int compoundPaddingRight = getCompoundPaddingRight();
+ final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft;
+
+ scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthTop) / 2;
+ scrollY += mPaddingTop;
+ } else if (drawable == drawables.mDrawableBottom) {
+ final int compoundPaddingLeft = getCompoundPaddingLeft();
+ final int compoundPaddingRight = getCompoundPaddingRight();
+ final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft;
+
+ scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthBottom) / 2;
+ scrollY += (mBottom - mTop - mPaddingBottom - drawables.mDrawableSizeBottom);
+ }
+ }
+
+ invalidate(dirty.left + scrollX, dirty.top + scrollY,
+ dirty.right + scrollX, dirty.bottom + scrollY);
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
restartMarqueeIfNeeded();
@@ -3708,6 +3776,8 @@
int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableLeft != null) {
canvas.save();
canvas.translate(scrollX + mPaddingLeft,
@@ -3717,6 +3787,8 @@
canvas.restore();
}
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableRight != null) {
canvas.save();
canvas.translate(scrollX + right - left - mPaddingRight - dr.mDrawableSizeRight,
@@ -3725,6 +3797,8 @@
canvas.restore();
}
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableTop != null) {
canvas.save();
canvas.translate(scrollX + compoundPaddingLeft + (hspace - dr.mDrawableWidthTop) / 2,
@@ -3733,6 +3807,8 @@
canvas.restore();
}
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableBottom != null) {
canvas.save();
canvas.translate(scrollX + compoundPaddingLeft +
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index e1ff2a5..ce32754 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -18,6 +18,8 @@
import com.android.internal.os.BatteryStatsImpl;
+import android.telephony.SignalStrength;
+
interface IBatteryStats {
byte[] getStatistics();
void noteStartWakelock(int uid, String name, int type);
@@ -33,7 +35,7 @@
void noteUserActivity(int uid, int event);
void notePhoneOn();
void notePhoneOff();
- void notePhoneSignalStrength(int asu);
+ void notePhoneSignalStrength(in SignalStrength signalStrength);
void notePhoneDataConnectionState(int dataType, boolean hasData);
void noteWifiOn(int uid);
void noteWifiOff(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e8356a2..bf9bc4e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -23,6 +23,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -54,7 +55,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 34;
+ private static final int VERSION = 35;
private final File mFile;
private final File mBackupFile;
@@ -982,14 +983,25 @@
}
}
- public void notePhoneSignalStrengthLocked(int asu) {
+ public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
// Bin the strength.
int bin;
- if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
- else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD;
- else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE;
- else bin = SIGNAL_STRENGTH_POOR;
+
+ if (!signalStrength.isGsm()) {
+ int dBm = signalStrength.getCdmaDbm();
+ if (dBm >= -75) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ else if (dBm >= -85) bin = SIGNAL_STRENGTH_GREAT;
+ else if (dBm >= -95) bin = SIGNAL_STRENGTH_GOOD;
+ else if (dBm >= -100) bin = SIGNAL_STRENGTH_MODERATE;
+ else bin = SIGNAL_STRENGTH_POOR;
+ } else {
+ int asu = signalStrength.getGsmSignalStrength();
+ if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
+ else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD;
+ else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE;
+ else bin = SIGNAL_STRENGTH_POOR;
+ }
if (mPhoneSignalStrengthBin != bin) {
if (mPhoneSignalStrengthBin >= 0) {
mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java
index 871c925..922f5be 100644
--- a/core/java/com/google/android/net/GoogleHttpClient.java
+++ b/core/java/com/google/android/net/GoogleHttpClient.java
@@ -37,6 +37,10 @@
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.LayeredSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.impl.client.EntityEnclosingRequestWrapper;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.params.HttpParams;
@@ -44,6 +48,8 @@
import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
@@ -66,25 +72,22 @@
private final AndroidHttpClient mClient;
private final ContentResolver mResolver;
- private final String mUserAgent;
+ private final String mAppName, mUserAgent;
+ private final ThreadLocal<Boolean> mConnectionAllocated = new ThreadLocal<Boolean>();
/**
- * Create an HTTP client. Normally one client is shared throughout an app.
- * @param resolver to use for accessing URL rewriting rules.
- * @param userAgent to report in your HTTP requests.
- * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)}
+ * Create an HTTP client without SSL session persistence.
+ * @deprecated Use {@link #GoogleHttpClient(android.content.Context, String, boolean)}
*/
public GoogleHttpClient(ContentResolver resolver, String userAgent) {
mClient = AndroidHttpClient.newInstance(userAgent);
mResolver = resolver;
- mUserAgent = userAgent;
+ mUserAgent = mAppName = userAgent;
}
/**
- * GoogleHttpClient(Context, String, boolean) - without SSL session
- * persistence.
- *
- * @deprecated use Context instead of ContentResolver.
+ * Create an HTTP client without SSL session persistence.
+ * @deprecated Use {@link #GoogleHttpClient(android.content.Context, String, boolean)}
*/
public GoogleHttpClient(ContentResolver resolver, String appAndVersion,
boolean gzipCapable) {
@@ -111,21 +114,72 @@
* headers. Needed because Google servers require gzip in the User-Agent
* in order to return gzip'd content.
*/
- public GoogleHttpClient(Context context, String appAndVersion,
- boolean gzipCapable) {
- this(context.getContentResolver(), SSLClientSessionCacheFactory.getCache(context),
+ public GoogleHttpClient(Context context, String appAndVersion, boolean gzipCapable) {
+ this(context.getContentResolver(),
+ SSLClientSessionCacheFactory.getCache(context),
appAndVersion, gzipCapable);
}
- private GoogleHttpClient(ContentResolver resolver, SSLClientSessionCache cache,
+ private GoogleHttpClient(ContentResolver resolver,
+ SSLClientSessionCache cache,
String appAndVersion, boolean gzipCapable) {
String userAgent = appAndVersion + " (" + Build.DEVICE + " " + Build.ID + ")";
if (gzipCapable) {
userAgent = userAgent + "; gzip";
}
+
mClient = AndroidHttpClient.newInstance(userAgent, cache);
mResolver = resolver;
+ mAppName = appAndVersion;
mUserAgent = userAgent;
+
+ // Wrap all the socket factories with the appropriate wrapper. (Apache
+ // HTTP, curse its black and stupid heart, inspects the SocketFactory to
+ // see if it's a LayeredSocketFactory, so we need two wrapper classes.)
+ SchemeRegistry registry = getConnectionManager().getSchemeRegistry();
+ for (String name : registry.getSchemeNames()) {
+ Scheme scheme = registry.unregister(name);
+ SocketFactory sf = scheme.getSocketFactory();
+ if (sf instanceof LayeredSocketFactory) {
+ sf = new WrappedLayeredSocketFactory((LayeredSocketFactory) sf);
+ } else {
+ sf = new WrappedSocketFactory(sf);
+ }
+ registry.register(new Scheme(name, sf, scheme.getDefaultPort()));
+ }
+ }
+
+ /**
+ * Delegating wrapper for SocketFactory records when sockets are connected.
+ * We use this to know whether a connection was created vs reused, to
+ * gather per-app statistics about connection reuse rates.
+ * (Note, we record only *connection*, not *creation* of sockets --
+ * what we care about is the network overhead of an actual TCP connect.)
+ */
+ private class WrappedSocketFactory implements SocketFactory {
+ private SocketFactory mDelegate;
+ private WrappedSocketFactory(SocketFactory delegate) { mDelegate = delegate; }
+ public final Socket createSocket() throws IOException { return mDelegate.createSocket(); }
+ public final boolean isSecure(Socket s) { return mDelegate.isSecure(s); }
+
+ public final Socket connectSocket(
+ Socket s, String h, int p,
+ InetAddress la, int lp, HttpParams params) throws IOException {
+ mConnectionAllocated.set(Boolean.TRUE);
+ return mDelegate.connectSocket(s, h, p, la, lp, params);
+ }
+ }
+
+ /** Like WrappedSocketFactory, but for the LayeredSocketFactory subclass. */
+ private class WrappedLayeredSocketFactory
+ extends WrappedSocketFactory implements LayeredSocketFactory {
+ private LayeredSocketFactory mDelegate;
+ private WrappedLayeredSocketFactory(LayeredSocketFactory sf) { super(sf); mDelegate = sf; }
+
+ public final Socket createSocket(Socket s, String host, int port, boolean autoClose)
+ throws IOException {
+ return mDelegate.createSocket(s, host, port, autoClose);
+ }
}
/**
@@ -140,24 +194,21 @@
public HttpResponse executeWithoutRewriting(
HttpUriRequest request, HttpContext context)
throws IOException {
- String code = "Error";
+ int code = -1;
long start = SystemClock.elapsedRealtime();
try {
HttpResponse response;
- // TODO: if we're logging network stats, and if the apache library is configured
- // to follow redirects, count each redirect as an additional round trip.
+ mConnectionAllocated.set(null);
- // see if we're logging network stats.
- boolean logNetworkStats = NetworkStatsEntity.shouldLogNetworkStats();
+ if (NetworkStatsEntity.shouldLogNetworkStats()) {
+ // TODO: if we're logging network stats, and if the apache library is configured
+ // to follow redirects, count each redirect as an additional round trip.
- if (logNetworkStats) {
int uid = android.os.Process.myUid();
long startTx = NetStat.getUidTxBytes(uid);
long startRx = NetStat.getUidRxBytes(uid);
response = mClient.execute(request, context);
- code = Integer.toString(response.getStatusLine().getStatusCode());
-
HttpEntity origEntity = response == null ? null : response.getEntity();
if (origEntity != null) {
// yeah, we compute the same thing below. we do need to compute this here
@@ -165,30 +216,39 @@
long now = SystemClock.elapsedRealtime();
long elapsed = now - start;
NetworkStatsEntity entity = new NetworkStatsEntity(origEntity,
- mUserAgent, uid, startTx, startRx,
+ mAppName, uid, startTx, startRx,
elapsed /* response latency */, now /* processing start time */);
response.setEntity(entity);
}
} else {
response = mClient.execute(request, context);
- code = Integer.toString(response.getStatusLine().getStatusCode());
}
+ code = response.getStatusLine().getStatusCode();
return response;
- } catch (IOException e) {
- code = "IOException";
- throw e;
} finally {
// Record some statistics to the checkin service about the outcome.
// Note that this is only describing execute(), not body download.
+ // We assume the database writes are much faster than network I/O,
+ // and not worth running in a background thread or anything.
try {
long elapsed = SystemClock.elapsedRealtime() - start;
ContentValues values = new ContentValues();
- values.put(Checkin.Stats.TAG,
- Checkin.Stats.Tag.HTTP_STATUS + ":" +
- mUserAgent + ":" + code);
values.put(Checkin.Stats.COUNT, 1);
values.put(Checkin.Stats.SUM, elapsed / 1000.0);
+
+ values.put(Checkin.Stats.TAG, Checkin.Stats.Tag.HTTP_REQUEST + ":" + mAppName);
+ mResolver.insert(Checkin.Stats.CONTENT_URI, values);
+
+ // No sockets and no exceptions means we successfully reused a connection
+ if (mConnectionAllocated.get() == null && code >= 0) {
+ values.put(Checkin.Stats.TAG, Checkin.Stats.Tag.HTTP_REUSED + ":" + mAppName);
+ mResolver.insert(Checkin.Stats.CONTENT_URI, values);
+ }
+
+ String status = code < 0 ? "IOException" : Integer.toString(code);
+ values.put(Checkin.Stats.TAG,
+ Checkin.Stats.Tag.HTTP_STATUS + ":" + mAppName + ":" + status);
mResolver.insert(Checkin.Stats.CONTENT_URI, values);
} catch (Exception e) {
Log.e(TAG, "Error recording stats", e);
diff --git a/core/jni/ActivityManager.cpp b/core/jni/ActivityManager.cpp
index 9017827..8950dfb 100644
--- a/core/jni/ActivityManager.cpp
+++ b/core/jni/ActivityManager.cpp
@@ -16,9 +16,9 @@
#include <unistd.h>
#include <android_runtime/ActivityManager.h>
-#include <utils/IBinder.h>
-#include <utils/IServiceManager.h>
-#include <utils/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
namespace android {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 702ea87..c07748e 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -104,7 +104,6 @@
android_util_FileObserver.cpp \
android/opengl/poly_clip.cpp.arm \
android/opengl/util.cpp.arm \
- android_bluetooth_Database.cpp \
android_bluetooth_HeadsetBase.cpp \
android_bluetooth_common.cpp \
android_bluetooth_BluetoothAudioGateway.cpp \
@@ -118,6 +117,7 @@
android_location_GpsLocationProvider.cpp \
com_android_internal_os_ZygoteInit.cpp \
com_android_internal_graphics_NativeUtils.cpp \
+ android_backup_BackupDataOutput.cpp \
android_backup_FileBackupHelper.cpp
LOCAL_C_INCLUDES += \
@@ -147,6 +147,7 @@
libnativehelper \
libcutils \
libutils \
+ libbinder \
libnetutils \
libui \
libskiagl \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d1e87f3..144bf5d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -19,11 +19,11 @@
//#define LOG_NDEBUG 0
#include <android_runtime/AndroidRuntime.h>
-#include <utils/IBinder.h>
-#include <utils/IServiceManager.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <utils/misc.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/string_array.h>
#include <utils/threads.h>
#include <cutils/properties.h>
@@ -142,7 +142,6 @@
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_KeyCharacterMap(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
-extern int register_android_bluetooth_Database(JNIEnv* env);
extern int register_android_bluetooth_HeadsetBase(JNIEnv* env);
extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
extern int register_android_bluetooth_RfcommSocket(JNIEnv *env);
@@ -154,6 +153,7 @@
extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
extern int register_android_util_Base64(JNIEnv* env);
extern int register_android_location_GpsLocationProvider(JNIEnv* env);
+extern int register_android_backup_BackupDataOutput(JNIEnv *env);
extern int register_android_backup_FileBackupHelper(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -1157,7 +1157,6 @@
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
- REG_JNI(register_android_bluetooth_Database),
REG_JNI(register_android_bluetooth_HeadsetBase),
REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
REG_JNI(register_android_bluetooth_RfcommSocket),
@@ -1169,6 +1168,7 @@
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_util_Base64),
REG_JNI(register_android_location_GpsLocationProvider),
+ REG_JNI(register_android_backup_BackupDataOutput),
REG_JNI(register_android_backup_FileBackupHelper),
};
diff --git a/core/jni/CursorWindow.cpp b/core/jni/CursorWindow.cpp
index fb891c9..7864189 100644
--- a/core/jni/CursorWindow.cpp
+++ b/core/jni/CursorWindow.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "CursorWindow"
#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <assert.h>
#include <string.h>
diff --git a/core/jni/CursorWindow.h b/core/jni/CursorWindow.h
index 0fb074f..e98b009 100644
--- a/core/jni/CursorWindow.h
+++ b/core/jni/CursorWindow.h
@@ -21,7 +21,7 @@
#include <stddef.h>
#include <stdint.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <utils/RefBase.h>
#include <jni.h>
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 65f44d5..29d8d3c 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -5,7 +5,7 @@
#include "SkDither.h"
#include "SkUnPreMultiply.h"
-#include "Parcel.h"
+#include <binder/Parcel.h>
#include "android_util_Binder.h"
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index 1dc0314..723cd37 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -134,7 +134,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#include "Parcel.h"
+#include <binder/Parcel.h>
#include "android_util_Binder.h"
static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
new file mode 100644
index 0000000..8fce2a2
--- /dev/null
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FileBackupHelper_native"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/backup_helpers.h>
+
+namespace android
+{
+
+static jfieldID s_descriptorField = 0;
+
+static int
+ctor_native(JNIEnv* env, jobject This, jobject fileDescriptor)
+{
+ int err;
+
+ int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+ if (fd == -1) {
+ return NULL;
+ }
+
+ return (int)new BackupDataWriter(fd);
+}
+
+static void
+dtor_native(JNIEnv* env, jobject This, int fd)
+{
+ delete (BackupDataWriter*)fd;
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
+ { "dtor", "(I)V", (void*)dtor_native },
+};
+
+int register_android_backup_BackupDataOutput(JNIEnv* env)
+{
+ LOGD("register_android_backup_BackupDataOutput");
+
+ jclass clazz;
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
+ s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
+ LOG_FATAL_IF(s_descriptorField == NULL,
+ "Unable to find descriptor field in java.io.FileDescriptor");
+
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupDataOutput",
+ g_methods, NELEM(g_methods));
+}
+
+}
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
index c6de3a5..a05d812 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelper.cpp
@@ -28,7 +28,7 @@
static jfieldID s_descriptorField = 0;
static int
-performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, jobject data,
+performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, int data,
jobject newState, jobjectArray files)
{
int err;
@@ -37,7 +37,7 @@
LOGD("oldState=%p newState=%p data=%p\n", oldState, newState, data);
int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
int newStateFD = env->GetIntField(newState, s_descriptorField);
- int dataFD = env->GetIntField(data, s_descriptorField);
+ BackupDataWriter* dataStream = (BackupDataWriter*)data;
char const* basePathUTF = env->GetStringUTFChars(basePath, NULL);
LOGD("basePathUTF=\"%s\"\n", basePathUTF);
@@ -47,7 +47,7 @@
filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL);
}
- err = back_up_files(oldStateFD, dataFD, newStateFD, basePathUTF, filesUTF, fileCount);
+ err = back_up_files(oldStateFD, dataStream, newStateFD, basePathUTF, filesUTF, fileCount);
for (int i=0; i<fileCount; i++) {
env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]);
@@ -60,8 +60,7 @@
static const JNINativeMethod g_methods[] = {
{ "performBackup_native",
- "(Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
- "Ljava/io/FileDescriptor;[Ljava/lang/String;)I",
+ "(Ljava/lang/String;Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;)I",
(void*)performBackup_native },
};
diff --git a/core/jni/android_bluetooth_Database.cpp b/core/jni/android_bluetooth_Database.cpp
deleted file mode 100644
index 136c9a3..0000000
--- a/core/jni/android_bluetooth_Database.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#define DBUS_CLASS_NAME BLUEZ_DBUS_BASE_IFC ".Database"
-#define LOG_TAG "bluetooth_Database.cpp"
-
-#include "android_bluetooth_common.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "JNIHelp.h"
-#include "jni.h"
-#include "utils/Log.h"
-
-#ifdef HAVE_BLUETOOTH
-#include <dbus/dbus.h>
-#endif
-
-namespace android {
-
-#ifdef HAVE_BLUETOOTH
-static DBusConnection* conn = NULL; // Singleton thread-safe connection
-#endif
-
-static void classInitNative(JNIEnv* env, jclass clazz) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- conn = NULL;
-#endif
-}
-
-static void initializeNativeDataNative(JNIEnv* env, jobject object) {
- LOGV(__FUNCTION__);
-
-#ifdef HAVE_BLUETOOTH
- if (conn == NULL) {
- DBusError err;
- dbus_error_init(&err);
- dbus_threads_init_default();
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_error_is_set(&err)) {
- LOGE("Could not get onto the system bus!");
- dbus_error_free(&err);
- }
- }
-#endif
-}
-
-static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
- LOGV(__FUNCTION__);
-}
-
-static jint addServiceRecordNative(JNIEnv *env, jobject object,
- jbyteArray record) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- if (conn != NULL) {
- jbyte* c_record = env->GetByteArrayElements(record, NULL);
- DBusMessage *reply = dbus_func_args(env,
- conn,
- BLUEZ_DBUS_BASE_PATH,
- DBUS_CLASS_NAME,
- "AddServiceRecord",
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &c_record,
- env->GetArrayLength(record),
- DBUS_TYPE_INVALID);
- env->ReleaseByteArrayElements(record, c_record, JNI_ABORT);
- return reply ? dbus_returns_uint32(env, reply) : -1;
- }
-#endif
- return -1;
-}
-
-static jint addServiceRecordFromXmlNative(JNIEnv *env, jobject object,
- jstring record) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- if (conn != NULL) {
- const char *c_record = env->GetStringUTFChars(record, NULL);
- DBusMessage *reply = dbus_func_args(env,
- conn,
- BLUEZ_DBUS_BASE_PATH,
- DBUS_CLASS_NAME,
- "AddServiceRecordFromXML",
- DBUS_TYPE_STRING, &c_record,
- DBUS_TYPE_INVALID);
- env->ReleaseStringUTFChars(record, c_record);
- return reply ? dbus_returns_uint32(env, reply) : -1;
- }
-#endif
- return -1;
-}
-
-static void updateServiceRecordNative(JNIEnv *env, jobject object,
- jint handle,
- jbyteArray record) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- if (conn != NULL) {
- jbyte* c_record = env->GetByteArrayElements(record, NULL);
- DBusMessage *reply = dbus_func_args(env,
- conn,
- BLUEZ_DBUS_BASE_PATH,
- DBUS_CLASS_NAME,
- "UpdateServiceRecord",
- DBUS_TYPE_UINT32, &handle,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &c_record,
- env->GetArrayLength(record),
- DBUS_TYPE_INVALID);
- env->ReleaseByteArrayElements(record, c_record, JNI_ABORT);
- }
-#endif
-}
-
-static void updateServiceRecordFromXmlNative(JNIEnv *env, jobject object,
- jint handle,
- jstring record) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- if (conn != NULL) {
- const char *c_record = env->GetStringUTFChars(record, NULL);
- DBusMessage *reply = dbus_func_args(env,
- conn,
- BLUEZ_DBUS_BASE_PATH,
- DBUS_CLASS_NAME,
- "UpdateServiceRecordFromXML",
- DBUS_TYPE_UINT32, &handle,
- DBUS_TYPE_STRING, &c_record,
- DBUS_TYPE_INVALID);
- env->ReleaseStringUTFChars(record, c_record);
- }
-#endif
-}
-
-/* private static native void removeServiceRecordNative(int handle); */
-static void removeServiceRecordNative(JNIEnv *env, jobject object,
- jint handle) {
- LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
- if (conn != NULL) {
- DBusMessage *reply = dbus_func_args(env,
- conn,
- BLUEZ_DBUS_BASE_PATH,
- DBUS_CLASS_NAME,
- "RemoveServiceRecord",
- DBUS_TYPE_UINT32, &handle,
- DBUS_TYPE_INVALID);
- }
-#endif
-}
-
-
-static JNINativeMethod sMethods[] = {
- /* name, signature, funcPtr */
- {"classInitNative", "()V", (void*)classInitNative},
- {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
- {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
- {"addServiceRecordNative", "([B)I", (void*)addServiceRecordNative},
- {"addServiceRecordFromXmlNative", "(Ljava/lang/String;)I", (void*)addServiceRecordFromXmlNative},
- {"updateServiceRecordNative", "(I[B)V", (void*)updateServiceRecordNative},
- {"updateServiceRecordFromXmlNative", "(ILjava/lang/String;)V", (void*)updateServiceRecordFromXmlNative},
- {"removeServiceRecordNative", "(I)V", (void*)removeServiceRecordNative},
-};
-
-int register_android_bluetooth_Database(JNIEnv *env) {
- return AndroidRuntime::registerNativeMethods(env,
- "android/bluetooth/Database", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index c107993..31086b8 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -25,7 +25,7 @@
#include <ui/Surface.h>
#include <ui/Camera.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
using namespace android;
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index 004b0e3..0858741 100644
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -176,7 +176,7 @@
{
int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency));
if (result) {
- return result;
+ return false;
}
return (sGpsInterface->start() == 0);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 42ada54..0cce3a6 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -30,8 +30,8 @@
#include "media/AudioSystem.h"
#include "media/AudioTrack.h"
-#include <utils/MemoryHeapBase.h>
-#include <utils/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 482d8eb..2685d75 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -133,6 +133,19 @@
commit ? 0 : JNI_ABORT);
}
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf += position << elementSizeShift;
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ return (void*) buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
@@ -305,9 +318,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -2779,9 +2791,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3034,9 +3045,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3392,9 +3402,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index 923e1aa..7c208e9 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -44,6 +44,7 @@
static jfieldID g_shortMonthsField = 0;
static jfieldID g_longMonthsField = 0;
+static jfieldID g_longStandaloneMonthsField = 0;
static jfieldID g_shortWeekdaysField = 0;
static jfieldID g_longWeekdaysField = 0;
static jfieldID g_timeOnlyFormatField = 0;
@@ -193,6 +194,7 @@
static jobject js_locale_previous = NULL;
static struct strftime_locale locale;
static jstring js_mon[12], js_month[12], js_wday[7], js_weekday[7];
+ static jstring js_standalone_month[12];
static jstring js_X_fmt, js_x_fmt, js_c_fmt, js_am, js_pm, js_date_fmt;
Time t;
@@ -206,8 +208,10 @@
for (int i = 0; i < 12; i++) {
env->ReleaseStringUTFChars(js_mon[i], locale.mon[i]);
env->ReleaseStringUTFChars(js_month[i], locale.month[i]);
+ env->ReleaseStringUTFChars(js_standalone_month[i], locale.standalone_month[i]);
env->DeleteGlobalRef(js_mon[i]);
env->DeleteGlobalRef(js_month[i]);
+ env->DeleteGlobalRef(js_standalone_month[i]);
}
for (int i = 0; i < 7; i++) {
@@ -245,6 +249,12 @@
locale.month[i] = env->GetStringUTFChars(js_month[i], NULL);
}
+ ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField);
+ for (int i = 0; i < 12; i++) {
+ js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
+ locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL);
+ }
+
ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField);
for (int i = 0; i < 7; i++) {
js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
@@ -639,6 +649,7 @@
g_shortMonthsField = env->GetStaticFieldID(timeClass, "sShortMonths", "[Ljava/lang/String;");
g_longMonthsField = env->GetStaticFieldID(timeClass, "sLongMonths", "[Ljava/lang/String;");
+ g_longStandaloneMonthsField = env->GetStaticFieldID(timeClass, "sLongStandaloneMonths", "[Ljava/lang/String;");
g_shortWeekdaysField = env->GetStaticFieldID(timeClass, "sShortWeekdays", "[Ljava/lang/String;");
g_longWeekdaysField = env->GetStaticFieldID(timeClass, "sLongWeekdays", "[Ljava/lang/String;");
g_timeOnlyFormatField = env->GetStaticFieldID(timeClass, "sTimeOnlyFormat", "Ljava/lang/String;");
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 7325432..f0885fd 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -25,12 +25,12 @@
#include <stdio.h>
#include <utils/Atomic.h>
-#include <utils/IInterface.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/jni/android_util_Binder.h b/core/jni/android_util_Binder.h
index 16d993d..495e76a 100644
--- a/core/jni/android_util_Binder.h
+++ b/core/jni/android_util_Binder.h
@@ -15,7 +15,7 @@
** limitations under the License.
*/
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
#include "jni.h"
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index d760feb..e8bffa4 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -18,9 +18,9 @@
#define LOG_TAG "Process"
#include <utils/Log.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -236,6 +236,36 @@
signalExceptionForGroupError(env, clazz, errno);
}
+void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
+{
+ DIR *d;
+ FILE *fp;
+ char proc_path[255];
+ struct dirent *de;
+
+ if (grp > ANDROID_TGROUP_MAX || grp < 0) {
+ signalExceptionForGroupError(env, clazz, EINVAL);
+ return;
+ }
+
+ sprintf(proc_path, "/proc/%d/task", pid);
+ if (!(d = opendir(proc_path))) {
+ signalExceptionForGroupError(env, clazz, errno);
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+ if (add_pid_to_cgroup(atoi(de->d_name), grp)) {
+ signalExceptionForGroupError(env, clazz, errno);
+ closedir(d);
+ return;
+ }
+ }
+ closedir(d);
+}
+
void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
jint pid, jint pri)
{
@@ -820,6 +850,7 @@
{"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
{"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
+ {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
{"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj},
{"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
{"setUid", "(I)I", (void*)android_os_Process_setUid},
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 11822e0..15e3a81 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -133,6 +133,19 @@
commit ? 0 : JNI_ABORT);
}
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf += position << elementSizeShift;
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ return (void*) buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
@@ -305,9 +318,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -2779,9 +2791,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3034,9 +3045,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
@@ -3392,9 +3402,8 @@
GLvoid *pointer = (GLvoid *) 0;
if (pointer_buf) {
- pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf);
+ pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf);
if ( ! pointer ) {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
return;
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 05fbe64..b97e07b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -220,12 +220,6 @@
android:label="@string/permlab_installLocationProvider"
android:description="@string/permdesc_installLocationProvider" />
- <!-- Allows an application to install a location collector into the Location Manager -->
- <permission android:name="android.permission.INSTALL_LOCATION_COLLECTOR"
- android:protectionLevel="signatureOrSystem"
- android:label="@string/permlab_installLocationCollector"
- android:description="@string/permdesc_installLocationCollector" />
-
<!-- ======================================= -->
<!-- Permissions for accessing networks -->
<!-- ======================================= -->
@@ -389,11 +383,11 @@
android:description="@string/permgroupdesc_storage" />
<!-- Allows an application to write to the SD card -->
- <permission android:name="android.permission.SDCARD_WRITE"
+ <permission android:name="android.permission.WRITE_SDCARD"
android:permissionGroup="android.permission-group.STORAGE"
android:label="@string/permlab_sdcardWrite"
android:description="@string/permdesc_sdcardWrite"
- android:protectionLevel="normal" />
+ android:protectionLevel="dangerous" />
<!-- ============================================ -->
<!-- Permissions for low-level system interaction -->
@@ -803,14 +797,22 @@
android:description="@string/permdesc_runSetActivityWatcher"
android:protectionLevel="signature" />
- <!-- Allows an application to watch and control how activities are
- started globally in the system. Only for is in debugging
- (usually the monkey command). -->
+ <!-- Allows an application to call the activity manager shutdown() API
+ to put the higher-level system there into a shutdown state. -->
<permission android:name="android.permission.SHUTDOWN"
android:label="@string/permlab_shutdown"
android:description="@string/permdesc_shutdown"
android:protectionLevel="signature" />
+ <!-- Allows an application to tell the activity manager to temporarily
+ stop application switches, putting it into a special mode that
+ prevents applications from immediately switching away from some
+ critical UI such as the home screen. -->
+ <permission android:name="android.permission.STOP_APP_SWITCHES"
+ android:label="@string/permlab_stopAppSwitches"
+ android:description="@string/permdesc_stopAppSwitches"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to retrieve the current state of keys and
switches. This is only for use by the system.-->
<permission android:name="android.permission.READ_INPUT_STATE"
@@ -973,7 +975,7 @@
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:label="@string/permlab_bindGadget"
android:description="@string/permdesc_bindGadget"
- android:protectionLevel="signature" />
+ android:protectionLevel="signatureOrSystem" />
<!-- Allows applications to change the background data setting
@hide pending API council -->
diff --git a/core/res/res/drawable/search_spinner.xml b/core/res/res/drawable/search_spinner.xml
new file mode 100644
index 0000000..34c163d
--- /dev/null
+++ b/core/res/res/drawable/search_spinner.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:drawable="@drawable/search_spinner_anim1" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim2" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim3" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim4" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim5" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim6" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim7" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim8" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim9" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim10" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim11" android:duration="150" />
+ <item android:drawable="@drawable/search_spinner_anim12" android:duration="150" />
+</animation-list>
+
diff --git a/core/res/res/drawable/search_spinner_anim1.png b/core/res/res/drawable/search_spinner_anim1.png
new file mode 100755
index 0000000..e55b60d
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim1.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim10.png b/core/res/res/drawable/search_spinner_anim10.png
new file mode 100755
index 0000000..9611d97
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim10.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim11.png b/core/res/res/drawable/search_spinner_anim11.png
new file mode 100755
index 0000000..4261704
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim11.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim12.png b/core/res/res/drawable/search_spinner_anim12.png
new file mode 100755
index 0000000..0602314
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim12.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim2.png b/core/res/res/drawable/search_spinner_anim2.png
new file mode 100755
index 0000000..05d58e0
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim2.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim3.png b/core/res/res/drawable/search_spinner_anim3.png
new file mode 100755
index 0000000..69fa9c1
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim3.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim4.png b/core/res/res/drawable/search_spinner_anim4.png
new file mode 100755
index 0000000..9201bac
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim4.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim5.png b/core/res/res/drawable/search_spinner_anim5.png
new file mode 100755
index 0000000..f0c7101
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim5.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim6.png b/core/res/res/drawable/search_spinner_anim6.png
new file mode 100755
index 0000000..99d1d4e
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim6.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim7.png b/core/res/res/drawable/search_spinner_anim7.png
new file mode 100755
index 0000000..8ca3358
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim7.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim8.png b/core/res/res/drawable/search_spinner_anim8.png
new file mode 100755
index 0000000..408d723
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim8.png
Binary files differ
diff --git a/core/res/res/drawable/search_spinner_anim9.png b/core/res/res/drawable/search_spinner_anim9.png
new file mode 100755
index 0000000..42a2c65
--- /dev/null
+++ b/core/res/res/drawable/search_spinner_anim9.png
Binary files differ
diff --git a/core/res/res/drawable/stat_ecb_mode.png b/core/res/res/drawable/stat_ecb_mode.png
new file mode 100644
index 0000000..a948770
--- /dev/null
+++ b/core/res/res/drawable/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png
new file mode 100755
index 0000000..11c2eae
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_dormant_evdo.png b/core/res/res/drawable/stat_sys_data_dormant_evdo.png
new file mode 100755
index 0000000..811fcb5
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_dormant_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_0.png b/core/res/res/drawable/stat_sys_roaming_cdma_0.png
new file mode 100755
index 0000000..c61cce7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml
new file mode 100644
index 0000000..07dc446
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/stat_sys_battery.xml
+**
+** Copyright 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.
+*/
+-->
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim0" android:duration="800" />
+ <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim1" android:duration="1200" />
+</animation-list>
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png
new file mode 100755
index 0000000..d62502d
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png
new file mode 100755
index 0000000..c61cce7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_0.png b/core/res/res/drawable/stat_sys_signal_cdma_0.png
new file mode 100755
index 0000000..0ef7d53
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_1.png b/core/res/res/drawable/stat_sys_signal_cdma_1.png
new file mode 100755
index 0000000..f4839d4
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_2.png b/core/res/res/drawable/stat_sys_signal_cdma_2.png
new file mode 100755
index 0000000..e25a99c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_2.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_3.png b/core/res/res/drawable/stat_sys_signal_cdma_3.png
new file mode 100755
index 0000000..d828d99
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_3.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_4.png b/core/res/res/drawable/stat_sys_signal_cdma_4.png
new file mode 100755
index 0000000..53a31ea
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_4.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_0.png b/core/res/res/drawable/stat_sys_signal_evdo_0.png
new file mode 100755
index 0000000..1b8aec7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_1.png b/core/res/res/drawable/stat_sys_signal_evdo_1.png
new file mode 100755
index 0000000..7ce01fd
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_2.png b/core/res/res/drawable/stat_sys_signal_evdo_2.png
new file mode 100755
index 0000000..890cd59
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_3.png b/core/res/res/drawable/stat_sys_signal_evdo_3.png
new file mode 100755
index 0000000..712c640
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_4.png b/core/res/res/drawable/stat_sys_signal_evdo_4.png
new file mode 100755
index 0000000..f0537dd
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/layout/google_web_content_helper_layout.xml b/core/res/res/layout/google_web_content_helper_layout.xml
index 40f84bf..546c458 100644
--- a/core/res/res/layout/google_web_content_helper_layout.xml
+++ b/core/res/res/layout/google_web_content_helper_layout.xml
@@ -18,10 +18,28 @@
android:foregroundGravity="center"
android:measureAllChildren="false">
- <!-- Include the indeterminate progress dialog's layout. -->
- <include
- android:id="@+id/progressContainer"
- layout="@android:layout/progress_dialog" />
+ <LinearLayout android:id="@+id/progressContainer"
+ android:orientation="horizontal"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:baselineAligned="false"
+ android:paddingLeft="8dip"
+ android:paddingTop="10dip"
+ android:paddingRight="8dip"
+ android:paddingBottom="10dip">
+
+ <ProgressBar android:id="@android:id/progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:max="10000"
+ android:layout_marginRight="12dip" />
+
+ <TextView android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
<WebView
android:id="@+id/web"
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index b512490..7b7f8a6 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -71,6 +71,7 @@
android:layout_weight="1.0"
android:paddingLeft="8dip"
android:paddingRight="6dip"
+ android:drawablePadding="2dip"
android:singleLine="true"
android:inputType="text|textAutoComplete"
android:dropDownWidth="fill_parent"
diff --git a/core/res/res/raw/latin_lowercase b/core/res/res/raw/latin_lowercase
new file mode 100644
index 0000000..5c38b91
--- /dev/null
+++ b/core/res/res/raw/latin_lowercase
Binary files differ
diff --git a/core/res/res/values-ar-rEG/donottranslate-cldr.xml b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
new file mode 100644
index 0000000..1bbbdca
--- /dev/null
+++ b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">يناير</string>
+ <string name="month_long_standalone_february">فبراير</string>
+ <string name="month_long_standalone_march">مارس</string>
+ <string name="month_long_standalone_april">أبريل</string>
+ <string name="month_long_standalone_may">مايو</string>
+ <string name="month_long_standalone_june">يونيو</string>
+ <string name="month_long_standalone_july">يوليو</string>
+ <string name="month_long_standalone_august">أغسطس</string>
+ <string name="month_long_standalone_september">سبتمبر</string>
+ <string name="month_long_standalone_october">أكتوبر</string>
+ <string name="month_long_standalone_november">نوفمبر</string>
+ <string name="month_long_standalone_december">ديسمبر</string>
+
+ <string name="month_long_january">يناير</string>
+ <string name="month_long_february">فبراير</string>
+ <string name="month_long_march">مارس</string>
+ <string name="month_long_april">أبريل</string>
+ <string name="month_long_may">مايو</string>
+ <string name="month_long_june">يونيو</string>
+ <string name="month_long_july">يوليو</string>
+ <string name="month_long_august">أغسطس</string>
+ <string name="month_long_september">سبتمبر</string>
+ <string name="month_long_october">أكتوبر</string>
+ <string name="month_long_november">نوفمبر</string>
+ <string name="month_long_december">ديسمبر</string>
+
+ <string name="month_medium_january">يناير</string>
+ <string name="month_medium_february">فبراير</string>
+ <string name="month_medium_march">مارس</string>
+ <string name="month_medium_april">أبريل</string>
+ <string name="month_medium_may">مايو</string>
+ <string name="month_medium_june">يونيو</string>
+ <string name="month_medium_july">يوليو</string>
+ <string name="month_medium_august">أغسطس</string>
+ <string name="month_medium_september">سبتمبر</string>
+ <string name="month_medium_october">أكتوبر</string>
+ <string name="month_medium_november">نوفمبر</string>
+ <string name="month_medium_december">ديسمبر</string>
+
+ <string name="month_shortest_january">ي</string>
+ <string name="month_shortest_february">ف</string>
+ <string name="month_shortest_march">م</string>
+ <string name="month_shortest_april">أ</string>
+ <string name="month_shortest_may">و</string>
+ <string name="month_shortest_june">ن</string>
+ <string name="month_shortest_july">ل</string>
+ <string name="month_shortest_august">غ</string>
+ <string name="month_shortest_september">س</string>
+ <string name="month_shortest_october">ك</string>
+ <string name="month_shortest_november">ب</string>
+ <string name="month_shortest_december">د</string>
+
+ <string name="day_of_week_long_sunday">الأحد</string>
+ <string name="day_of_week_long_monday">الإثنين</string>
+ <string name="day_of_week_long_tuesday">الثلاثاء</string>
+ <string name="day_of_week_long_wednesday">الأربعاء</string>
+ <string name="day_of_week_long_thursday">الخميس</string>
+ <string name="day_of_week_long_friday">الجمعة</string>
+ <string name="day_of_week_long_saturday">السبت</string>
+
+ <string name="day_of_week_medium_sunday">أحد</string>
+ <string name="day_of_week_medium_monday">إثنين</string>
+ <string name="day_of_week_medium_tuesday">ثلاثاء</string>
+ <string name="day_of_week_medium_wednesday">أربعاء</string>
+ <string name="day_of_week_medium_thursday">خميس</string>
+ <string name="day_of_week_medium_friday">جمعة</string>
+ <string name="day_of_week_medium_saturday">سبت</string>
+
+ <string name="day_of_week_short_sunday">أحد</string>
+ <string name="day_of_week_short_monday">إثنين</string>
+ <string name="day_of_week_short_tuesday">ثلاثاء</string>
+ <string name="day_of_week_short_wednesday">أربعاء</string>
+ <string name="day_of_week_short_thursday">خميس</string>
+ <string name="day_of_week_short_friday">جمعة</string>
+ <string name="day_of_week_short_saturday">سبت</string>
+
+ <string name="day_of_week_shortest_sunday">ح</string>
+ <string name="day_of_week_shortest_monday">ن</string>
+ <string name="day_of_week_shortest_tuesday">ث</string>
+ <string name="day_of_week_shortest_wednesday">ر</string>
+ <string name="day_of_week_shortest_thursday">خ</string>
+ <string name="day_of_week_shortest_friday">ج</string>
+ <string name="day_of_week_shortest_saturday">س</string>
+
+ <string name="am">ص</string>
+ <string name="pm">م</string>
+ <string name="yesterday">أمس</string>
+ <string name="today">اليوم</string>
+ <string name="tomorrow">غدًا</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-e/%-m/%Y</string>
+ <string name="numeric_date_format">d/M/yyyy</string>
+ <string name="month_day_year">%-e %B، %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
new file mode 100644
index 0000000..608b3a7
--- /dev/null
+++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">януари</string>
+ <string name="month_long_standalone_february">февруари</string>
+ <string name="month_long_standalone_march">март</string>
+ <string name="month_long_standalone_april">април</string>
+ <string name="month_long_standalone_may">май</string>
+ <string name="month_long_standalone_june">юни</string>
+ <string name="month_long_standalone_july">юли</string>
+ <string name="month_long_standalone_august">август</string>
+ <string name="month_long_standalone_september">септември</string>
+ <string name="month_long_standalone_october">октомври</string>
+ <string name="month_long_standalone_november">ноември</string>
+ <string name="month_long_standalone_december">декември</string>
+
+ <string name="month_long_january">януари</string>
+ <string name="month_long_february">февруари</string>
+ <string name="month_long_march">март</string>
+ <string name="month_long_april">април</string>
+ <string name="month_long_may">май</string>
+ <string name="month_long_june">юни</string>
+ <string name="month_long_july">юли</string>
+ <string name="month_long_august">август</string>
+ <string name="month_long_september">септември</string>
+ <string name="month_long_october">октомври</string>
+ <string name="month_long_november">ноември</string>
+ <string name="month_long_december">декември</string>
+
+ <string name="month_medium_january">ян.</string>
+ <string name="month_medium_february">февр.</string>
+ <string name="month_medium_march">март</string>
+ <string name="month_medium_april">апр.</string>
+ <string name="month_medium_may">май</string>
+ <string name="month_medium_june">юни</string>
+ <string name="month_medium_july">юли</string>
+ <string name="month_medium_august">авг.</string>
+ <string name="month_medium_september">септ.</string>
+ <string name="month_medium_october">окт.</string>
+ <string name="month_medium_november">ноем.</string>
+ <string name="month_medium_december">дек.</string>
+
+ <string name="month_shortest_january">я</string>
+ <string name="month_shortest_february">ф</string>
+ <string name="month_shortest_march">м</string>
+ <string name="month_shortest_april">а</string>
+ <string name="month_shortest_may">м</string>
+ <string name="month_shortest_june">ю</string>
+ <string name="month_shortest_july">ю</string>
+ <string name="month_shortest_august">а</string>
+ <string name="month_shortest_september">с</string>
+ <string name="month_shortest_october">о</string>
+ <string name="month_shortest_november">н</string>
+ <string name="month_shortest_december">д</string>
+
+ <string name="day_of_week_long_sunday">неделя</string>
+ <string name="day_of_week_long_monday">понеделник</string>
+ <string name="day_of_week_long_tuesday">вторник</string>
+ <string name="day_of_week_long_wednesday">сряда</string>
+ <string name="day_of_week_long_thursday">четвъртък</string>
+ <string name="day_of_week_long_friday">петък</string>
+ <string name="day_of_week_long_saturday">събота</string>
+
+ <string name="day_of_week_medium_sunday">нд</string>
+ <string name="day_of_week_medium_monday">пн</string>
+ <string name="day_of_week_medium_tuesday">вт</string>
+ <string name="day_of_week_medium_wednesday">ср</string>
+ <string name="day_of_week_medium_thursday">чт</string>
+ <string name="day_of_week_medium_friday">пт</string>
+ <string name="day_of_week_medium_saturday">сб</string>
+
+ <string name="day_of_week_short_sunday">нд</string>
+ <string name="day_of_week_short_monday">пн</string>
+ <string name="day_of_week_short_tuesday">вт</string>
+ <string name="day_of_week_short_wednesday">ср</string>
+ <string name="day_of_week_short_thursday">чт</string>
+ <string name="day_of_week_short_friday">пт</string>
+ <string name="day_of_week_short_saturday">сб</string>
+
+ <string name="day_of_week_shortest_sunday">н</string>
+ <string name="day_of_week_shortest_monday">п</string>
+ <string name="day_of_week_shortest_tuesday">в</string>
+ <string name="day_of_week_shortest_wednesday">с</string>
+ <string name="day_of_week_shortest_thursday">ч</string>
+ <string name="day_of_week_shortest_friday">п</string>
+ <string name="day_of_week_shortest_saturday">с</string>
+
+ <string name="am">пр. об.</string>
+ <string name="pm">сл. об.</string>
+ <string name="yesterday">Вчера</string>
+ <string name="today">Днес</string>
+ <string name="tomorrow">Утре</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-ca-rES/donottranslate-cldr.xml b/core/res/res/values-ca-rES/donottranslate-cldr.xml
new file mode 100644
index 0000000..6ed2a88
--- /dev/null
+++ b/core/res/res/values-ca-rES/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">gener</string>
+ <string name="month_long_standalone_february">febrer</string>
+ <string name="month_long_standalone_march">març</string>
+ <string name="month_long_standalone_april">abril</string>
+ <string name="month_long_standalone_may">maig</string>
+ <string name="month_long_standalone_june">juny</string>
+ <string name="month_long_standalone_july">juliol</string>
+ <string name="month_long_standalone_august">agost</string>
+ <string name="month_long_standalone_september">setembre</string>
+ <string name="month_long_standalone_october">octubre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">desembre</string>
+
+ <string name="month_long_january">gener</string>
+ <string name="month_long_february">febrer</string>
+ <string name="month_long_march">març</string>
+ <string name="month_long_april">abril</string>
+ <string name="month_long_may">maig</string>
+ <string name="month_long_june">juny</string>
+ <string name="month_long_july">juliol</string>
+ <string name="month_long_august">agost</string>
+ <string name="month_long_september">setembre</string>
+ <string name="month_long_october">octubre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">desembre</string>
+
+ <string name="month_medium_january">gen.</string>
+ <string name="month_medium_february">febr.</string>
+ <string name="month_medium_march">març</string>
+ <string name="month_medium_april">abr.</string>
+ <string name="month_medium_may">maig</string>
+ <string name="month_medium_june">juny</string>
+ <string name="month_medium_july">jul.</string>
+ <string name="month_medium_august">ag.</string>
+ <string name="month_medium_september">set.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">des.</string>
+
+ <string name="month_shortest_january">g</string>
+ <string name="month_shortest_february">f</string>
+ <string name="month_shortest_march">m</string>
+ <string name="month_shortest_april">a</string>
+ <string name="month_shortest_may">m</string>
+ <string name="month_shortest_june">j</string>
+ <string name="month_shortest_july">j</string>
+ <string name="month_shortest_august">a</string>
+ <string name="month_shortest_september">s</string>
+ <string name="month_shortest_october">o</string>
+ <string name="month_shortest_november">n</string>
+ <string name="month_shortest_december">d</string>
+
+ <string name="day_of_week_long_sunday">diumenge</string>
+ <string name="day_of_week_long_monday">dilluns</string>
+ <string name="day_of_week_long_tuesday">dimarts</string>
+ <string name="day_of_week_long_wednesday">dimecres</string>
+ <string name="day_of_week_long_thursday">dijous</string>
+ <string name="day_of_week_long_friday">divendres</string>
+ <string name="day_of_week_long_saturday">dissabte</string>
+
+ <string name="day_of_week_medium_sunday">dg.</string>
+ <string name="day_of_week_medium_monday">dl.</string>
+ <string name="day_of_week_medium_tuesday">dt.</string>
+ <string name="day_of_week_medium_wednesday">dc.</string>
+ <string name="day_of_week_medium_thursday">dj.</string>
+ <string name="day_of_week_medium_friday">dv.</string>
+ <string name="day_of_week_medium_saturday">ds.</string>
+
+ <string name="day_of_week_short_sunday">dg.</string>
+ <string name="day_of_week_short_monday">dl.</string>
+ <string name="day_of_week_short_tuesday">dt.</string>
+ <string name="day_of_week_short_wednesday">dc.</string>
+ <string name="day_of_week_short_thursday">dj.</string>
+ <string name="day_of_week_short_friday">dv.</string>
+ <string name="day_of_week_short_saturday">ds.</string>
+
+ <string name="day_of_week_shortest_sunday">g</string>
+ <string name="day_of_week_shortest_monday">l</string>
+ <string name="day_of_week_shortest_tuesday">t</string>
+ <string name="day_of_week_shortest_wednesday">c</string>
+ <string name="day_of_week_shortest_thursday">j</string>
+ <string name="day_of_week_shortest_friday">v</string>
+ <string name="day_of_week_shortest_saturday">s</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">ahir</string>
+ <string name="today">avui</string>
+ <string name="tomorrow">demà</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B del %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
new file mode 100644
index 0000000..f477d56
--- /dev/null
+++ b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">leden</string>
+ <string name="month_long_standalone_february">únor</string>
+ <string name="month_long_standalone_march">březen</string>
+ <string name="month_long_standalone_april">duben</string>
+ <string name="month_long_standalone_may">květen</string>
+ <string name="month_long_standalone_june">červen</string>
+ <string name="month_long_standalone_july">červenec</string>
+ <string name="month_long_standalone_august">srpen</string>
+ <string name="month_long_standalone_september">září</string>
+ <string name="month_long_standalone_october">říjen</string>
+ <string name="month_long_standalone_november">listopad</string>
+ <string name="month_long_standalone_december">prosinec</string>
+
+ <string name="month_long_january">ledna</string>
+ <string name="month_long_february">února</string>
+ <string name="month_long_march">března</string>
+ <string name="month_long_april">dubna</string>
+ <string name="month_long_may">května</string>
+ <string name="month_long_june">června</string>
+ <string name="month_long_july">července</string>
+ <string name="month_long_august">srpna</string>
+ <string name="month_long_september">září</string>
+ <string name="month_long_october">října</string>
+ <string name="month_long_november">listopadu</string>
+ <string name="month_long_december">prosince</string>
+
+ <string name="month_medium_january">1</string>
+ <string name="month_medium_february">2</string>
+ <string name="month_medium_march">3</string>
+ <string name="month_medium_april">4</string>
+ <string name="month_medium_may">5</string>
+ <string name="month_medium_june">6</string>
+ <string name="month_medium_july">7</string>
+ <string name="month_medium_august">8</string>
+ <string name="month_medium_september">9</string>
+ <string name="month_medium_october">10</string>
+ <string name="month_medium_november">11</string>
+ <string name="month_medium_december">12</string>
+
+ <string name="month_shortest_january">l</string>
+ <string name="month_shortest_february">ú</string>
+ <string name="month_shortest_march">b</string>
+ <string name="month_shortest_april">d</string>
+ <string name="month_shortest_may">k</string>
+ <string name="month_shortest_june">č</string>
+ <string name="month_shortest_july">č</string>
+ <string name="month_shortest_august">s</string>
+ <string name="month_shortest_september">z</string>
+ <string name="month_shortest_october">ř</string>
+ <string name="month_shortest_november">l</string>
+ <string name="month_shortest_december">p</string>
+
+ <string name="day_of_week_long_sunday">neděle</string>
+ <string name="day_of_week_long_monday">pondělí</string>
+ <string name="day_of_week_long_tuesday">úterý</string>
+ <string name="day_of_week_long_wednesday">středa</string>
+ <string name="day_of_week_long_thursday">čtvrtek</string>
+ <string name="day_of_week_long_friday">pátek</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">ne</string>
+ <string name="day_of_week_medium_monday">po</string>
+ <string name="day_of_week_medium_tuesday">út</string>
+ <string name="day_of_week_medium_wednesday">st</string>
+ <string name="day_of_week_medium_thursday">čt</string>
+ <string name="day_of_week_medium_friday">pá</string>
+ <string name="day_of_week_medium_saturday">so</string>
+
+ <string name="day_of_week_short_sunday">ne</string>
+ <string name="day_of_week_short_monday">po</string>
+ <string name="day_of_week_short_tuesday">út</string>
+ <string name="day_of_week_short_wednesday">st</string>
+ <string name="day_of_week_short_thursday">čt</string>
+ <string name="day_of_week_short_friday">pá</string>
+ <string name="day_of_week_short_saturday">so</string>
+
+ <string name="day_of_week_shortest_sunday">N</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">Ú</string>
+ <string name="day_of_week_shortest_wednesday">S</string>
+ <string name="day_of_week_shortest_thursday">Č</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">dop.</string>
+ <string name="pm">odp.</string>
+ <string name="yesterday">Včera</string>
+ <string name="today">Dnes</string>
+ <string name="tomorrow">Zítra</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%-e.%-m.%Y</string>
+ <string name="numeric_date_format">d.M.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
+ <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
new file mode 100644
index 0000000..f477d56
--- /dev/null
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">leden</string>
+ <string name="month_long_standalone_february">únor</string>
+ <string name="month_long_standalone_march">březen</string>
+ <string name="month_long_standalone_april">duben</string>
+ <string name="month_long_standalone_may">květen</string>
+ <string name="month_long_standalone_june">červen</string>
+ <string name="month_long_standalone_july">červenec</string>
+ <string name="month_long_standalone_august">srpen</string>
+ <string name="month_long_standalone_september">září</string>
+ <string name="month_long_standalone_october">říjen</string>
+ <string name="month_long_standalone_november">listopad</string>
+ <string name="month_long_standalone_december">prosinec</string>
+
+ <string name="month_long_january">ledna</string>
+ <string name="month_long_february">února</string>
+ <string name="month_long_march">března</string>
+ <string name="month_long_april">dubna</string>
+ <string name="month_long_may">května</string>
+ <string name="month_long_june">června</string>
+ <string name="month_long_july">července</string>
+ <string name="month_long_august">srpna</string>
+ <string name="month_long_september">září</string>
+ <string name="month_long_october">října</string>
+ <string name="month_long_november">listopadu</string>
+ <string name="month_long_december">prosince</string>
+
+ <string name="month_medium_january">1</string>
+ <string name="month_medium_february">2</string>
+ <string name="month_medium_march">3</string>
+ <string name="month_medium_april">4</string>
+ <string name="month_medium_may">5</string>
+ <string name="month_medium_june">6</string>
+ <string name="month_medium_july">7</string>
+ <string name="month_medium_august">8</string>
+ <string name="month_medium_september">9</string>
+ <string name="month_medium_october">10</string>
+ <string name="month_medium_november">11</string>
+ <string name="month_medium_december">12</string>
+
+ <string name="month_shortest_january">l</string>
+ <string name="month_shortest_february">ú</string>
+ <string name="month_shortest_march">b</string>
+ <string name="month_shortest_april">d</string>
+ <string name="month_shortest_may">k</string>
+ <string name="month_shortest_june">č</string>
+ <string name="month_shortest_july">č</string>
+ <string name="month_shortest_august">s</string>
+ <string name="month_shortest_september">z</string>
+ <string name="month_shortest_october">ř</string>
+ <string name="month_shortest_november">l</string>
+ <string name="month_shortest_december">p</string>
+
+ <string name="day_of_week_long_sunday">neděle</string>
+ <string name="day_of_week_long_monday">pondělí</string>
+ <string name="day_of_week_long_tuesday">úterý</string>
+ <string name="day_of_week_long_wednesday">středa</string>
+ <string name="day_of_week_long_thursday">čtvrtek</string>
+ <string name="day_of_week_long_friday">pátek</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">ne</string>
+ <string name="day_of_week_medium_monday">po</string>
+ <string name="day_of_week_medium_tuesday">út</string>
+ <string name="day_of_week_medium_wednesday">st</string>
+ <string name="day_of_week_medium_thursday">čt</string>
+ <string name="day_of_week_medium_friday">pá</string>
+ <string name="day_of_week_medium_saturday">so</string>
+
+ <string name="day_of_week_short_sunday">ne</string>
+ <string name="day_of_week_short_monday">po</string>
+ <string name="day_of_week_short_tuesday">út</string>
+ <string name="day_of_week_short_wednesday">st</string>
+ <string name="day_of_week_short_thursday">čt</string>
+ <string name="day_of_week_short_friday">pá</string>
+ <string name="day_of_week_short_saturday">so</string>
+
+ <string name="day_of_week_shortest_sunday">N</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">Ú</string>
+ <string name="day_of_week_shortest_wednesday">S</string>
+ <string name="day_of_week_shortest_thursday">Č</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">dop.</string>
+ <string name="pm">odp.</string>
+ <string name="yesterday">Včera</string>
+ <string name="today">Dnes</string>
+ <string name="tomorrow">Zítra</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%-e.%-m.%Y</string>
+ <string name="numeric_date_format">d.M.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
+ <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 35a3f9a..c3860d4 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Heslo"</string>
<string name="lockscreen_glogin_submit_button">"Přihlásit se"</string>
<string name="lockscreen_glogin_invalid_input">"Neplatné uživatelské jméno nebo heslo."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Vymazat oznámení"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"enter"</string>
<string name="menu_delete_shortcut_label">"smazat"</string>
<string name="search_go">"Hledat"</string>
- <string name="today">"Dnes"</string>
- <string name="yesterday">"Včera"</string>
- <string name="tomorrow">"Zítra"</string>
<string name="oneMonthDurationPast">"před 1 měsícem"</string>
<string name="beforeOneMonthDurationPast">"Déle než před 1 měsícem"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"týd."</string>
<string name="year">"rokem"</string>
<string name="years">"lety"</string>
- <string name="sunday">"neděle"</string>
- <string name="monday">"pondělí"</string>
- <string name="tuesday">"úterý"</string>
- <string name="wednesday">"středa"</string>
- <string name="thursday">"čtvrtek"</string>
- <string name="friday">"pátek"</string>
- <string name="saturday">"sobota"</string>
<string name="every_weekday">"Každý pracovní den (Po – Pá)"</string>
<string name="daily">"Denně"</string>
<string name="weekly">"Každý týden v <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Omlouváme se, ale toto video nelze přenášet datovým proudem do tohoto zařízení."</string>
<string name="VideoView_error_text_unknown">"Toto video bohužel nelze přehrát."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"dop."</string>
- <string name="pm">"odp."</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"poledne"</string>
<string name="Noon">"Poledne"</string>
<string name="midnight">"půlnoc"</string>
<string name="Midnight">"Půlnoc"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"neděle"</string>
- <string name="day_of_week_long_monday">"pondělí"</string>
- <string name="day_of_week_long_tuesday">"úterý"</string>
- <string name="day_of_week_long_wednesday">"středa"</string>
- <string name="day_of_week_long_thursday">"čtvrtek"</string>
- <string name="day_of_week_long_friday">"pátek"</string>
- <string name="day_of_week_long_saturday">"sobota"</string>
- <string name="day_of_week_medium_sunday">"Ne"</string>
- <string name="day_of_week_medium_monday">"Po"</string>
- <string name="day_of_week_medium_tuesday">"Út"</string>
- <string name="day_of_week_medium_wednesday">"St"</string>
- <string name="day_of_week_medium_thursday">"Čt"</string>
- <string name="day_of_week_medium_friday">"Pá"</string>
- <string name="day_of_week_medium_saturday">"So"</string>
- <string name="day_of_week_short_sunday">"Ne"</string>
- <string name="day_of_week_short_monday">"Po"</string>
- <string name="day_of_week_short_tuesday">"Út"</string>
- <string name="day_of_week_short_wednesday">"St"</string>
- <string name="day_of_week_short_thursday">"Čt"</string>
- <string name="day_of_week_short_friday">"Pá"</string>
- <string name="day_of_week_short_saturday">"So"</string>
- <string name="day_of_week_shorter_sunday">"Ne"</string>
- <string name="day_of_week_shorter_monday">"Po"</string>
- <string name="day_of_week_shorter_tuesday">"Út"</string>
- <string name="day_of_week_shorter_wednesday">"St"</string>
- <string name="day_of_week_shorter_thursday">"Čt"</string>
- <string name="day_of_week_shorter_friday">"Pá"</string>
- <string name="day_of_week_shorter_saturday">"So"</string>
- <string name="day_of_week_shortest_sunday">"Ne"</string>
- <string name="day_of_week_shortest_monday">"Po"</string>
- <string name="day_of_week_shortest_tuesday">"Čt"</string>
- <string name="day_of_week_shortest_wednesday">"St"</string>
- <string name="day_of_week_shortest_thursday">"Čt"</string>
- <string name="day_of_week_shortest_friday">"Pá"</string>
- <string name="day_of_week_shortest_saturday">"So"</string>
- <string name="month_long_january">"leden"</string>
- <string name="month_long_february">"únor"</string>
- <string name="month_long_march">"březen"</string>
- <string name="month_long_april">"duben"</string>
- <string name="month_long_may">"květen"</string>
- <string name="month_long_june">"červen"</string>
- <string name="month_long_july">"červenec"</string>
- <string name="month_long_august">"srpen"</string>
- <string name="month_long_september">"září"</string>
- <string name="month_long_october">"říjen"</string>
- <string name="month_long_november">"listopad"</string>
- <string name="month_long_december">"prosinec"</string>
- <string name="month_medium_january">"leden"</string>
- <string name="month_medium_february">"únor"</string>
- <string name="month_medium_march">"březen"</string>
- <string name="month_medium_april">"duben"</string>
- <string name="month_medium_may">"květen"</string>
- <string name="month_medium_june">"červen"</string>
- <string name="month_medium_july">"červenec"</string>
- <string name="month_medium_august">"srpen"</string>
- <string name="month_medium_september">"září"</string>
- <string name="month_medium_october">"říjen"</string>
- <string name="month_medium_november">"listopad"</string>
- <string name="month_medium_december">"prosinec"</string>
- <string name="month_shortest_january">"1."</string>
- <string name="month_shortest_february">"2."</string>
- <string name="month_shortest_march">"Po"</string>
- <string name="month_shortest_april">"4."</string>
- <string name="month_shortest_may">"5."</string>
- <string name="month_shortest_june">"6."</string>
- <string name="month_shortest_july">"7."</string>
- <string name="month_shortest_august">"8."</string>
- <string name="month_shortest_september">"9."</string>
- <string name="month_shortest_october">"10."</string>
- <string name="month_shortest_november">"11."</string>
- <string name="month_shortest_december">"12."</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Vybrat vše"</string>
diff --git a/core/res/res/values-da-rDK/donottranslate-cldr.xml b/core/res/res/values-da-rDK/donottranslate-cldr.xml
new file mode 100644
index 0000000..38097bd
--- /dev/null
+++ b/core/res/res/values-da-rDK/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januar</string>
+ <string name="month_long_standalone_february">februar</string>
+ <string name="month_long_standalone_march">marts</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">maj</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">august</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januar</string>
+ <string name="month_long_february">februar</string>
+ <string name="month_long_march">marts</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">maj</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">august</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mar.</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">maj</string>
+ <string name="month_medium_june">jun.</string>
+ <string name="month_medium_july">jul.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sep.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">søndag</string>
+ <string name="day_of_week_long_monday">mandag</string>
+ <string name="day_of_week_long_tuesday">tirsdag</string>
+ <string name="day_of_week_long_wednesday">onsdag</string>
+ <string name="day_of_week_long_thursday">torsdag</string>
+ <string name="day_of_week_long_friday">fredag</string>
+ <string name="day_of_week_long_saturday">lørdag</string>
+
+ <string name="day_of_week_medium_sunday">søn</string>
+ <string name="day_of_week_medium_monday">man</string>
+ <string name="day_of_week_medium_tuesday">tir</string>
+ <string name="day_of_week_medium_wednesday">ons</string>
+ <string name="day_of_week_medium_thursday">tor</string>
+ <string name="day_of_week_medium_friday">fre</string>
+ <string name="day_of_week_medium_saturday">lør</string>
+
+ <string name="day_of_week_short_sunday">søn</string>
+ <string name="day_of_week_short_monday">man</string>
+ <string name="day_of_week_short_tuesday">tir</string>
+ <string name="day_of_week_short_wednesday">ons</string>
+ <string name="day_of_week_short_thursday">tor</string>
+ <string name="day_of_week_short_friday">fre</string>
+ <string name="day_of_week_short_saturday">lør</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">O</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">L</string>
+
+ <string name="am">f.m.</string>
+ <string name="pm">e.m.</string>
+ <string name="yesterday">i går</string>
+ <string name="today">i dag</string>
+ <string name="tomorrow">i morgen</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e. %b %Y</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%b</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de-rAT/donottranslate-cldr.xml b/core/res/res/values-de-rAT/donottranslate-cldr.xml
new file mode 100644
index 0000000..ad35fee
--- /dev/null
+++ b/core/res/res/values-de-rAT/donottranslate-cldr.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Jänner</string>
+
+ <string name="month_long_january">Jänner</string>
+
+ <string name="month_medium_january">Jän</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sonntag</string>
+ <string name="day_of_week_long_monday">Montag</string>
+ <string name="day_of_week_long_tuesday">Dienstag</string>
+ <string name="day_of_week_long_wednesday">Mittwoch</string>
+ <string name="day_of_week_long_thursday">Donnerstag</string>
+ <string name="day_of_week_long_friday">Freitag</string>
+ <string name="day_of_week_long_saturday">Samstag</string>
+
+ <string name="day_of_week_medium_sunday">So.</string>
+ <string name="day_of_week_medium_monday">Mo.</string>
+ <string name="day_of_week_medium_tuesday">Di.</string>
+ <string name="day_of_week_medium_wednesday">Mi.</string>
+ <string name="day_of_week_medium_thursday">Do.</string>
+ <string name="day_of_week_medium_friday">Fr.</string>
+ <string name="day_of_week_medium_saturday">Sa.</string>
+
+ <string name="day_of_week_short_sunday">So.</string>
+ <string name="day_of_week_short_monday">Mo.</string>
+ <string name="day_of_week_short_tuesday">Di.</string>
+ <string name="day_of_week_short_wednesday">Mi.</string>
+ <string name="day_of_week_short_thursday">Do.</string>
+ <string name="day_of_week_short_friday">Fr.</string>
+ <string name="day_of_week_short_saturday">Sa.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">vorm.</string>
+ <string name="pm">nachm.</string>
+ <string name="yesterday">Gestern</string>
+ <string name="today">Heute</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%d. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de-rCH/donottranslate-cldr.xml b/core/res/res/values-de-rCH/donottranslate-cldr.xml
new file mode 100644
index 0000000..c8e0de8
--- /dev/null
+++ b/core/res/res/values-de-rCH/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Januar</string>
+ <string name="month_long_standalone_february">Februar</string>
+ <string name="month_long_standalone_march">März</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">Mai</string>
+ <string name="month_long_standalone_june">Juni</string>
+ <string name="month_long_standalone_july">Juli</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">Oktober</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">Dezember</string>
+
+ <string name="month_long_january">Januar</string>
+ <string name="month_long_february">Februar</string>
+ <string name="month_long_march">März</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">Mai</string>
+ <string name="month_long_june">Juni</string>
+ <string name="month_long_july">Juli</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">Oktober</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">Dezember</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mär</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">Mai</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Okt</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sonntag</string>
+ <string name="day_of_week_long_monday">Montag</string>
+ <string name="day_of_week_long_tuesday">Dienstag</string>
+ <string name="day_of_week_long_wednesday">Mittwoch</string>
+ <string name="day_of_week_long_thursday">Donnerstag</string>
+ <string name="day_of_week_long_friday">Freitag</string>
+ <string name="day_of_week_long_saturday">Samstag</string>
+
+ <string name="day_of_week_medium_sunday">So.</string>
+ <string name="day_of_week_medium_monday">Mo.</string>
+ <string name="day_of_week_medium_tuesday">Di.</string>
+ <string name="day_of_week_medium_wednesday">Mi.</string>
+ <string name="day_of_week_medium_thursday">Do.</string>
+ <string name="day_of_week_medium_friday">Fr.</string>
+ <string name="day_of_week_medium_saturday">Sa.</string>
+
+ <string name="day_of_week_short_sunday">So.</string>
+ <string name="day_of_week_short_monday">Mo.</string>
+ <string name="day_of_week_short_tuesday">Di.</string>
+ <string name="day_of_week_short_wednesday">Mi.</string>
+ <string name="day_of_week_short_thursday">Do.</string>
+ <string name="day_of_week_short_friday">Fr.</string>
+ <string name="day_of_week_short_saturday">Sa.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">vorm.</string>
+ <string name="pm">nachm.</string>
+ <string name="yesterday">Gestern</string>
+ <string name="today">Heute</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de-rDE/donottranslate-cldr.xml b/core/res/res/values-de-rDE/donottranslate-cldr.xml
new file mode 100644
index 0000000..c8e0de8
--- /dev/null
+++ b/core/res/res/values-de-rDE/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Januar</string>
+ <string name="month_long_standalone_february">Februar</string>
+ <string name="month_long_standalone_march">März</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">Mai</string>
+ <string name="month_long_standalone_june">Juni</string>
+ <string name="month_long_standalone_july">Juli</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">Oktober</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">Dezember</string>
+
+ <string name="month_long_january">Januar</string>
+ <string name="month_long_february">Februar</string>
+ <string name="month_long_march">März</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">Mai</string>
+ <string name="month_long_june">Juni</string>
+ <string name="month_long_july">Juli</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">Oktober</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">Dezember</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mär</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">Mai</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Okt</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sonntag</string>
+ <string name="day_of_week_long_monday">Montag</string>
+ <string name="day_of_week_long_tuesday">Dienstag</string>
+ <string name="day_of_week_long_wednesday">Mittwoch</string>
+ <string name="day_of_week_long_thursday">Donnerstag</string>
+ <string name="day_of_week_long_friday">Freitag</string>
+ <string name="day_of_week_long_saturday">Samstag</string>
+
+ <string name="day_of_week_medium_sunday">So.</string>
+ <string name="day_of_week_medium_monday">Mo.</string>
+ <string name="day_of_week_medium_tuesday">Di.</string>
+ <string name="day_of_week_medium_wednesday">Mi.</string>
+ <string name="day_of_week_medium_thursday">Do.</string>
+ <string name="day_of_week_medium_friday">Fr.</string>
+ <string name="day_of_week_medium_saturday">Sa.</string>
+
+ <string name="day_of_week_short_sunday">So.</string>
+ <string name="day_of_week_short_monday">Mo.</string>
+ <string name="day_of_week_short_tuesday">Di.</string>
+ <string name="day_of_week_short_wednesday">Mi.</string>
+ <string name="day_of_week_short_thursday">Do.</string>
+ <string name="day_of_week_short_friday">Fr.</string>
+ <string name="day_of_week_short_saturday">Sa.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">vorm.</string>
+ <string name="pm">nachm.</string>
+ <string name="yesterday">Gestern</string>
+ <string name="today">Heute</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de-rLI/donottranslate-cldr.xml b/core/res/res/values-de-rLI/donottranslate-cldr.xml
new file mode 100644
index 0000000..c8e0de8
--- /dev/null
+++ b/core/res/res/values-de-rLI/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Januar</string>
+ <string name="month_long_standalone_february">Februar</string>
+ <string name="month_long_standalone_march">März</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">Mai</string>
+ <string name="month_long_standalone_june">Juni</string>
+ <string name="month_long_standalone_july">Juli</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">Oktober</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">Dezember</string>
+
+ <string name="month_long_january">Januar</string>
+ <string name="month_long_february">Februar</string>
+ <string name="month_long_march">März</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">Mai</string>
+ <string name="month_long_june">Juni</string>
+ <string name="month_long_july">Juli</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">Oktober</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">Dezember</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mär</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">Mai</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Okt</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sonntag</string>
+ <string name="day_of_week_long_monday">Montag</string>
+ <string name="day_of_week_long_tuesday">Dienstag</string>
+ <string name="day_of_week_long_wednesday">Mittwoch</string>
+ <string name="day_of_week_long_thursday">Donnerstag</string>
+ <string name="day_of_week_long_friday">Freitag</string>
+ <string name="day_of_week_long_saturday">Samstag</string>
+
+ <string name="day_of_week_medium_sunday">So.</string>
+ <string name="day_of_week_medium_monday">Mo.</string>
+ <string name="day_of_week_medium_tuesday">Di.</string>
+ <string name="day_of_week_medium_wednesday">Mi.</string>
+ <string name="day_of_week_medium_thursday">Do.</string>
+ <string name="day_of_week_medium_friday">Fr.</string>
+ <string name="day_of_week_medium_saturday">Sa.</string>
+
+ <string name="day_of_week_short_sunday">So.</string>
+ <string name="day_of_week_short_monday">Mo.</string>
+ <string name="day_of_week_short_tuesday">Di.</string>
+ <string name="day_of_week_short_wednesday">Mi.</string>
+ <string name="day_of_week_short_thursday">Do.</string>
+ <string name="day_of_week_short_friday">Fr.</string>
+ <string name="day_of_week_short_saturday">Sa.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">vorm.</string>
+ <string name="pm">nachm.</string>
+ <string name="yesterday">Gestern</string>
+ <string name="today">Heute</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
new file mode 100644
index 0000000..c8e0de8
--- /dev/null
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Januar</string>
+ <string name="month_long_standalone_february">Februar</string>
+ <string name="month_long_standalone_march">März</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">Mai</string>
+ <string name="month_long_standalone_june">Juni</string>
+ <string name="month_long_standalone_july">Juli</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">Oktober</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">Dezember</string>
+
+ <string name="month_long_january">Januar</string>
+ <string name="month_long_february">Februar</string>
+ <string name="month_long_march">März</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">Mai</string>
+ <string name="month_long_june">Juni</string>
+ <string name="month_long_july">Juli</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">Oktober</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">Dezember</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mär</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">Mai</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Okt</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sonntag</string>
+ <string name="day_of_week_long_monday">Montag</string>
+ <string name="day_of_week_long_tuesday">Dienstag</string>
+ <string name="day_of_week_long_wednesday">Mittwoch</string>
+ <string name="day_of_week_long_thursday">Donnerstag</string>
+ <string name="day_of_week_long_friday">Freitag</string>
+ <string name="day_of_week_long_saturday">Samstag</string>
+
+ <string name="day_of_week_medium_sunday">So.</string>
+ <string name="day_of_week_medium_monday">Mo.</string>
+ <string name="day_of_week_medium_tuesday">Di.</string>
+ <string name="day_of_week_medium_wednesday">Mi.</string>
+ <string name="day_of_week_medium_thursday">Do.</string>
+ <string name="day_of_week_medium_friday">Fr.</string>
+ <string name="day_of_week_medium_saturday">Sa.</string>
+
+ <string name="day_of_week_short_sunday">So.</string>
+ <string name="day_of_week_short_monday">Mo.</string>
+ <string name="day_of_week_short_tuesday">Di.</string>
+ <string name="day_of_week_short_wednesday">Mi.</string>
+ <string name="day_of_week_short_thursday">Do.</string>
+ <string name="day_of_week_short_friday">Fr.</string>
+ <string name="day_of_week_short_saturday">Sa.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">vorm.</string>
+ <string name="pm">nachm.</string>
+ <string name="yesterday">Gestern</string>
+ <string name="today">Heute</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 674c64b..d121801 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Passwort"</string>
<string name="lockscreen_glogin_submit_button">"Anmelden"</string>
<string name="lockscreen_glogin_invalid_input">"Ungültiger Nutzername oder ungültiges Passwort."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Benachrichtigungen löschen"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"Enter"</string>
<string name="menu_delete_shortcut_label">"löschen"</string>
<string name="search_go">"Suche"</string>
- <string name="today">"Heute"</string>
- <string name="yesterday">"Gestern"</string>
- <string name="tomorrow">"Morgen"</string>
<string name="oneMonthDurationPast">"Vor 1 Monat"</string>
<string name="beforeOneMonthDurationPast">"Vor mehr als 1 Monat"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"Wochen"</string>
<string name="year">"Jahr"</string>
<string name="years">"Jahre"</string>
- <string name="sunday">"Sonntag"</string>
- <string name="monday">"Montag"</string>
- <string name="tuesday">"Dienstag"</string>
- <string name="wednesday">"Mittwoch"</string>
- <string name="thursday">"Donnerstag"</string>
- <string name="friday">"Freitag"</string>
- <string name="saturday">"Samstag"</string>
<string name="every_weekday">"Jeden Wochentag (Mo-Fr)"</string>
<string name="daily">"Täglich"</string>
<string name="weekly">"Jede Woche am <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Leider ist dieses Video nicht für Streaming auf diesem Gerät gültig."</string>
<string name="VideoView_error_text_unknown">"Dieses Video kann leider nicht abgespielt werden."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"AM"</string>
- <string name="pm">".."</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"Mittag"</string>
<string name="Noon">"Mittag"</string>
<string name="midnight">"Mitternacht"</string>
<string name="Midnight">"Mitternacht"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"Sonntag"</string>
- <string name="day_of_week_long_monday">"Montag"</string>
- <string name="day_of_week_long_tuesday">"Dienstag"</string>
- <string name="day_of_week_long_wednesday">"Mittwoch"</string>
- <string name="day_of_week_long_thursday">"Donnerstag"</string>
- <string name="day_of_week_long_friday">"Freitag"</string>
- <string name="day_of_week_long_saturday">"Samstag"</string>
- <string name="day_of_week_medium_sunday">"So"</string>
- <string name="day_of_week_medium_monday">"Mo"</string>
- <string name="day_of_week_medium_tuesday">"Di"</string>
- <string name="day_of_week_medium_wednesday">"Mi"</string>
- <string name="day_of_week_medium_thursday">"Do"</string>
- <string name="day_of_week_medium_friday">"Fr"</string>
- <string name="day_of_week_medium_saturday">"Sa"</string>
- <string name="day_of_week_short_sunday">"So"</string>
- <string name="day_of_week_short_monday">"Mo"</string>
- <string name="day_of_week_short_tuesday">"Di"</string>
- <string name="day_of_week_short_wednesday">"Mi"</string>
- <string name="day_of_week_short_thursday">"Do"</string>
- <string name="day_of_week_short_friday">"Fr"</string>
- <string name="day_of_week_short_saturday">"Sa"</string>
- <string name="day_of_week_shorter_sunday">"So"</string>
- <string name="day_of_week_shorter_monday">"März"</string>
- <string name="day_of_week_shorter_tuesday">"Di"</string>
- <string name="day_of_week_shorter_wednesday">"Mi"</string>
- <string name="day_of_week_shorter_thursday">"Do"</string>
- <string name="day_of_week_shorter_friday">"Fr"</string>
- <string name="day_of_week_shorter_saturday">"Sa"</string>
- <string name="day_of_week_shortest_sunday">"Sep"</string>
- <string name="day_of_week_shortest_monday">"Mo"</string>
- <string name="day_of_week_shortest_tuesday">"Do"</string>
- <string name="day_of_week_shortest_wednesday">"Mi"</string>
- <string name="day_of_week_shortest_thursday">"Do"</string>
- <string name="day_of_week_shortest_friday">"Fr"</string>
- <string name="day_of_week_shortest_saturday">"Sa"</string>
- <string name="month_long_january">"Januar"</string>
- <string name="month_long_february">"Februar"</string>
- <string name="month_long_march">"März"</string>
- <string name="month_long_april">"April"</string>
- <string name="month_long_may">"Mai"</string>
- <string name="month_long_june">"Juni"</string>
- <string name="month_long_july">"Juli"</string>
- <string name="month_long_august">"August"</string>
- <string name="month_long_september">"September"</string>
- <string name="month_long_october">"Oktober"</string>
- <string name="month_long_november">"November"</string>
- <string name="month_long_december">"Dezember"</string>
- <string name="month_medium_january">"Jan."</string>
- <string name="month_medium_february">"Feb."</string>
- <string name="month_medium_march">"März"</string>
- <string name="month_medium_april">"Apr."</string>
- <string name="month_medium_may">"Mai"</string>
- <string name="month_medium_june">"Juni"</string>
- <string name="month_medium_july">"Juli"</string>
- <string name="month_medium_august">"Aug"</string>
- <string name="month_medium_september">"Sep."</string>
- <string name="month_medium_october">"Okt."</string>
- <string name="month_medium_november">"Nov."</string>
- <string name="month_medium_december">"Dez."</string>
- <string name="month_shortest_january">"Juli"</string>
- <string name="month_shortest_february">"Fr"</string>
- <string name="month_shortest_march">"März"</string>
- <string name="month_shortest_april">"Apr"</string>
- <string name="month_shortest_may">"Mo"</string>
- <string name="month_shortest_june">"Juni"</string>
- <string name="month_shortest_july">"Juli"</string>
- <string name="month_shortest_august">"Aug."</string>
- <string name="month_shortest_september">"Sep"</string>
- <string name="month_shortest_october">"Okt."</string>
- <string name="month_shortest_november">"No"</string>
- <string name="month_shortest_december">"Dez."</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Alles auswählen"</string>
diff --git a/core/res/res/values-el-rGR/donottranslate-cldr.xml b/core/res/res/values-el-rGR/donottranslate-cldr.xml
new file mode 100644
index 0000000..9d2a0aa
--- /dev/null
+++ b/core/res/res/values-el-rGR/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Ιανουάριος</string>
+ <string name="month_long_standalone_february">Φεβρουάριος</string>
+ <string name="month_long_standalone_march">Μάρτιος</string>
+ <string name="month_long_standalone_april">Απρίλιος</string>
+ <string name="month_long_standalone_may">Μάιος</string>
+ <string name="month_long_standalone_june">Ιούνιος</string>
+ <string name="month_long_standalone_july">Ιούλιος</string>
+ <string name="month_long_standalone_august">Αύγουστος</string>
+ <string name="month_long_standalone_september">Σεπτέμβριος</string>
+ <string name="month_long_standalone_october">Οκτώβριος</string>
+ <string name="month_long_standalone_november">Νοέμβριος</string>
+ <string name="month_long_standalone_december">Δεκέμβριος</string>
+
+ <string name="month_long_january">Ιανουαρίου</string>
+ <string name="month_long_february">Φεβρουαρίου</string>
+ <string name="month_long_march">Μαρτίου</string>
+ <string name="month_long_april">Απριλίου</string>
+ <string name="month_long_may">Μαΐου</string>
+ <string name="month_long_june">Ιουνίου</string>
+ <string name="month_long_july">Ιουλίου</string>
+ <string name="month_long_august">Αυγούστου</string>
+ <string name="month_long_september">Σεπτεμβρίου</string>
+ <string name="month_long_october">Οκτωβρίου</string>
+ <string name="month_long_november">Νοεμβρίου</string>
+ <string name="month_long_december">Δεκεμβρίου</string>
+
+ <string name="month_medium_january">Ιαν</string>
+ <string name="month_medium_february">Φεβ</string>
+ <string name="month_medium_march">Μαρ</string>
+ <string name="month_medium_april">Απρ</string>
+ <string name="month_medium_may">Μαϊ</string>
+ <string name="month_medium_june">Ιουν</string>
+ <string name="month_medium_july">Ιουλ</string>
+ <string name="month_medium_august">Αυγ</string>
+ <string name="month_medium_september">Σεπ</string>
+ <string name="month_medium_october">Οκτ</string>
+ <string name="month_medium_november">Νοε</string>
+ <string name="month_medium_december">Δεκ</string>
+
+ <string name="month_shortest_january">Ι</string>
+ <string name="month_shortest_february">Φ</string>
+ <string name="month_shortest_march">Μ</string>
+ <string name="month_shortest_april">Α</string>
+ <string name="month_shortest_may">Μ</string>
+ <string name="month_shortest_june">Ι</string>
+ <string name="month_shortest_july">Ι</string>
+ <string name="month_shortest_august">Α</string>
+ <string name="month_shortest_september">Σ</string>
+ <string name="month_shortest_october">Ο</string>
+ <string name="month_shortest_november">Ν</string>
+ <string name="month_shortest_december">Δ</string>
+
+ <string name="day_of_week_long_sunday">Κυριακή</string>
+ <string name="day_of_week_long_monday">Δευτέρα</string>
+ <string name="day_of_week_long_tuesday">Τρίτη</string>
+ <string name="day_of_week_long_wednesday">Τετάρτη</string>
+ <string name="day_of_week_long_thursday">Πέμπτη</string>
+ <string name="day_of_week_long_friday">Παρασκευή</string>
+ <string name="day_of_week_long_saturday">Σάββατο</string>
+
+ <string name="day_of_week_medium_sunday">Κυρ</string>
+ <string name="day_of_week_medium_monday">Δευ</string>
+ <string name="day_of_week_medium_tuesday">Τρι</string>
+ <string name="day_of_week_medium_wednesday">Τετ</string>
+ <string name="day_of_week_medium_thursday">Πεμ</string>
+ <string name="day_of_week_medium_friday">Παρ</string>
+ <string name="day_of_week_medium_saturday">Σαβ</string>
+
+ <string name="day_of_week_short_sunday">Κυρ</string>
+ <string name="day_of_week_short_monday">Δευ</string>
+ <string name="day_of_week_short_tuesday">Τρι</string>
+ <string name="day_of_week_short_wednesday">Τετ</string>
+ <string name="day_of_week_short_thursday">Πεμ</string>
+ <string name="day_of_week_short_friday">Παρ</string>
+ <string name="day_of_week_short_saturday">Σαβ</string>
+
+ <string name="day_of_week_shortest_sunday">Κ</string>
+ <string name="day_of_week_shortest_monday">Δ</string>
+ <string name="day_of_week_shortest_tuesday">Τ</string>
+ <string name="day_of_week_shortest_wednesday">Τ</string>
+ <string name="day_of_week_shortest_thursday">Π</string>
+ <string name="day_of_week_shortest_friday">Π</string>
+ <string name="day_of_week_shortest_saturday">Σ</string>
+
+ <string name="am">π.μ.</string>
+ <string name="pm">μ.μ.</string>
+ <string name="yesterday">Χτες</string>
+ <string name="today">Σήμερα</string>
+ <string name="tomorrow">Αύριο</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string>
+ <string name="abbrev_month_day_year">%d %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml
new file mode 100644
index 0000000..7ed029c
--- /dev/null
+++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-e/%m/%Y</string>
+ <string name="numeric_date_format">d/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 9da879b..d482222 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -710,7 +710,6 @@
<!-- no translation found for lockscreen_glogin_invalid_input (4881057177478491580) -->
<skip />
<!-- no translation found for status_bar_time_format (2168573805413119180) -->
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
<!-- no translation found for hour_minute_ampm (1850330605794978742) -->
<skip />
<!-- no translation found for hour_minute_cap_ampm (1122840227537374196) -->
@@ -864,7 +863,6 @@
<!-- from values-de/strings.xml and removal of all the german craziyness-->
<skip />
<!-- no translation found for numeric_date (5120078478872821100) -->
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for wday1_date1_time1_wday2_date2_time2 (7066878981949584861) -->
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<!-- no translation found for wday1_date1_wday2_date2 (8671068747172261907) -->
@@ -888,11 +886,9 @@
<!-- no translation found for full_date_month_first (6011143962222283357) -->
<skip />
<!-- no translation found for full_date_day_first (8621594762705478189) -->
- <string name="full_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string>
<!-- no translation found for medium_date_month_first (48990963718825728) -->
<skip />
<!-- no translation found for medium_date_day_first (2898992016440387123) -->
- <string name="medium_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string>
<!-- no translation found for twelve_hour_time_format (6015557937879492156) -->
<skip />
<!-- no translation found for twenty_four_hour_time_format (5176807998669709535) -->
@@ -906,15 +902,12 @@
<!-- no translation found for Midnight (1260172107848123187) -->
<skip />
<!-- no translation found for month_day (3356633704511426364) -->
- <string name="month_day">"<xliff:g id="day" example="9">%-d</xliff:g> <xliff:g id="month" example="October">%B</xliff:g>"</string>
<!-- no translation found for month (3017405760734206414) -->
<skip />
<!-- no translation found for month_day_year (2435948225709176752) -->
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for month_year (6228414124777343135) -->
<skip />
<!-- no translation found for time_of_day (8375993139317154157) -->
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<!-- no translation found for date_and_time (9197690194373107109) -->
<skip />
<!-- no translation found for same_year_md1_md2 (9199324363135981317) -->
@@ -922,7 +915,6 @@
<!-- no translation found for same_year_wday1_md1_wday2_md2 (6006392413355305178) -->
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<!-- no translation found for date_and_time (353898423108629694) -->
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for same_year_mdy1_mdy2 (1576657593937827090) -->
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
<!-- no translation found for same_year_wday1_mdy1_wday2_mdy2 (9135935796468891580) -->
@@ -968,11 +960,9 @@
<!-- no translation found for same_month_wday1_mdy1_time1_wday2_mdy2_time2 (1332950588774239228) -->
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<!-- no translation found for abbrev_month_day_year (5767271534015320250) -->
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for abbrev_month_year (8058929633673942490) -->
<skip />
<!-- no translation found for abbrev_month_day (458867920693482757) -->
- <string name="abbrev_month_day">"<xliff:g id="day" example="31">%-d</xliff:g> <xliff:g id="month" example="Oct">%b</xliff:g>"</string>
<!-- no translation found for abbrev_month (1674509986330181349) -->
<skip />
<!-- no translation found for day_of_week_long_sunday (9057662850446501884) -->
diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml
new file mode 100644
index 0000000..2fb3ef6
--- /dev/null
+++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%Y-%m-%d</string>
+ <string name="numeric_date_format">yyyy-MM-dd</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %Y-%m-%d</string>
+ <string name="abbrev_month_day_year">%Y-%m-%d</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
new file mode 100644
index 0000000..0c544af
--- /dev/null
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml
new file mode 100644
index 0000000..0c544af
--- /dev/null
+++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml
new file mode 100644
index 0000000..823c3c1
--- /dev/null
+++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d-%b-%Y</string>
+ <string name="abbrev_month_day_year">%d-%b-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
new file mode 100644
index 0000000..bcd976c
--- /dev/null
+++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-e/%m/%Y</string>
+ <string name="numeric_date_format">d/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %-e/%m/%Y</string>
+ <string name="abbrev_month_day_year">%-e/%m/%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rSG/donottranslate-cldr.xml b/core/res/res/values-en-rSG/donottranslate-cldr.xml
new file mode 100644
index 0000000..f305948
--- /dev/null
+++ b/core/res/res/values-en-rSG/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-m/%-e/%Y</string>
+ <string name="numeric_date_format">M/d/yyyy</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %b %-e, %Y</string>
+ <string name="abbrev_month_day_year">%b %-e, %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rSG/strings.xml b/core/res/res/values-en-rSG/strings.xml
index 6850a5d..1c6eda2 100644
--- a/core/res/res/values-en-rSG/strings.xml
+++ b/core/res/res/values-en-rSG/strings.xml
@@ -710,7 +710,6 @@
<!-- no translation found for lockscreen_glogin_invalid_input (4881057177478491580) -->
<skip />
<!-- no translation found for status_bar_time_format (2168573805413119180) -->
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
<!-- no translation found for hour_minute_ampm (1850330605794978742) -->
<skip />
<!-- no translation found for hour_minute_cap_ampm (1122840227537374196) -->
@@ -867,7 +866,6 @@
<!-- no translation found for wday1_date1_wday2_date2 (8671068747172261907) -->
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<!-- no translation found for numeric_date (5537215108967329745) -->
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for date1_time1_date2_time2 (3645498975775629615) -->
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<!-- no translation found for date1_date2 (377057563556488062) -->
@@ -885,11 +883,9 @@
<!-- no translation found for full_date_month_first (6011143962222283357) -->
<skip />
<!-- no translation found for full_date_day_first (8621594762705478189) -->
- <string name="full_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string>
<!-- no translation found for medium_date_month_first (48990963718825728) -->
<skip />
<!-- no translation found for medium_date_day_first (2898992016440387123) -->
- <string name="medium_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string>
<!-- no translation found for twelve_hour_time_format (6015557937879492156) -->
<skip />
<!-- no translation found for twenty_four_hour_time_format (5176807998669709535) -->
@@ -903,17 +899,13 @@
<!-- no translation found for Midnight (1260172107848123187) -->
<skip />
<!-- no translation found for month_day (3356633704511426364) -->
- <string name="month_day">"<xliff:g id="day" example="9">%-d</xliff:g> <xliff:g id="month" example="October">%B</xliff:g>"</string>
<!-- no translation found for month (3017405760734206414) -->
<skip />
<!-- no translation found for month_day_year (2435948225709176752) -->
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for month_year (6228414124777343135) -->
<skip />
<!-- no translation found for time_of_day (8375993139317154157) -->
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<!-- no translation found for date_and_time (9197690194373107109) -->
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for same_year_md1_md2 (9199324363135981317) -->
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<!-- no translation found for same_year_wday1_md1_wday2_md2 (6006392413355305178) -->
@@ -963,11 +955,9 @@
<!-- no translation found for same_month_wday1_mdy1_time1_wday2_mdy2_time2 (1332950588774239228) -->
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<!-- no translation found for abbrev_month_day_year (5767271534015320250) -->
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for abbrev_month_year (8058929633673942490) -->
<skip />
<!-- no translation found for abbrev_month_day (458867920693482757) -->
- <string name="abbrev_month_day">"<xliff:g id="day" example="31">%-d</xliff:g> <xliff:g id="month" example="Oct">%b</xliff:g>"</string>
<!-- no translation found for abbrev_month (1674509986330181349) -->
<skip />
<!-- no translation found for day_of_week_long_sunday (9057662850446501884) -->
diff --git a/core/res/res/values-en-rUS/donottranslate-cldr.xml b/core/res/res/values-en-rUS/donottranslate-cldr.xml
new file mode 100644
index 0000000..f305948
--- /dev/null
+++ b/core/res/res/values-en-rUS/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-m/%-e/%Y</string>
+ <string name="numeric_date_format">M/d/yyyy</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %b %-e, %Y</string>
+ <string name="abbrev_month_day_year">%b %-e, %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml
new file mode 100644
index 0000000..633c761
--- /dev/null
+++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%Y/%m/%d</string>
+ <string name="numeric_date_format">yyyy/MM/dd</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string>
+ <string name="abbrev_month_day_year">%d %b %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-es-rES/donottranslate-cldr.xml b/core/res/res/values-es-rES/donottranslate-cldr.xml
new file mode 100644
index 0000000..967a639
--- /dev/null
+++ b/core/res/res/values-es-rES/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">enero</string>
+ <string name="month_long_standalone_february">febrero</string>
+ <string name="month_long_standalone_march">marzo</string>
+ <string name="month_long_standalone_april">abril</string>
+ <string name="month_long_standalone_may">mayo</string>
+ <string name="month_long_standalone_june">junio</string>
+ <string name="month_long_standalone_july">julio</string>
+ <string name="month_long_standalone_august">agosto</string>
+ <string name="month_long_standalone_september">septiembre</string>
+ <string name="month_long_standalone_october">octubre</string>
+ <string name="month_long_standalone_november">noviembre</string>
+ <string name="month_long_standalone_december">diciembre</string>
+
+ <string name="month_long_january">enero</string>
+ <string name="month_long_february">febrero</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">abril</string>
+ <string name="month_long_may">mayo</string>
+ <string name="month_long_june">junio</string>
+ <string name="month_long_july">julio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">septiembre</string>
+ <string name="month_long_october">octubre</string>
+ <string name="month_long_november">noviembre</string>
+ <string name="month_long_december">diciembre</string>
+
+ <string name="month_medium_january">ene</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">abr</string>
+ <string name="month_medium_may">may</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">oct</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">E</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domingo</string>
+ <string name="day_of_week_long_monday">lunes</string>
+ <string name="day_of_week_long_tuesday">martes</string>
+ <string name="day_of_week_long_wednesday">miércoles</string>
+ <string name="day_of_week_long_thursday">jueves</string>
+ <string name="day_of_week_long_friday">viernes</string>
+ <string name="day_of_week_long_saturday">sábado</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mié</string>
+ <string name="day_of_week_medium_thursday">jue</string>
+ <string name="day_of_week_medium_friday">vie</string>
+ <string name="day_of_week_medium_saturday">sáb</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mié</string>
+ <string name="day_of_week_short_thursday">jue</string>
+ <string name="day_of_week_short_friday">vie</string>
+ <string name="day_of_week_short_saturday">sáb</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">ayer</string>
+ <string name="today">hoy</string>
+ <string name="tomorrow">mañana</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B de %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
new file mode 100644
index 0000000..8668fda
--- /dev/null
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">enero</string>
+ <string name="month_long_standalone_february">febrero</string>
+ <string name="month_long_standalone_march">marzo</string>
+ <string name="month_long_standalone_april">abril</string>
+ <string name="month_long_standalone_may">mayo</string>
+ <string name="month_long_standalone_june">junio</string>
+ <string name="month_long_standalone_july">julio</string>
+ <string name="month_long_standalone_august">agosto</string>
+ <string name="month_long_standalone_september">septiembre</string>
+ <string name="month_long_standalone_october">octubre</string>
+ <string name="month_long_standalone_november">noviembre</string>
+ <string name="month_long_standalone_december">diciembre</string>
+
+ <string name="month_long_january">enero</string>
+ <string name="month_long_february">febrero</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">abril</string>
+ <string name="month_long_may">mayo</string>
+ <string name="month_long_june">junio</string>
+ <string name="month_long_july">julio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">septiembre</string>
+ <string name="month_long_october">octubre</string>
+ <string name="month_long_november">noviembre</string>
+ <string name="month_long_december">diciembre</string>
+
+ <string name="month_medium_january">ene</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">abr</string>
+ <string name="month_medium_may">may</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">oct</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">E</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domingo</string>
+ <string name="day_of_week_long_monday">lunes</string>
+ <string name="day_of_week_long_tuesday">martes</string>
+ <string name="day_of_week_long_wednesday">miércoles</string>
+ <string name="day_of_week_long_thursday">jueves</string>
+ <string name="day_of_week_long_friday">viernes</string>
+ <string name="day_of_week_long_saturday">sábado</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mié</string>
+ <string name="day_of_week_medium_thursday">jue</string>
+ <string name="day_of_week_medium_friday">vie</string>
+ <string name="day_of_week_medium_saturday">sáb</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mié</string>
+ <string name="day_of_week_short_thursday">jue</string>
+ <string name="day_of_week_short_friday">vie</string>
+ <string name="day_of_week_short_saturday">sáb</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">ayer</string>
+ <string name="today">hoy</string>
+ <string name="tomorrow">mañana</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-m/%-e/%Y</string>
+ <string name="numeric_date_format">M/d/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %b %-e, %Y</string>
+ <string name="abbrev_month_day_year">%b %-e, %Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B de %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 7b60a39..6032321 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -436,9 +436,6 @@
<string name="lockscreen_glogin_password_hint">"Contraseña"</string>
<string name="lockscreen_glogin_submit_button">"Inicia sesión"</string>
<string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña incorrecta."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Borrar notificaciones"</string>
@@ -470,9 +467,6 @@
<string name="menu_enter_shortcut_label">"ingresar"</string>
<string name="menu_delete_shortcut_label">"borrar"</string>
<string name="search_go">"Buscar"</string>
- <string name="today">"Hoy"</string>
- <string name="yesterday">"Ayer"</string>
- <string name="tomorrow">"Mañana"</string>
<string name="oneMonthDurationPast">"hace 1 mes"</string>
<string name="beforeOneMonthDurationPast">"Anterior a 1 mes atrás"</string>
<plurals name="num_seconds_ago">
@@ -554,13 +548,6 @@
<string name="weeks">"semanas"</string>
<string name="year">"año"</string>
<string name="years">"años"</string>
- <string name="sunday">"Domingo"</string>
- <string name="monday">"Lunes"</string>
- <string name="tuesday">"Martes"</string>
- <string name="wednesday">"Miércoles"</string>
- <string name="thursday">"Jueves"</string>
- <string name="friday">"Viernes"</string>
- <string name="saturday">"Sábado"</string>
<string name="every_weekday">"Los días de semana (lunes a viernes)"</string>
<string name="daily">"Diariamente"</string>
<string name="weekly">"Semanalmente el día <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -570,9 +557,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Lo sentimos, este video no es válido para las transmisiones a este dispositivo."</string>
<string name="VideoView_error_text_unknown">"Lo sentimos, no se puede reproducir este video."</string>
<string name="VideoView_error_button">"Aceptar"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -584,23 +568,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"mediodía"</string>
<string name="Noon">"Mediodía"</string>
<string name="midnight">"medianoche"</string>
<string name="Midnight">"Medianoche"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -625,82 +598,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"Domingo"</string>
- <string name="day_of_week_long_monday">"Lunes"</string>
- <string name="day_of_week_long_tuesday">"Martes"</string>
- <string name="day_of_week_long_wednesday">"Miércoles"</string>
- <string name="day_of_week_long_thursday">"Jueves"</string>
- <string name="day_of_week_long_friday">"Viernes"</string>
- <string name="day_of_week_long_saturday">"Sábado"</string>
- <string name="day_of_week_medium_sunday">"Dom."</string>
- <string name="day_of_week_medium_monday">"Lun."</string>
- <string name="day_of_week_medium_tuesday">"Mar."</string>
- <string name="day_of_week_medium_wednesday">"Mié."</string>
- <string name="day_of_week_medium_thursday">"Jue."</string>
- <string name="day_of_week_medium_friday">"Vie."</string>
- <string name="day_of_week_medium_saturday">"Sáb."</string>
- <string name="day_of_week_short_sunday">"Dom."</string>
- <string name="day_of_week_short_monday">"Lun."</string>
- <string name="day_of_week_short_tuesday">"Mar."</string>
- <string name="day_of_week_short_wednesday">"Nosotros"</string>
- <string name="day_of_week_short_thursday">"Jue."</string>
- <string name="day_of_week_short_friday">"V"</string>
- <string name="day_of_week_short_saturday">"Sáb."</string>
- <string name="day_of_week_shorter_sunday">"Dom."</string>
- <string name="day_of_week_shorter_monday">"L"</string>
- <string name="day_of_week_shorter_tuesday">"Mar."</string>
- <string name="day_of_week_shorter_wednesday">"M"</string>
- <string name="day_of_week_shorter_thursday">"Jue."</string>
- <string name="day_of_week_shorter_friday">"V"</string>
- <string name="day_of_week_shorter_saturday">"Sáb."</string>
- <string name="day_of_week_shortest_sunday">"D"</string>
- <string name="day_of_week_shortest_monday">"L"</string>
- <string name="day_of_week_shortest_tuesday">"Mar."</string>
- <string name="day_of_week_shortest_wednesday">"M"</string>
- <string name="day_of_week_shortest_thursday">"Jue."</string>
- <string name="day_of_week_shortest_friday">"V"</string>
- <string name="day_of_week_shortest_saturday">"D"</string>
- <string name="month_long_january">"Enero"</string>
- <string name="month_long_february">"Febrero"</string>
- <string name="month_long_march">"Marzo"</string>
- <string name="month_long_april">"Abril"</string>
- <string name="month_long_may">"Mayo"</string>
- <string name="month_long_june">"Junio"</string>
- <string name="month_long_july">"Julio"</string>
- <string name="month_long_august">"Agosto"</string>
- <string name="month_long_september">"Septiembre"</string>
- <string name="month_long_october">"Octubre"</string>
- <string name="month_long_november">"Noviembre"</string>
- <string name="month_long_december">"Diciembre"</string>
- <string name="month_medium_january">"Ene."</string>
- <string name="month_medium_february">"Feb."</string>
- <string name="month_medium_march">"Mar."</string>
- <string name="month_medium_april">"Abr."</string>
- <string name="month_medium_may">"Mayo"</string>
- <string name="month_medium_june">"Jun."</string>
- <string name="month_medium_july">"Jul."</string>
- <string name="month_medium_august">"Ago."</string>
- <string name="month_medium_september">"Sep."</string>
- <string name="month_medium_october">"Oct."</string>
- <string name="month_medium_november">"Nov."</string>
- <string name="month_medium_december">"Dic."</string>
- <string name="month_shortest_january">"E"</string>
- <string name="month_shortest_february">"V"</string>
- <string name="month_shortest_march">"M"</string>
- <string name="month_shortest_april">"A"</string>
- <string name="month_shortest_may">"M"</string>
- <string name="month_shortest_june">"E"</string>
- <string name="month_shortest_july">"J"</string>
- <string name="month_shortest_august">"Ago."</string>
- <string name="month_shortest_september">"D"</string>
- <string name="month_shortest_october">"O"</string>
- <string name="month_shortest_november">"N"</string>
- <string name="month_shortest_december">"Dic."</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Seleccionar todos"</string>
diff --git a/core/res/res/values-es/donottranslate-cldr.xml b/core/res/res/values-es/donottranslate-cldr.xml
new file mode 100644
index 0000000..967a639
--- /dev/null
+++ b/core/res/res/values-es/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">enero</string>
+ <string name="month_long_standalone_february">febrero</string>
+ <string name="month_long_standalone_march">marzo</string>
+ <string name="month_long_standalone_april">abril</string>
+ <string name="month_long_standalone_may">mayo</string>
+ <string name="month_long_standalone_june">junio</string>
+ <string name="month_long_standalone_july">julio</string>
+ <string name="month_long_standalone_august">agosto</string>
+ <string name="month_long_standalone_september">septiembre</string>
+ <string name="month_long_standalone_october">octubre</string>
+ <string name="month_long_standalone_november">noviembre</string>
+ <string name="month_long_standalone_december">diciembre</string>
+
+ <string name="month_long_january">enero</string>
+ <string name="month_long_february">febrero</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">abril</string>
+ <string name="month_long_may">mayo</string>
+ <string name="month_long_june">junio</string>
+ <string name="month_long_july">julio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">septiembre</string>
+ <string name="month_long_october">octubre</string>
+ <string name="month_long_november">noviembre</string>
+ <string name="month_long_december">diciembre</string>
+
+ <string name="month_medium_january">ene</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">abr</string>
+ <string name="month_medium_may">may</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">oct</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">E</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domingo</string>
+ <string name="day_of_week_long_monday">lunes</string>
+ <string name="day_of_week_long_tuesday">martes</string>
+ <string name="day_of_week_long_wednesday">miércoles</string>
+ <string name="day_of_week_long_thursday">jueves</string>
+ <string name="day_of_week_long_friday">viernes</string>
+ <string name="day_of_week_long_saturday">sábado</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mié</string>
+ <string name="day_of_week_medium_thursday">jue</string>
+ <string name="day_of_week_medium_friday">vie</string>
+ <string name="day_of_week_medium_saturday">sáb</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mié</string>
+ <string name="day_of_week_short_thursday">jue</string>
+ <string name="day_of_week_short_friday">vie</string>
+ <string name="day_of_week_short_saturday">sáb</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">ayer</string>
+ <string name="today">hoy</string>
+ <string name="tomorrow">mañana</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B de %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a9f267a..c55e0ed 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Contraseña"</string>
<string name="lockscreen_glogin_submit_button">"Acceder"</string>
<string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña no válido"</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Cerrar notificaciones"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"intro"</string>
<string name="menu_delete_shortcut_label">"suprimir"</string>
<string name="search_go">"Buscar"</string>
- <string name="today">"Hoy"</string>
- <string name="yesterday">"Ayer"</string>
- <string name="tomorrow">"Mañana"</string>
<string name="oneMonthDurationPast">"Hace un mes"</string>
<string name="beforeOneMonthDurationPast">"Hace más de un mes"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"semanas"</string>
<string name="year">"año"</string>
<string name="years">"años"</string>
- <string name="sunday">"Domingo"</string>
- <string name="monday">"Lunes"</string>
- <string name="tuesday">"Martes"</string>
- <string name="wednesday">"Miércoles"</string>
- <string name="thursday">"Jueves"</string>
- <string name="friday">"Viernes"</string>
- <string name="saturday">"Sábado"</string>
<string name="every_weekday">"Todos los días laborables (Lun-Vie)"</string>
<string name="daily">"Diariamente"</string>
<string name="weekly">"Semanalmente, el <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Este vídeo no se puede transmitir al dispositivo."</string>
<string name="VideoView_error_text_unknown">"Este vídeo no se puede reproducir."</string>
<string name="VideoView_error_button">"Aceptar"</string>
- <string name="am">"a.m."</string>
- <string name="pm">"p.m."</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"mediodía"</string>
<string name="Noon">"Mediodía"</string>
<string name="midnight">"medianoche"</string>
<string name="Midnight">"Medianoche"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%b</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"Domingo"</string>
- <string name="day_of_week_long_monday">"Lunes"</string>
- <string name="day_of_week_long_tuesday">"Martes"</string>
- <string name="day_of_week_long_wednesday">"Miércoles"</string>
- <string name="day_of_week_long_thursday">"Jueves"</string>
- <string name="day_of_week_long_friday">"Viernes"</string>
- <string name="day_of_week_long_saturday">"Sábado"</string>
- <string name="day_of_week_medium_sunday">"Dom"</string>
- <string name="day_of_week_medium_monday">"Lun"</string>
- <string name="day_of_week_medium_tuesday">"Mar"</string>
- <string name="day_of_week_medium_wednesday">"Mié"</string>
- <string name="day_of_week_medium_thursday">"Jue"</string>
- <string name="day_of_week_medium_friday">"Vie"</string>
- <string name="day_of_week_medium_saturday">"Sáb"</string>
- <string name="day_of_week_short_sunday">"Do"</string>
- <string name="day_of_week_short_monday">"Lu"</string>
- <string name="day_of_week_short_tuesday">"Ma"</string>
- <string name="day_of_week_short_wednesday">"Mi"</string>
- <string name="day_of_week_short_thursday">"Ju"</string>
- <string name="day_of_week_short_friday">"Vi"</string>
- <string name="day_of_week_short_saturday">"Sá"</string>
- <string name="day_of_week_shorter_sunday">"Do"</string>
- <string name="day_of_week_shorter_monday">"L"</string>
- <string name="day_of_week_shorter_tuesday">"Ma"</string>
- <string name="day_of_week_shorter_wednesday">"Mi"</string>
- <string name="day_of_week_shorter_thursday">"Ju"</string>
- <string name="day_of_week_shorter_friday">"V"</string>
- <string name="day_of_week_shorter_saturday">"S"</string>
- <string name="day_of_week_shortest_sunday">"D"</string>
- <string name="day_of_week_shortest_monday">"Mz"</string>
- <string name="day_of_week_shortest_tuesday">"M"</string>
- <string name="day_of_week_shortest_wednesday">"Mi"</string>
- <string name="day_of_week_shortest_thursday">"M"</string>
- <string name="day_of_week_shortest_friday">"V"</string>
- <string name="day_of_week_shortest_saturday">"D"</string>
- <string name="month_long_january">"Enero"</string>
- <string name="month_long_february">"Febrero"</string>
- <string name="month_long_march">"Marzo"</string>
- <string name="month_long_april">"Abril"</string>
- <string name="month_long_may">"Mayo"</string>
- <string name="month_long_june">"Junio"</string>
- <string name="month_long_july">"Julio"</string>
- <string name="month_long_august">"Agosto"</string>
- <string name="month_long_september">"Septiembre"</string>
- <string name="month_long_october">"Octubre"</string>
- <string name="month_long_november">"Noviembre"</string>
- <string name="month_long_december">"Diciembre"</string>
- <string name="month_medium_january">"Ene"</string>
- <string name="month_medium_february">"Feb"</string>
- <string name="month_medium_march">"Mar"</string>
- <string name="month_medium_april">"Abr"</string>
- <string name="month_medium_may">"May"</string>
- <string name="month_medium_june">"Jun"</string>
- <string name="month_medium_july">"Jul"</string>
- <string name="month_medium_august">"Ago"</string>
- <string name="month_medium_september">"Sep"</string>
- <string name="month_medium_october">"Oct"</string>
- <string name="month_medium_november">"Nov"</string>
- <string name="month_medium_december">"Dic"</string>
- <string name="month_shortest_january">"E"</string>
- <string name="month_shortest_february">"V"</string>
- <string name="month_shortest_march">"Mz"</string>
- <string name="month_shortest_april">"A"</string>
- <string name="month_shortest_may">"My"</string>
- <string name="month_shortest_june">"J"</string>
- <string name="month_shortest_july">"E"</string>
- <string name="month_shortest_august">"Ag"</string>
- <string name="month_shortest_september">"S"</string>
- <string name="month_shortest_october">"O"</string>
- <string name="month_shortest_november">"N"</string>
- <string name="month_shortest_december">"D"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Seleccionar todo"</string>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
new file mode 100644
index 0000000..ae28635
--- /dev/null
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">tammikuu</string>
+ <string name="month_long_standalone_february">helmikuu</string>
+ <string name="month_long_standalone_march">maaliskuu</string>
+ <string name="month_long_standalone_april">huhtikuu</string>
+ <string name="month_long_standalone_may">toukokuu</string>
+ <string name="month_long_standalone_june">kesäkuu</string>
+ <string name="month_long_standalone_july">heinäkuu</string>
+ <string name="month_long_standalone_august">elokuu</string>
+ <string name="month_long_standalone_september">syyskuu</string>
+ <string name="month_long_standalone_october">lokakuu</string>
+ <string name="month_long_standalone_november">marraskuu</string>
+ <string name="month_long_standalone_december">joulukuu</string>
+
+ <string name="month_long_january">tammikuuta</string>
+ <string name="month_long_february">helmikuuta</string>
+ <string name="month_long_march">maaliskuuta</string>
+ <string name="month_long_april">huhtikuuta</string>
+ <string name="month_long_may">toukokuuta</string>
+ <string name="month_long_june">kesäkuuta</string>
+ <string name="month_long_july">heinäkuuta</string>
+ <string name="month_long_august">elokuuta</string>
+ <string name="month_long_september">syyskuuta</string>
+ <string name="month_long_october">lokakuuta</string>
+ <string name="month_long_november">marraskuuta</string>
+ <string name="month_long_december">joulukuuta</string>
+
+ <string name="month_medium_january">tammikuuta</string>
+ <string name="month_medium_february">helmikuuta</string>
+ <string name="month_medium_march">maaliskuuta</string>
+ <string name="month_medium_april">huhtikuuta</string>
+ <string name="month_medium_may">toukokuuta</string>
+ <string name="month_medium_june">kesäkuuta</string>
+ <string name="month_medium_july">heinäkuuta</string>
+ <string name="month_medium_august">elokuuta</string>
+ <string name="month_medium_september">syyskuuta</string>
+ <string name="month_medium_october">lokakuuta</string>
+ <string name="month_medium_november">marraskuuta</string>
+ <string name="month_medium_december">joulukuuta</string>
+
+ <string name="month_shortest_january">T</string>
+ <string name="month_shortest_february">H</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">H</string>
+ <string name="month_shortest_may">T</string>
+ <string name="month_shortest_june">K</string>
+ <string name="month_shortest_july">H</string>
+ <string name="month_shortest_august">E</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">L</string>
+ <string name="month_shortest_november">M</string>
+ <string name="month_shortest_december">J</string>
+
+ <string name="day_of_week_long_sunday">sunnuntaina</string>
+ <string name="day_of_week_long_monday">maanantaina</string>
+ <string name="day_of_week_long_tuesday">tiistaina</string>
+ <string name="day_of_week_long_wednesday">keskiviikkona</string>
+ <string name="day_of_week_long_thursday">torstaina</string>
+ <string name="day_of_week_long_friday">perjantaina</string>
+ <string name="day_of_week_long_saturday">lauantaina</string>
+
+ <string name="day_of_week_medium_sunday">su</string>
+ <string name="day_of_week_medium_monday">ma</string>
+ <string name="day_of_week_medium_tuesday">ti</string>
+ <string name="day_of_week_medium_wednesday">ke</string>
+ <string name="day_of_week_medium_thursday">to</string>
+ <string name="day_of_week_medium_friday">pe</string>
+ <string name="day_of_week_medium_saturday">la</string>
+
+ <string name="day_of_week_short_sunday">su</string>
+ <string name="day_of_week_short_monday">ma</string>
+ <string name="day_of_week_short_tuesday">ti</string>
+ <string name="day_of_week_short_wednesday">ke</string>
+ <string name="day_of_week_short_thursday">to</string>
+ <string name="day_of_week_short_friday">pe</string>
+ <string name="day_of_week_short_saturday">la</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">K</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">L</string>
+
+ <string name="am">ap.</string>
+ <string name="pm">ip.</string>
+ <string name="yesterday">eilen</string>
+ <string name="today">tänään</string>
+ <string name="tomorrow">huomenna</string>
+
+ <string name="hour_minute_ampm">%-k.%M</string>
+ <string name="hour_minute_cap_ampm">%-k.%M</string>
+ <string name="numeric_date">%-e.%-m.%Y</string>
+ <string name="numeric_date_format">d.M.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%-k.%M.%S</string>
+ <string name="date_and_time">%-k.%M.%S %-e.%-m.%Y</string>
+ <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%-b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr-rBE/donottranslate-cldr.xml b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
new file mode 100644
index 0000000..b540336
--- /dev/null
+++ b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvier</string>
+ <string name="month_long_standalone_february">février</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avril</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juin</string>
+ <string name="month_long_standalone_july">juillet</string>
+ <string name="month_long_standalone_august">août</string>
+ <string name="month_long_standalone_september">septembre</string>
+ <string name="month_long_standalone_october">octobre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">décembre</string>
+
+ <string name="month_long_january">janvier</string>
+ <string name="month_long_february">février</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avril</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juin</string>
+ <string name="month_long_july">juillet</string>
+ <string name="month_long_august">août</string>
+ <string name="month_long_september">septembre</string>
+ <string name="month_long_october">octobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">décembre</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">févr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juin</string>
+ <string name="month_medium_july">juil.</string>
+ <string name="month_medium_august">août</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">déc.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">dimanche</string>
+ <string name="day_of_week_long_monday">lundi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mercredi</string>
+ <string name="day_of_week_long_thursday">jeudi</string>
+ <string name="day_of_week_long_friday">vendredi</string>
+ <string name="day_of_week_long_saturday">samedi</string>
+
+ <string name="day_of_week_medium_sunday">dim.</string>
+ <string name="day_of_week_medium_monday">lun.</string>
+ <string name="day_of_week_medium_tuesday">mar.</string>
+ <string name="day_of_week_medium_wednesday">mer.</string>
+ <string name="day_of_week_medium_thursday">jeu.</string>
+ <string name="day_of_week_medium_friday">ven.</string>
+ <string name="day_of_week_medium_saturday">sam.</string>
+
+ <string name="day_of_week_short_sunday">dim.</string>
+ <string name="day_of_week_short_monday">lun.</string>
+ <string name="day_of_week_short_tuesday">mar.</string>
+ <string name="day_of_week_short_wednesday">mer.</string>
+ <string name="day_of_week_short_thursday">jeu.</string>
+ <string name="day_of_week_short_friday">ven.</string>
+ <string name="day_of_week_short_saturday">sam.</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">matin</string>
+ <string name="pm">soir</string>
+ <string name="yesterday">hier</string>
+ <string name="today">aujourd’hui</string>
+ <string name="tomorrow">demain</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%-e/%m/%Y</string>
+ <string name="numeric_date_format">d/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr-rCA/donottranslate-cldr.xml b/core/res/res/values-fr-rCA/donottranslate-cldr.xml
new file mode 100644
index 0000000..5fa5d54
--- /dev/null
+++ b/core/res/res/values-fr-rCA/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvier</string>
+ <string name="month_long_standalone_february">février</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avril</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juin</string>
+ <string name="month_long_standalone_july">juillet</string>
+ <string name="month_long_standalone_august">août</string>
+ <string name="month_long_standalone_september">septembre</string>
+ <string name="month_long_standalone_october">octobre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">décembre</string>
+
+ <string name="month_long_january">janvier</string>
+ <string name="month_long_february">février</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avril</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juin</string>
+ <string name="month_long_july">juillet</string>
+ <string name="month_long_august">août</string>
+ <string name="month_long_september">septembre</string>
+ <string name="month_long_october">octobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">décembre</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">févr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juin</string>
+ <string name="month_medium_july">juil.</string>
+ <string name="month_medium_august">août</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">déc.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">dimanche</string>
+ <string name="day_of_week_long_monday">lundi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mercredi</string>
+ <string name="day_of_week_long_thursday">jeudi</string>
+ <string name="day_of_week_long_friday">vendredi</string>
+ <string name="day_of_week_long_saturday">samedi</string>
+
+ <string name="day_of_week_medium_sunday">dim.</string>
+ <string name="day_of_week_medium_monday">lun.</string>
+ <string name="day_of_week_medium_tuesday">mar.</string>
+ <string name="day_of_week_medium_wednesday">mer.</string>
+ <string name="day_of_week_medium_thursday">jeu.</string>
+ <string name="day_of_week_medium_friday">ven.</string>
+ <string name="day_of_week_medium_saturday">sam.</string>
+
+ <string name="day_of_week_short_sunday">dim.</string>
+ <string name="day_of_week_short_monday">lun.</string>
+ <string name="day_of_week_short_tuesday">mar.</string>
+ <string name="day_of_week_short_wednesday">mer.</string>
+ <string name="day_of_week_short_thursday">jeu.</string>
+ <string name="day_of_week_short_friday">ven.</string>
+ <string name="day_of_week_short_saturday">sam.</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">matin</string>
+ <string name="pm">soir</string>
+ <string name="yesterday">hier</string>
+ <string name="today">aujourd’hui</string>
+ <string name="tomorrow">demain</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%Y-%m-%d</string>
+ <string name="numeric_date_format">yyyy-MM-dd</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %Y-%m-%d</string>
+ <string name="abbrev_month_day_year">%Y-%m-%d</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr-rCH/donottranslate-cldr.xml b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
new file mode 100644
index 0000000..589c801
--- /dev/null
+++ b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvier</string>
+ <string name="month_long_standalone_february">février</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avril</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juin</string>
+ <string name="month_long_standalone_july">juillet</string>
+ <string name="month_long_standalone_august">août</string>
+ <string name="month_long_standalone_september">septembre</string>
+ <string name="month_long_standalone_october">octobre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">décembre</string>
+
+ <string name="month_long_january">janvier</string>
+ <string name="month_long_february">février</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avril</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juin</string>
+ <string name="month_long_july">juillet</string>
+ <string name="month_long_august">août</string>
+ <string name="month_long_september">septembre</string>
+ <string name="month_long_october">octobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">décembre</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">févr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juin</string>
+ <string name="month_medium_july">juil.</string>
+ <string name="month_medium_august">août</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">déc.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">dimanche</string>
+ <string name="day_of_week_long_monday">lundi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mercredi</string>
+ <string name="day_of_week_long_thursday">jeudi</string>
+ <string name="day_of_week_long_friday">vendredi</string>
+ <string name="day_of_week_long_saturday">samedi</string>
+
+ <string name="day_of_week_medium_sunday">dim.</string>
+ <string name="day_of_week_medium_monday">lun.</string>
+ <string name="day_of_week_medium_tuesday">mar.</string>
+ <string name="day_of_week_medium_wednesday">mer.</string>
+ <string name="day_of_week_medium_thursday">jeu.</string>
+ <string name="day_of_week_medium_friday">ven.</string>
+ <string name="day_of_week_medium_saturday">sam.</string>
+
+ <string name="day_of_week_short_sunday">dim.</string>
+ <string name="day_of_week_short_monday">lun.</string>
+ <string name="day_of_week_short_tuesday">mar.</string>
+ <string name="day_of_week_short_wednesday">mer.</string>
+ <string name="day_of_week_short_thursday">jeu.</string>
+ <string name="day_of_week_short_friday">ven.</string>
+ <string name="day_of_week_short_saturday">sam.</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">matin</string>
+ <string name="pm">soir</string>
+ <string name="yesterday">hier</string>
+ <string name="today">aujourd’hui</string>
+ <string name="tomorrow">demain</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr-rFR/donottranslate-cldr.xml b/core/res/res/values-fr-rFR/donottranslate-cldr.xml
new file mode 100644
index 0000000..1213ed8
--- /dev/null
+++ b/core/res/res/values-fr-rFR/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvier</string>
+ <string name="month_long_standalone_february">février</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avril</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juin</string>
+ <string name="month_long_standalone_july">juillet</string>
+ <string name="month_long_standalone_august">août</string>
+ <string name="month_long_standalone_september">septembre</string>
+ <string name="month_long_standalone_october">octobre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">décembre</string>
+
+ <string name="month_long_january">janvier</string>
+ <string name="month_long_february">février</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avril</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juin</string>
+ <string name="month_long_july">juillet</string>
+ <string name="month_long_august">août</string>
+ <string name="month_long_september">septembre</string>
+ <string name="month_long_october">octobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">décembre</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">févr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juin</string>
+ <string name="month_medium_july">juil.</string>
+ <string name="month_medium_august">août</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">déc.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">dimanche</string>
+ <string name="day_of_week_long_monday">lundi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mercredi</string>
+ <string name="day_of_week_long_thursday">jeudi</string>
+ <string name="day_of_week_long_friday">vendredi</string>
+ <string name="day_of_week_long_saturday">samedi</string>
+
+ <string name="day_of_week_medium_sunday">dim.</string>
+ <string name="day_of_week_medium_monday">lun.</string>
+ <string name="day_of_week_medium_tuesday">mar.</string>
+ <string name="day_of_week_medium_wednesday">mer.</string>
+ <string name="day_of_week_medium_thursday">jeu.</string>
+ <string name="day_of_week_medium_friday">ven.</string>
+ <string name="day_of_week_medium_saturday">sam.</string>
+
+ <string name="day_of_week_short_sunday">dim.</string>
+ <string name="day_of_week_short_monday">lun.</string>
+ <string name="day_of_week_short_tuesday">mar.</string>
+ <string name="day_of_week_short_wednesday">mer.</string>
+ <string name="day_of_week_short_thursday">jeu.</string>
+ <string name="day_of_week_short_friday">ven.</string>
+ <string name="day_of_week_short_saturday">sam.</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">matin</string>
+ <string name="pm">soir</string>
+ <string name="yesterday">hier</string>
+ <string name="today">aujourd’hui</string>
+ <string name="tomorrow">demain</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr/donottranslate-cldr.xml b/core/res/res/values-fr/donottranslate-cldr.xml
new file mode 100644
index 0000000..1213ed8
--- /dev/null
+++ b/core/res/res/values-fr/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvier</string>
+ <string name="month_long_standalone_february">février</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avril</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juin</string>
+ <string name="month_long_standalone_july">juillet</string>
+ <string name="month_long_standalone_august">août</string>
+ <string name="month_long_standalone_september">septembre</string>
+ <string name="month_long_standalone_october">octobre</string>
+ <string name="month_long_standalone_november">novembre</string>
+ <string name="month_long_standalone_december">décembre</string>
+
+ <string name="month_long_january">janvier</string>
+ <string name="month_long_february">février</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avril</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juin</string>
+ <string name="month_long_july">juillet</string>
+ <string name="month_long_august">août</string>
+ <string name="month_long_september">septembre</string>
+ <string name="month_long_october">octobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">décembre</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">févr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juin</string>
+ <string name="month_medium_july">juil.</string>
+ <string name="month_medium_august">août</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">déc.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">dimanche</string>
+ <string name="day_of_week_long_monday">lundi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mercredi</string>
+ <string name="day_of_week_long_thursday">jeudi</string>
+ <string name="day_of_week_long_friday">vendredi</string>
+ <string name="day_of_week_long_saturday">samedi</string>
+
+ <string name="day_of_week_medium_sunday">dim.</string>
+ <string name="day_of_week_medium_monday">lun.</string>
+ <string name="day_of_week_medium_tuesday">mar.</string>
+ <string name="day_of_week_medium_wednesday">mer.</string>
+ <string name="day_of_week_medium_thursday">jeu.</string>
+ <string name="day_of_week_medium_friday">ven.</string>
+ <string name="day_of_week_medium_saturday">sam.</string>
+
+ <string name="day_of_week_short_sunday">dim.</string>
+ <string name="day_of_week_short_monday">lun.</string>
+ <string name="day_of_week_short_tuesday">mar.</string>
+ <string name="day_of_week_short_wednesday">mer.</string>
+ <string name="day_of_week_short_thursday">jeu.</string>
+ <string name="day_of_week_short_friday">ven.</string>
+ <string name="day_of_week_short_saturday">sam.</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">matin</string>
+ <string name="pm">soir</string>
+ <string name="yesterday">hier</string>
+ <string name="today">aujourd’hui</string>
+ <string name="tomorrow">demain</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c664d1a..736caf7 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Mot de passe"</string>
<string name="lockscreen_glogin_submit_button">"Se connecter"</string>
<string name="lockscreen_glogin_invalid_input">"Nom d\'utilisateur ou mot de passe incorrect."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Effacer les notifications"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"entrée"</string>
<string name="menu_delete_shortcut_label">"supprimer"</string>
<string name="search_go">"Rechercher"</string>
- <string name="today">"Aujourd\'hui"</string>
- <string name="yesterday">"Hier"</string>
- <string name="tomorrow">"Demain"</string>
<string name="oneMonthDurationPast">"Il y a 1 mois"</string>
<string name="beforeOneMonthDurationPast">"Il y a plus d\'un mois"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"semaines"</string>
<string name="year">"année"</string>
<string name="years">"années"</string>
- <string name="sunday">"dimanche"</string>
- <string name="monday">"lundi"</string>
- <string name="tuesday">"mardi"</string>
- <string name="wednesday">"mercredi"</string>
- <string name="thursday">"jeudi"</string>
- <string name="friday">"vendredi"</string>
- <string name="saturday">"samedi"</string>
<string name="every_weekday">"Tous les jours ouvrés (lun.- ven.)"</string>
<string name="daily">"Tous les jours"</string>
<string name="weekly">"Toutes les semaines le <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Désolé, cette vidéo ne peut être lue sur cet appareil."</string>
<string name="VideoView_error_text_unknown">"Désolé, impossible de lire cette vidéo."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"midi"</string>
<string name="Noon">"Midi"</string>
<string name="midnight">"minuit"</string>
<string name="Midnight">"Minuit"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"dimanche"</string>
- <string name="day_of_week_long_monday">"lundi"</string>
- <string name="day_of_week_long_tuesday">"mardi"</string>
- <string name="day_of_week_long_wednesday">"mercredi"</string>
- <string name="day_of_week_long_thursday">"jeudi"</string>
- <string name="day_of_week_long_friday">"vendredi"</string>
- <string name="day_of_week_long_saturday">"samedi"</string>
- <string name="day_of_week_medium_sunday">"dim."</string>
- <string name="day_of_week_medium_monday">"Lun"</string>
- <string name="day_of_week_medium_tuesday">"Mar"</string>
- <string name="day_of_week_medium_wednesday">"Mer"</string>
- <string name="day_of_week_medium_thursday">"Jeu"</string>
- <string name="day_of_week_medium_friday">"Ven"</string>
- <string name="day_of_week_medium_saturday">"Sam"</string>
- <string name="day_of_week_short_sunday">"Dim"</string>
- <string name="day_of_week_short_monday">"Lun"</string>
- <string name="day_of_week_short_tuesday">"Mar"</string>
- <string name="day_of_week_short_wednesday">"Mer"</string>
- <string name="day_of_week_short_thursday">"Jeu"</string>
- <string name="day_of_week_short_friday">"Ven"</string>
- <string name="day_of_week_short_saturday">"Sam"</string>
- <string name="day_of_week_shorter_sunday">"Dim"</string>
- <string name="day_of_week_shorter_monday">"Lun"</string>
- <string name="day_of_week_shorter_tuesday">"Mar"</string>
- <string name="day_of_week_shorter_wednesday">"Mer"</string>
- <string name="day_of_week_shorter_thursday">"Jeu"</string>
- <string name="day_of_week_shorter_friday">"Ven"</string>
- <string name="day_of_week_shorter_saturday">"sam."</string>
- <string name="day_of_week_shortest_sunday">"Dim"</string>
- <string name="day_of_week_shortest_monday">"Lun"</string>
- <string name="day_of_week_shortest_tuesday">"Mar"</string>
- <string name="day_of_week_shortest_wednesday">"Mer"</string>
- <string name="day_of_week_shortest_thursday">"Jeu"</string>
- <string name="day_of_week_shortest_friday">"Ven"</string>
- <string name="day_of_week_shortest_saturday">"Sam"</string>
- <string name="month_long_january">"janvier"</string>
- <string name="month_long_february">"février"</string>
- <string name="month_long_march">"mars"</string>
- <string name="month_long_april">"avril"</string>
- <string name="month_long_may">"mai"</string>
- <string name="month_long_june">"juin"</string>
- <string name="month_long_july">"juillet"</string>
- <string name="month_long_august">"août"</string>
- <string name="month_long_september">"septembre"</string>
- <string name="month_long_october">"octobre"</string>
- <string name="month_long_november">"novembre"</string>
- <string name="month_long_december">"décembre"</string>
- <string name="month_medium_january">"janv."</string>
- <string name="month_medium_february">"févr."</string>
- <string name="month_medium_march">"mars"</string>
- <string name="month_medium_april">"avr."</string>
- <string name="month_medium_may">"mai"</string>
- <string name="month_medium_june">"juin"</string>
- <string name="month_medium_july">"juil."</string>
- <string name="month_medium_august">"août"</string>
- <string name="month_medium_september">"sept."</string>
- <string name="month_medium_october">"oct."</string>
- <string name="month_medium_november">"nov."</string>
- <string name="month_medium_december">"déc."</string>
- <string name="month_shortest_january">"jan."</string>
- <string name="month_shortest_february">"Ven"</string>
- <string name="month_shortest_march">"mars"</string>
- <string name="month_shortest_april">"avr."</string>
- <string name="month_shortest_may">"mai"</string>
- <string name="month_shortest_june">"juin"</string>
- <string name="month_shortest_july">"juil."</string>
- <string name="month_shortest_august">"août"</string>
- <string name="month_shortest_september">"sept."</string>
- <string name="month_shortest_october">"oct."</string>
- <string name="month_shortest_november">"nov."</string>
- <string name="month_shortest_december">"déc."</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Tout sélectionner"</string>
diff --git a/core/res/res/values-he-rIL/donottranslate-cldr.xml b/core/res/res/values-he-rIL/donottranslate-cldr.xml
new file mode 100644
index 0000000..1b1aafa
--- /dev/null
+++ b/core/res/res/values-he-rIL/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">ינואר</string>
+ <string name="month_long_standalone_february">פברואר</string>
+ <string name="month_long_standalone_march">מרס</string>
+ <string name="month_long_standalone_april">אפריל</string>
+ <string name="month_long_standalone_may">מאי</string>
+ <string name="month_long_standalone_june">יוני</string>
+ <string name="month_long_standalone_july">יולי</string>
+ <string name="month_long_standalone_august">אוגוסט</string>
+ <string name="month_long_standalone_september">ספטמבר</string>
+ <string name="month_long_standalone_october">אוקטובר</string>
+ <string name="month_long_standalone_november">נובמבר</string>
+ <string name="month_long_standalone_december">דצמבר</string>
+
+ <string name="month_long_january">ינואר</string>
+ <string name="month_long_february">פברואר</string>
+ <string name="month_long_march">מרס</string>
+ <string name="month_long_april">אפריל</string>
+ <string name="month_long_may">מאי</string>
+ <string name="month_long_june">יוני</string>
+ <string name="month_long_july">יולי</string>
+ <string name="month_long_august">אוגוסט</string>
+ <string name="month_long_september">ספטמבר</string>
+ <string name="month_long_october">אוקטובר</string>
+ <string name="month_long_november">נובמבר</string>
+ <string name="month_long_december">דצמבר</string>
+
+ <string name="month_medium_january">ינו</string>
+ <string name="month_medium_february">פבר</string>
+ <string name="month_medium_march">מרס</string>
+ <string name="month_medium_april">אפר</string>
+ <string name="month_medium_may">מאי</string>
+ <string name="month_medium_june">יונ</string>
+ <string name="month_medium_july">יול</string>
+ <string name="month_medium_august">אוג</string>
+ <string name="month_medium_september">ספט</string>
+ <string name="month_medium_october">אוק</string>
+ <string name="month_medium_november">נוב</string>
+ <string name="month_medium_december">דצמ</string>
+
+ <string name="month_shortest_january">1</string>
+ <string name="month_shortest_february">2</string>
+ <string name="month_shortest_march">3</string>
+ <string name="month_shortest_april">4</string>
+ <string name="month_shortest_may">5</string>
+ <string name="month_shortest_june">6</string>
+ <string name="month_shortest_july">7</string>
+ <string name="month_shortest_august">8</string>
+ <string name="month_shortest_september">9</string>
+ <string name="month_shortest_october">10</string>
+ <string name="month_shortest_november">11</string>
+ <string name="month_shortest_december">12</string>
+
+ <string name="day_of_week_long_sunday">יום ראשון</string>
+ <string name="day_of_week_long_monday">יום שני</string>
+ <string name="day_of_week_long_tuesday">יום שלישי</string>
+ <string name="day_of_week_long_wednesday">יום רביעי</string>
+ <string name="day_of_week_long_thursday">יום חמישי</string>
+ <string name="day_of_week_long_friday">יום שישי</string>
+ <string name="day_of_week_long_saturday">יום שבת</string>
+
+ <string name="day_of_week_medium_sunday">יום א'</string>
+ <string name="day_of_week_medium_monday">יום ב'</string>
+ <string name="day_of_week_medium_tuesday">יום ג'</string>
+ <string name="day_of_week_medium_wednesday">יום ד'</string>
+ <string name="day_of_week_medium_thursday">יום ה'</string>
+ <string name="day_of_week_medium_friday">יום ו'</string>
+ <string name="day_of_week_medium_saturday">שבת</string>
+
+ <string name="day_of_week_short_sunday">יום א'</string>
+ <string name="day_of_week_short_monday">יום ב'</string>
+ <string name="day_of_week_short_tuesday">יום ג'</string>
+ <string name="day_of_week_short_wednesday">יום ד'</string>
+ <string name="day_of_week_short_thursday">יום ה'</string>
+ <string name="day_of_week_short_friday">יום ו'</string>
+ <string name="day_of_week_short_saturday">שבת</string>
+
+ <string name="day_of_week_shortest_sunday">א</string>
+ <string name="day_of_week_shortest_monday">ב</string>
+ <string name="day_of_week_shortest_tuesday">ג</string>
+ <string name="day_of_week_shortest_wednesday">ד</string>
+ <string name="day_of_week_shortest_thursday">ה</string>
+ <string name="day_of_week_shortest_friday">ו</string>
+ <string name="day_of_week_shortest_saturday">ש</string>
+
+ <string name="am">לפנה"צ</string>
+ <string name="pm">אחה"צ</string>
+ <string name="yesterday">אתמול</string>
+ <string name="today">היום</string>
+ <string name="tomorrow">מחר</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e ב%B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e.%-m.%Y</string>
+ <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+ <string name="month_day">%-e ב%B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
new file mode 100644
index 0000000..8c6a34f7
--- /dev/null
+++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">जनवरी</string>
+ <string name="month_long_standalone_february">फरवरी</string>
+ <string name="month_long_standalone_march">मार्च</string>
+ <string name="month_long_standalone_april">अप्रैल</string>
+ <string name="month_long_standalone_may">मई</string>
+ <string name="month_long_standalone_june">जून</string>
+ <string name="month_long_standalone_july">जुलाई</string>
+ <string name="month_long_standalone_august">अगस्त</string>
+ <string name="month_long_standalone_september">सितम्बर</string>
+ <string name="month_long_standalone_october">अक्तूबर</string>
+ <string name="month_long_standalone_november">नवम्बर</string>
+ <string name="month_long_standalone_december">दिसम्बर</string>
+
+ <string name="month_long_january">जनवरी</string>
+ <string name="month_long_february">फरवरी</string>
+ <string name="month_long_march">मार्च</string>
+ <string name="month_long_april">अप्रैल</string>
+ <string name="month_long_may">मई</string>
+ <string name="month_long_june">जून</string>
+ <string name="month_long_july">जुलाई</string>
+ <string name="month_long_august">अगस्त</string>
+ <string name="month_long_september">सितम्बर</string>
+ <string name="month_long_october">अक्तूबर</string>
+ <string name="month_long_november">नवम्बर</string>
+ <string name="month_long_december">दिसम्बर</string>
+
+ <string name="month_medium_january">जनवरी</string>
+ <string name="month_medium_february">फरवरी</string>
+ <string name="month_medium_march">मार्च</string>
+ <string name="month_medium_april">अप्रैल</string>
+ <string name="month_medium_may">मई</string>
+ <string name="month_medium_june">जून</string>
+ <string name="month_medium_july">जुलाई</string>
+ <string name="month_medium_august">अगस्त</string>
+ <string name="month_medium_september">सितम्बर</string>
+ <string name="month_medium_october">अक्तूबर</string>
+ <string name="month_medium_november">नवम्बर</string>
+ <string name="month_medium_december">दिसम्बर</string>
+
+ <string name="month_shortest_january">ज</string>
+ <string name="month_shortest_february">फ़</string>
+ <string name="month_shortest_march">मा</string>
+ <string name="month_shortest_april">अ</string>
+ <string name="month_shortest_may">म</string>
+ <string name="month_shortest_june">जू</string>
+ <string name="month_shortest_july">जु</string>
+ <string name="month_shortest_august">अ</string>
+ <string name="month_shortest_september">सि</string>
+ <string name="month_shortest_october">अ</string>
+ <string name="month_shortest_november">न</string>
+ <string name="month_shortest_december">दि</string>
+
+ <string name="day_of_week_long_sunday">रविवार</string>
+ <string name="day_of_week_long_monday">सोमवार</string>
+ <string name="day_of_week_long_tuesday">मंगलवार</string>
+ <string name="day_of_week_long_wednesday">बुधवार</string>
+ <string name="day_of_week_long_thursday">गुरुवार</string>
+ <string name="day_of_week_long_friday">शुक्रवार</string>
+ <string name="day_of_week_long_saturday">शनिवार</string>
+
+ <string name="day_of_week_medium_sunday">रवि</string>
+ <string name="day_of_week_medium_monday">सोम</string>
+ <string name="day_of_week_medium_tuesday">मंगल</string>
+ <string name="day_of_week_medium_wednesday">बुध</string>
+ <string name="day_of_week_medium_thursday">गुरु</string>
+ <string name="day_of_week_medium_friday">शुक्र</string>
+ <string name="day_of_week_medium_saturday">शनि</string>
+
+ <string name="day_of_week_short_sunday">रवि</string>
+ <string name="day_of_week_short_monday">सोम</string>
+ <string name="day_of_week_short_tuesday">मंगल</string>
+ <string name="day_of_week_short_wednesday">बुध</string>
+ <string name="day_of_week_short_thursday">गुरु</string>
+ <string name="day_of_week_short_friday">शुक्र</string>
+ <string name="day_of_week_short_saturday">शनि</string>
+
+ <string name="day_of_week_shortest_sunday">र</string>
+ <string name="day_of_week_shortest_monday">सो</string>
+ <string name="day_of_week_shortest_tuesday">मं</string>
+ <string name="day_of_week_shortest_wednesday">बु</string>
+ <string name="day_of_week_shortest_thursday">गु</string>
+ <string name="day_of_week_shortest_friday">शु</string>
+ <string name="day_of_week_shortest_saturday">श</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-e-%-m-%Y</string>
+ <string name="numeric_date_format">d-M-yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %d-%m-%Y</string>
+ <string name="abbrev_month_day_year">%d-%m-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
new file mode 100644
index 0000000..6085c6f
--- /dev/null
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">január</string>
+ <string name="month_long_standalone_february">február</string>
+ <string name="month_long_standalone_march">március</string>
+ <string name="month_long_standalone_april">április</string>
+ <string name="month_long_standalone_may">május</string>
+ <string name="month_long_standalone_june">június</string>
+ <string name="month_long_standalone_july">július</string>
+ <string name="month_long_standalone_august">augusztus</string>
+ <string name="month_long_standalone_september">szeptember</string>
+ <string name="month_long_standalone_october">október</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">január</string>
+ <string name="month_long_february">február</string>
+ <string name="month_long_march">március</string>
+ <string name="month_long_april">április</string>
+ <string name="month_long_may">május</string>
+ <string name="month_long_june">június</string>
+ <string name="month_long_july">július</string>
+ <string name="month_long_august">augusztus</string>
+ <string name="month_long_september">szeptember</string>
+ <string name="month_long_october">október</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">febr.</string>
+ <string name="month_medium_march">márc.</string>
+ <string name="month_medium_april">ápr.</string>
+ <string name="month_medium_may">máj.</string>
+ <string name="month_medium_june">jún.</string>
+ <string name="month_medium_july">júl.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">szept.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">Á</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">vasárnap</string>
+ <string name="day_of_week_long_monday">hétfő</string>
+ <string name="day_of_week_long_tuesday">kedd</string>
+ <string name="day_of_week_long_wednesday">szerda</string>
+ <string name="day_of_week_long_thursday">csütörtök</string>
+ <string name="day_of_week_long_friday">péntek</string>
+ <string name="day_of_week_long_saturday">szombat</string>
+
+ <string name="day_of_week_medium_sunday">V</string>
+ <string name="day_of_week_medium_monday">H</string>
+ <string name="day_of_week_medium_tuesday">K</string>
+ <string name="day_of_week_medium_wednesday">Sze</string>
+ <string name="day_of_week_medium_thursday">Cs</string>
+ <string name="day_of_week_medium_friday">P</string>
+ <string name="day_of_week_medium_saturday">Szo</string>
+
+ <string name="day_of_week_short_sunday">V</string>
+ <string name="day_of_week_short_monday">H</string>
+ <string name="day_of_week_short_tuesday">K</string>
+ <string name="day_of_week_short_wednesday">Sze</string>
+ <string name="day_of_week_short_thursday">Cs</string>
+ <string name="day_of_week_short_friday">P</string>
+ <string name="day_of_week_short_saturday">Szo</string>
+
+ <string name="day_of_week_shortest_sunday">V</string>
+ <string name="day_of_week_shortest_monday">H</string>
+ <string name="day_of_week_shortest_tuesday">K</string>
+ <string name="day_of_week_shortest_wednesday">S</string>
+ <string name="day_of_week_shortest_thursday">C</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">de.</string>
+ <string name="pm">du.</string>
+ <string name="yesterday">tegnap</string>
+ <string name="today">ma</string>
+ <string name="tomorrow">holnap</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%Y.%m.%d.</string>
+ <string name="numeric_date_format">yyyy.MM.dd.</string>
+ <string name="month_day_year">%Y. %B %-e.</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %Y.%m.%d.</string>
+ <string name="abbrev_month_day_year">%Y.%m.%d.</string>
+ <string name="month_day">%B %-e.</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e.</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml
new file mode 100644
index 0000000..0a15fed
--- /dev/null
+++ b/core/res/res/values-id-rID/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Januari</string>
+ <string name="month_long_standalone_february">Februari</string>
+ <string name="month_long_standalone_march">Maret</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">Mei</string>
+ <string name="month_long_standalone_june">Juni</string>
+ <string name="month_long_standalone_july">Juli</string>
+ <string name="month_long_standalone_august">Agustus</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">Oktober</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">Desember</string>
+
+ <string name="month_long_january">Januari</string>
+ <string name="month_long_february">Februari</string>
+ <string name="month_long_march">Maret</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">Mei</string>
+ <string name="month_long_june">Juni</string>
+ <string name="month_long_july">Juli</string>
+ <string name="month_long_august">Agustus</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">Oktober</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">Desember</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">Mei</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Agu</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Okt</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Des</string>
+
+ <string name="month_shortest_january">1</string>
+ <string name="month_shortest_february">2</string>
+ <string name="month_shortest_march">3</string>
+ <string name="month_shortest_april">4</string>
+ <string name="month_shortest_may">5</string>
+ <string name="month_shortest_june">6</string>
+ <string name="month_shortest_july">7</string>
+ <string name="month_shortest_august">8</string>
+ <string name="month_shortest_september">9</string>
+ <string name="month_shortest_october">10</string>
+ <string name="month_shortest_november">11</string>
+ <string name="month_shortest_december">12</string>
+
+ <string name="day_of_week_long_sunday">Minggu</string>
+ <string name="day_of_week_long_monday">Senin</string>
+ <string name="day_of_week_long_tuesday">Selasa</string>
+ <string name="day_of_week_long_wednesday">Rabu</string>
+ <string name="day_of_week_long_thursday">Kamis</string>
+ <string name="day_of_week_long_friday">Jumat</string>
+ <string name="day_of_week_long_saturday">Sabtu</string>
+
+ <string name="day_of_week_medium_sunday">Min</string>
+ <string name="day_of_week_medium_monday">Sen</string>
+ <string name="day_of_week_medium_tuesday">Sel</string>
+ <string name="day_of_week_medium_wednesday">Rab</string>
+ <string name="day_of_week_medium_thursday">Kam</string>
+ <string name="day_of_week_medium_friday">Jum</string>
+ <string name="day_of_week_medium_saturday">Sab</string>
+
+ <string name="day_of_week_short_sunday">Min</string>
+ <string name="day_of_week_short_monday">Sen</string>
+ <string name="day_of_week_short_tuesday">Sel</string>
+ <string name="day_of_week_short_wednesday">Rab</string>
+ <string name="day_of_week_short_thursday">Kam</string>
+ <string name="day_of_week_short_friday">Jum</string>
+ <string name="day_of_week_short_saturday">Sab</string>
+
+ <string name="day_of_week_shortest_sunday">1</string>
+ <string name="day_of_week_shortest_monday">2</string>
+ <string name="day_of_week_shortest_tuesday">3</string>
+ <string name="day_of_week_shortest_wednesday">4</string>
+ <string name="day_of_week_shortest_thursday">5</string>
+ <string name="day_of_week_shortest_friday">6</string>
+ <string name="day_of_week_shortest_saturday">7</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-it-rCH/donottranslate-cldr.xml b/core/res/res/values-it-rCH/donottranslate-cldr.xml
new file mode 100644
index 0000000..4129d6c
--- /dev/null
+++ b/core/res/res/values-it-rCH/donottranslate-cldr.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Gennaio</string>
+ <string name="month_long_standalone_february">Febbraio</string>
+ <string name="month_long_standalone_march">Marzo</string>
+ <string name="month_long_standalone_april">Aprile</string>
+ <string name="month_long_standalone_may">Maggio</string>
+ <string name="month_long_standalone_june">Giugno</string>
+ <string name="month_long_standalone_july">Luglio</string>
+
+ <string name="month_long_january">gennaio</string>
+ <string name="month_long_february">febbraio</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">aprile</string>
+ <string name="month_long_may">maggio</string>
+ <string name="month_long_june">giugno</string>
+ <string name="month_long_july">Luglio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">settembre</string>
+ <string name="month_long_october">ottobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">dicembre</string>
+
+ <string name="month_medium_january">gen</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">mag</string>
+ <string name="month_medium_june">giu</string>
+ <string name="month_medium_july">lug</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">set</string>
+ <string name="month_medium_october">ott</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">G</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">G</string>
+ <string name="month_shortest_july">L</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domenica</string>
+ <string name="day_of_week_long_monday">lunedì</string>
+ <string name="day_of_week_long_tuesday">martedì</string>
+ <string name="day_of_week_long_wednesday">mercoledì</string>
+ <string name="day_of_week_long_thursday">giovedì</string>
+ <string name="day_of_week_long_friday">venerdì</string>
+ <string name="day_of_week_long_saturday">sabato</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mer</string>
+ <string name="day_of_week_medium_thursday">gio</string>
+ <string name="day_of_week_medium_friday">ven</string>
+ <string name="day_of_week_medium_saturday">sab</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mer</string>
+ <string name="day_of_week_short_thursday">gio</string>
+ <string name="day_of_week_short_friday">ven</string>
+ <string name="day_of_week_short_saturday">sab</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">G</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">m.</string>
+ <string name="pm">p.</string>
+ <string name="yesterday">ieri</string>
+ <string name="today">oggi</string>
+ <string name="tomorrow">domani</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %-e-%b-%Y</string>
+ <string name="abbrev_month_day_year">%-e-%b-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-it-rIT/donottranslate-cldr.xml b/core/res/res/values-it-rIT/donottranslate-cldr.xml
new file mode 100644
index 0000000..e3dd747
--- /dev/null
+++ b/core/res/res/values-it-rIT/donottranslate-cldr.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Gennaio</string>
+ <string name="month_long_standalone_february">Febbraio</string>
+ <string name="month_long_standalone_march">Marzo</string>
+ <string name="month_long_standalone_april">Aprile</string>
+ <string name="month_long_standalone_may">Maggio</string>
+ <string name="month_long_standalone_june">Giugno</string>
+ <string name="month_long_standalone_july">Luglio</string>
+
+ <string name="month_long_january">gennaio</string>
+ <string name="month_long_february">febbraio</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">aprile</string>
+ <string name="month_long_may">maggio</string>
+ <string name="month_long_june">giugno</string>
+ <string name="month_long_july">Luglio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">settembre</string>
+ <string name="month_long_october">ottobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">dicembre</string>
+
+ <string name="month_medium_january">gen</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">mag</string>
+ <string name="month_medium_june">giu</string>
+ <string name="month_medium_july">lug</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">set</string>
+ <string name="month_medium_october">ott</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">G</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">G</string>
+ <string name="month_shortest_july">L</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domenica</string>
+ <string name="day_of_week_long_monday">lunedì</string>
+ <string name="day_of_week_long_tuesday">martedì</string>
+ <string name="day_of_week_long_wednesday">mercoledì</string>
+ <string name="day_of_week_long_thursday">giovedì</string>
+ <string name="day_of_week_long_friday">venerdì</string>
+ <string name="day_of_week_long_saturday">sabato</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mer</string>
+ <string name="day_of_week_medium_thursday">gio</string>
+ <string name="day_of_week_medium_friday">ven</string>
+ <string name="day_of_week_medium_saturday">sab</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mer</string>
+ <string name="day_of_week_short_thursday">gio</string>
+ <string name="day_of_week_short_friday">ven</string>
+ <string name="day_of_week_short_saturday">sab</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">G</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">m.</string>
+ <string name="pm">p.</string>
+ <string name="yesterday">ieri</string>
+ <string name="today">oggi</string>
+ <string name="tomorrow">domani</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %d/%b/%Y</string>
+ <string name="abbrev_month_day_year">%d/%b/%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
new file mode 100644
index 0000000..e3dd747
--- /dev/null
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Gennaio</string>
+ <string name="month_long_standalone_february">Febbraio</string>
+ <string name="month_long_standalone_march">Marzo</string>
+ <string name="month_long_standalone_april">Aprile</string>
+ <string name="month_long_standalone_may">Maggio</string>
+ <string name="month_long_standalone_june">Giugno</string>
+ <string name="month_long_standalone_july">Luglio</string>
+
+ <string name="month_long_january">gennaio</string>
+ <string name="month_long_february">febbraio</string>
+ <string name="month_long_march">marzo</string>
+ <string name="month_long_april">aprile</string>
+ <string name="month_long_may">maggio</string>
+ <string name="month_long_june">giugno</string>
+ <string name="month_long_july">Luglio</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">settembre</string>
+ <string name="month_long_october">ottobre</string>
+ <string name="month_long_november">novembre</string>
+ <string name="month_long_december">dicembre</string>
+
+ <string name="month_medium_january">gen</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">mag</string>
+ <string name="month_medium_june">giu</string>
+ <string name="month_medium_july">lug</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">set</string>
+ <string name="month_medium_october">ott</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dic</string>
+
+ <string name="month_shortest_january">G</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">G</string>
+ <string name="month_shortest_july">L</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domenica</string>
+ <string name="day_of_week_long_monday">lunedì</string>
+ <string name="day_of_week_long_tuesday">martedì</string>
+ <string name="day_of_week_long_wednesday">mercoledì</string>
+ <string name="day_of_week_long_thursday">giovedì</string>
+ <string name="day_of_week_long_friday">venerdì</string>
+ <string name="day_of_week_long_saturday">sabato</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">lun</string>
+ <string name="day_of_week_medium_tuesday">mar</string>
+ <string name="day_of_week_medium_wednesday">mer</string>
+ <string name="day_of_week_medium_thursday">gio</string>
+ <string name="day_of_week_medium_friday">ven</string>
+ <string name="day_of_week_medium_saturday">sab</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">lun</string>
+ <string name="day_of_week_short_tuesday">mar</string>
+ <string name="day_of_week_short_wednesday">mer</string>
+ <string name="day_of_week_short_thursday">gio</string>
+ <string name="day_of_week_short_friday">ven</string>
+ <string name="day_of_week_short_saturday">sab</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">G</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">m.</string>
+ <string name="pm">p.</string>
+ <string name="yesterday">ieri</string>
+ <string name="today">oggi</string>
+ <string name="tomorrow">domani</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %d/%b/%Y</string>
+ <string name="abbrev_month_day_year">%d/%b/%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f80a4f4..cb040f2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Password"</string>
<string name="lockscreen_glogin_submit_button">"Accedi"</string>
<string name="lockscreen_glogin_invalid_input">"Password o nome utente non valido."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Cancella notifiche"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"Invio"</string>
<string name="menu_delete_shortcut_label">"Canc"</string>
<string name="search_go">"Cerca"</string>
- <string name="today">"Oggi"</string>
- <string name="yesterday">"Ieri"</string>
- <string name="tomorrow">"Domani"</string>
<string name="oneMonthDurationPast">"1 mese fa"</string>
<string name="beforeOneMonthDurationPast">"Oltre 1 mese fa"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"settimane"</string>
<string name="year">"anno"</string>
<string name="years">"anni"</string>
- <string name="sunday">"Domenica"</string>
- <string name="monday">"Lunedì"</string>
- <string name="tuesday">"Martedì"</string>
- <string name="wednesday">"Mercoledì"</string>
- <string name="thursday">"Giovedì"</string>
- <string name="friday">"Venerdì"</string>
- <string name="saturday">"Sabato"</string>
<string name="every_weekday">"Ogni giorno feriale (lun-ven)"</string>
<string name="daily">"Quotidianamente"</string>
<string name="weekly">"Ogni settimana il <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Spiacenti, questo video non è valido per lo streaming su questo dispositivo."</string>
<string name="VideoView_error_text_unknown">"Spiacenti. Impossibile riprodurre il video."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"mezzogiorno"</string>
<string name="Noon">"Mezzogiorno"</string>
<string name="midnight">"mezzanotte"</string>
<string name="Midnight">"Mezzanotte"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"Domenica"</string>
- <string name="day_of_week_long_monday">"Lunedì"</string>
- <string name="day_of_week_long_tuesday">"Martedì"</string>
- <string name="day_of_week_long_wednesday">"Mercoledì"</string>
- <string name="day_of_week_long_thursday">"Giovedì"</string>
- <string name="day_of_week_long_friday">"Venerdì"</string>
- <string name="day_of_week_long_saturday">"Sabato"</string>
- <string name="day_of_week_medium_sunday">"Dom"</string>
- <string name="day_of_week_medium_monday">"Lun"</string>
- <string name="day_of_week_medium_tuesday">"Mar"</string>
- <string name="day_of_week_medium_wednesday">"Mer"</string>
- <string name="day_of_week_medium_thursday">"Gio"</string>
- <string name="day_of_week_medium_friday">"Ven"</string>
- <string name="day_of_week_medium_saturday">"Sab"</string>
- <string name="day_of_week_short_sunday">"Do"</string>
- <string name="day_of_week_short_monday">"Lu"</string>
- <string name="day_of_week_short_tuesday">"Ma"</string>
- <string name="day_of_week_short_wednesday">"Me"</string>
- <string name="day_of_week_short_thursday">"Gi"</string>
- <string name="day_of_week_short_friday">"Ve"</string>
- <string name="day_of_week_short_saturday">"Sa"</string>
- <string name="day_of_week_shorter_sunday">"Do"</string>
- <string name="day_of_week_shorter_monday">"Lu"</string>
- <string name="day_of_week_shorter_tuesday">"Ma"</string>
- <string name="day_of_week_shorter_wednesday">"Me"</string>
- <string name="day_of_week_shorter_thursday">"Gi"</string>
- <string name="day_of_week_shorter_friday">"V"</string>
- <string name="day_of_week_shorter_saturday">"Sa"</string>
- <string name="day_of_week_shortest_sunday">"D"</string>
- <string name="day_of_week_shortest_monday">"Lun"</string>
- <string name="day_of_week_shortest_tuesday">"M"</string>
- <string name="day_of_week_shortest_wednesday">"Me"</string>
- <string name="day_of_week_shortest_thursday">"G"</string>
- <string name="day_of_week_shortest_friday">"V"</string>
- <string name="day_of_week_shortest_saturday">"Sa"</string>
- <string name="month_long_january">"Gennaio"</string>
- <string name="month_long_february">"Febbraio"</string>
- <string name="month_long_march">"Marzo"</string>
- <string name="month_long_april">"Aprile"</string>
- <string name="month_long_may">"Maggio"</string>
- <string name="month_long_june">"Giugno"</string>
- <string name="month_long_july">"Luglio"</string>
- <string name="month_long_august">"Agosto"</string>
- <string name="month_long_september">"Settembre"</string>
- <string name="month_long_october">"Ottobre"</string>
- <string name="month_long_november">"Novembre"</string>
- <string name="month_long_december">"Dicembre"</string>
- <string name="month_medium_january">"Gen"</string>
- <string name="month_medium_february">"Feb"</string>
- <string name="month_medium_march">"Mar"</string>
- <string name="month_medium_april">"Apr"</string>
- <string name="month_medium_may">"Mag"</string>
- <string name="month_medium_june">"Giu"</string>
- <string name="month_medium_july">"Lug"</string>
- <string name="month_medium_august">"Ago"</string>
- <string name="month_medium_september">"Set"</string>
- <string name="month_medium_october">"Ott"</string>
- <string name="month_medium_november">"Nov"</string>
- <string name="month_medium_december">"Dic"</string>
- <string name="month_shortest_january">"G"</string>
- <string name="month_shortest_february">"F"</string>
- <string name="month_shortest_march">"M"</string>
- <string name="month_shortest_april">"Ap"</string>
- <string name="month_shortest_may">"Mag"</string>
- <string name="month_shortest_june">"Gi"</string>
- <string name="month_shortest_july">"Lug"</string>
- <string name="month_shortest_august">"Ago"</string>
- <string name="month_shortest_september">"Set"</string>
- <string name="month_shortest_october">"O"</string>
- <string name="month_shortest_november">"N"</string>
- <string name="month_shortest_december">"Di"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Seleziona tutto"</string>
diff --git a/core/res/res/values-ja-rJP/donottranslate-cldr.xml b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
new file mode 100644
index 0000000..b8e94fc
--- /dev/null
+++ b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">1月</string>
+ <string name="month_long_standalone_february">2月</string>
+ <string name="month_long_standalone_march">3月</string>
+ <string name="month_long_standalone_april">4月</string>
+ <string name="month_long_standalone_may">5月</string>
+ <string name="month_long_standalone_june">6月</string>
+ <string name="month_long_standalone_july">7月</string>
+ <string name="month_long_standalone_august">8月</string>
+ <string name="month_long_standalone_september">9月</string>
+ <string name="month_long_standalone_october">10月</string>
+ <string name="month_long_standalone_november">11月</string>
+ <string name="month_long_standalone_december">12月</string>
+
+ <string name="month_long_january">1月</string>
+ <string name="month_long_february">2月</string>
+ <string name="month_long_march">3月</string>
+ <string name="month_long_april">4月</string>
+ <string name="month_long_may">5月</string>
+ <string name="month_long_june">6月</string>
+ <string name="month_long_july">7月</string>
+ <string name="month_long_august">8月</string>
+ <string name="month_long_september">9月</string>
+ <string name="month_long_october">10月</string>
+ <string name="month_long_november">11月</string>
+ <string name="month_long_december">12月</string>
+
+ <string name="month_medium_january">1月</string>
+ <string name="month_medium_february">2月</string>
+ <string name="month_medium_march">3月</string>
+ <string name="month_medium_april">4月</string>
+ <string name="month_medium_may">5月</string>
+ <string name="month_medium_june">6月</string>
+ <string name="month_medium_july">7月</string>
+ <string name="month_medium_august">8月</string>
+ <string name="month_medium_september">9月</string>
+ <string name="month_medium_october">10月</string>
+ <string name="month_medium_november">11月</string>
+ <string name="month_medium_december">12月</string>
+
+ <string name="month_shortest_january">1</string>
+ <string name="month_shortest_february">2</string>
+ <string name="month_shortest_march">3</string>
+ <string name="month_shortest_april">4</string>
+ <string name="month_shortest_may">5</string>
+ <string name="month_shortest_june">6</string>
+ <string name="month_shortest_july">7</string>
+ <string name="month_shortest_august">8</string>
+ <string name="month_shortest_september">9</string>
+ <string name="month_shortest_october">10</string>
+ <string name="month_shortest_november">11</string>
+ <string name="month_shortest_december">12</string>
+
+ <string name="day_of_week_long_sunday">日曜日</string>
+ <string name="day_of_week_long_monday">月曜日</string>
+ <string name="day_of_week_long_tuesday">火曜日</string>
+ <string name="day_of_week_long_wednesday">水曜日</string>
+ <string name="day_of_week_long_thursday">木曜日</string>
+ <string name="day_of_week_long_friday">金曜日</string>
+ <string name="day_of_week_long_saturday">土曜日</string>
+
+ <string name="day_of_week_medium_sunday">日</string>
+ <string name="day_of_week_medium_monday">月</string>
+ <string name="day_of_week_medium_tuesday">火</string>
+ <string name="day_of_week_medium_wednesday">水</string>
+ <string name="day_of_week_medium_thursday">木</string>
+ <string name="day_of_week_medium_friday">金</string>
+ <string name="day_of_week_medium_saturday">土</string>
+
+ <string name="day_of_week_short_sunday">日</string>
+ <string name="day_of_week_short_monday">月</string>
+ <string name="day_of_week_short_tuesday">火</string>
+ <string name="day_of_week_short_wednesday">水</string>
+ <string name="day_of_week_short_thursday">木</string>
+ <string name="day_of_week_short_friday">金</string>
+ <string name="day_of_week_short_saturday">土</string>
+
+ <string name="day_of_week_shortest_sunday">日</string>
+ <string name="day_of_week_shortest_monday">月</string>
+ <string name="day_of_week_shortest_tuesday">火</string>
+ <string name="day_of_week_shortest_wednesday">水</string>
+ <string name="day_of_week_shortest_thursday">木</string>
+ <string name="day_of_week_shortest_friday">金</string>
+ <string name="day_of_week_shortest_saturday">土</string>
+
+ <string name="am">午前</string>
+ <string name="pm">午後</string>
+ <string name="yesterday">昨日</string>
+ <string name="today">今日</string>
+ <string name="tomorrow">明日</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%Y/%m/%d</string>
+ <string name="numeric_date_format">yyyy/MM/dd</string>
+ <string name="month_day_year">%Y年%-m月%-e日</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string>
+ <string name="abbrev_month_day_year">%Y/%m/%d</string>
+ <string name="month_day">%-m月%-e日</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y年%-m月</string>
+ <string name="abbrev_month_day">%-m月%-e日</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y年%-m月</string>
+</resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
new file mode 100644
index 0000000..b8e94fc
--- /dev/null
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">1月</string>
+ <string name="month_long_standalone_february">2月</string>
+ <string name="month_long_standalone_march">3月</string>
+ <string name="month_long_standalone_april">4月</string>
+ <string name="month_long_standalone_may">5月</string>
+ <string name="month_long_standalone_june">6月</string>
+ <string name="month_long_standalone_july">7月</string>
+ <string name="month_long_standalone_august">8月</string>
+ <string name="month_long_standalone_september">9月</string>
+ <string name="month_long_standalone_october">10月</string>
+ <string name="month_long_standalone_november">11月</string>
+ <string name="month_long_standalone_december">12月</string>
+
+ <string name="month_long_january">1月</string>
+ <string name="month_long_february">2月</string>
+ <string name="month_long_march">3月</string>
+ <string name="month_long_april">4月</string>
+ <string name="month_long_may">5月</string>
+ <string name="month_long_june">6月</string>
+ <string name="month_long_july">7月</string>
+ <string name="month_long_august">8月</string>
+ <string name="month_long_september">9月</string>
+ <string name="month_long_october">10月</string>
+ <string name="month_long_november">11月</string>
+ <string name="month_long_december">12月</string>
+
+ <string name="month_medium_january">1月</string>
+ <string name="month_medium_february">2月</string>
+ <string name="month_medium_march">3月</string>
+ <string name="month_medium_april">4月</string>
+ <string name="month_medium_may">5月</string>
+ <string name="month_medium_june">6月</string>
+ <string name="month_medium_july">7月</string>
+ <string name="month_medium_august">8月</string>
+ <string name="month_medium_september">9月</string>
+ <string name="month_medium_october">10月</string>
+ <string name="month_medium_november">11月</string>
+ <string name="month_medium_december">12月</string>
+
+ <string name="month_shortest_january">1</string>
+ <string name="month_shortest_february">2</string>
+ <string name="month_shortest_march">3</string>
+ <string name="month_shortest_april">4</string>
+ <string name="month_shortest_may">5</string>
+ <string name="month_shortest_june">6</string>
+ <string name="month_shortest_july">7</string>
+ <string name="month_shortest_august">8</string>
+ <string name="month_shortest_september">9</string>
+ <string name="month_shortest_october">10</string>
+ <string name="month_shortest_november">11</string>
+ <string name="month_shortest_december">12</string>
+
+ <string name="day_of_week_long_sunday">日曜日</string>
+ <string name="day_of_week_long_monday">月曜日</string>
+ <string name="day_of_week_long_tuesday">火曜日</string>
+ <string name="day_of_week_long_wednesday">水曜日</string>
+ <string name="day_of_week_long_thursday">木曜日</string>
+ <string name="day_of_week_long_friday">金曜日</string>
+ <string name="day_of_week_long_saturday">土曜日</string>
+
+ <string name="day_of_week_medium_sunday">日</string>
+ <string name="day_of_week_medium_monday">月</string>
+ <string name="day_of_week_medium_tuesday">火</string>
+ <string name="day_of_week_medium_wednesday">水</string>
+ <string name="day_of_week_medium_thursday">木</string>
+ <string name="day_of_week_medium_friday">金</string>
+ <string name="day_of_week_medium_saturday">土</string>
+
+ <string name="day_of_week_short_sunday">日</string>
+ <string name="day_of_week_short_monday">月</string>
+ <string name="day_of_week_short_tuesday">火</string>
+ <string name="day_of_week_short_wednesday">水</string>
+ <string name="day_of_week_short_thursday">木</string>
+ <string name="day_of_week_short_friday">金</string>
+ <string name="day_of_week_short_saturday">土</string>
+
+ <string name="day_of_week_shortest_sunday">日</string>
+ <string name="day_of_week_shortest_monday">月</string>
+ <string name="day_of_week_shortest_tuesday">火</string>
+ <string name="day_of_week_shortest_wednesday">水</string>
+ <string name="day_of_week_shortest_thursday">木</string>
+ <string name="day_of_week_shortest_friday">金</string>
+ <string name="day_of_week_shortest_saturday">土</string>
+
+ <string name="am">午前</string>
+ <string name="pm">午後</string>
+ <string name="yesterday">昨日</string>
+ <string name="today">今日</string>
+ <string name="tomorrow">明日</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%Y/%m/%d</string>
+ <string name="numeric_date_format">yyyy/MM/dd</string>
+ <string name="month_day_year">%Y年%-m月%-e日</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string>
+ <string name="abbrev_month_day_year">%Y/%m/%d</string>
+ <string name="month_day">%-m月%-e日</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y年%-m月</string>
+ <string name="abbrev_month_day">%-m月%-e日</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y年%-m月</string>
+</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8da040e..877ecbd 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"パスワード"</string>
<string name="lockscreen_glogin_submit_button">"ログイン"</string>
<string name="lockscreen_glogin_invalid_input">"ユーザー名またはパスワードが正しくありません。"</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"通知を消去"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"Enter"</string>
<string name="menu_delete_shortcut_label">"Del"</string>
<string name="search_go">"検索"</string>
- <string name="today">"今日"</string>
- <string name="yesterday">"昨日"</string>
- <string name="tomorrow">"明日"</string>
<string name="oneMonthDurationPast">"1か月前"</string>
<string name="beforeOneMonthDurationPast">"1か月前"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"週間"</string>
<string name="year">"年"</string>
<string name="years">"年"</string>
- <string name="sunday">"日曜日"</string>
- <string name="monday">"月曜日"</string>
- <string name="tuesday">"火曜日"</string>
- <string name="wednesday">"水曜日"</string>
- <string name="thursday">"木曜日"</string>
- <string name="friday">"金曜日"</string>
- <string name="saturday">"土曜日"</string>
<string name="every_weekday">"平日(月~金)"</string>
<string name="daily">"毎日"</string>
<string name="weekly">"毎週<xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"この動画はご使用の端末でストリーミングできません。"</string>
<string name="VideoView_error_text_unknown">"この動画は再生できません。"</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%3$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g><xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>'日 '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'年'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'日'"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'年'"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"正午"</string>
<string name="Noon">"正午"</string>
<string name="midnight">"午前0時"</string>
<string name="Midnight">"午前0時"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string>
- <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%B</xliff:g>/<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%b</xliff:g>月"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"日曜日"</string>
- <string name="day_of_week_long_monday">"月曜日"</string>
- <string name="day_of_week_long_tuesday">"火曜日"</string>
- <string name="day_of_week_long_wednesday">"水曜日"</string>
- <string name="day_of_week_long_thursday">"木曜日"</string>
- <string name="day_of_week_long_friday">"金曜日"</string>
- <string name="day_of_week_long_saturday">"土曜日"</string>
- <string name="day_of_week_medium_sunday">"(日)"</string>
- <string name="day_of_week_medium_monday">"(月)"</string>
- <string name="day_of_week_medium_tuesday">"(火)"</string>
- <string name="day_of_week_medium_wednesday">"(水)"</string>
- <string name="day_of_week_medium_thursday">"(木)"</string>
- <string name="day_of_week_medium_friday">"(金)"</string>
- <string name="day_of_week_medium_saturday">"(土)"</string>
- <string name="day_of_week_short_sunday">"日"</string>
- <string name="day_of_week_short_monday">"月"</string>
- <string name="day_of_week_short_tuesday">"火"</string>
- <string name="day_of_week_short_wednesday">"水"</string>
- <string name="day_of_week_short_thursday">"木"</string>
- <string name="day_of_week_short_friday">"金"</string>
- <string name="day_of_week_short_saturday">"土"</string>
- <string name="day_of_week_shorter_sunday">"日"</string>
- <string name="day_of_week_shorter_monday">"月"</string>
- <string name="day_of_week_shorter_tuesday">"火"</string>
- <string name="day_of_week_shorter_wednesday">"水"</string>
- <string name="day_of_week_shorter_thursday">"木"</string>
- <string name="day_of_week_shorter_friday">"金"</string>
- <string name="day_of_week_shorter_saturday">"土"</string>
- <string name="day_of_week_shortest_sunday">"日"</string>
- <string name="day_of_week_shortest_monday">"月"</string>
- <string name="day_of_week_shortest_tuesday">"火"</string>
- <string name="day_of_week_shortest_wednesday">"水"</string>
- <string name="day_of_week_shortest_thursday">"火"</string>
- <string name="day_of_week_shortest_friday">"金"</string>
- <string name="day_of_week_shortest_saturday">"土"</string>
- <string name="month_long_january">"1月"</string>
- <string name="month_long_february">"2月"</string>
- <string name="month_long_march">"3月"</string>
- <string name="month_long_april">"4月"</string>
- <string name="month_long_may">"5月"</string>
- <string name="month_long_june">"6月"</string>
- <string name="month_long_july">"7月"</string>
- <string name="month_long_august">"8月"</string>
- <string name="month_long_september">"9月"</string>
- <string name="month_long_october">"10月"</string>
- <string name="month_long_november">"11月"</string>
- <string name="month_long_december">"12月"</string>
- <string name="month_medium_january">"1"</string>
- <string name="month_medium_february">"2"</string>
- <string name="month_medium_march">"3"</string>
- <string name="month_medium_april">"4"</string>
- <string name="month_medium_may">"5"</string>
- <string name="month_medium_june">"6"</string>
- <string name="month_medium_july">"7"</string>
- <string name="month_medium_august">"8"</string>
- <string name="month_medium_september">"9"</string>
- <string name="month_medium_october">"10"</string>
- <string name="month_medium_november">"11"</string>
- <string name="month_medium_december">"12"</string>
- <string name="month_shortest_january">"1"</string>
- <string name="month_shortest_february">"2"</string>
- <string name="month_shortest_march">"3"</string>
- <string name="month_shortest_april">"4"</string>
- <string name="month_shortest_may">"5"</string>
- <string name="month_shortest_june">"6"</string>
- <string name="month_shortest_july">"7"</string>
- <string name="month_shortest_august">"8"</string>
- <string name="month_shortest_september">"9"</string>
- <string name="month_shortest_october">"10"</string>
- <string name="month_shortest_november">"11"</string>
- <string name="month_shortest_december">"12"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"すべて選択"</string>
diff --git a/core/res/res/values-ko-rKR/donottranslate-cldr.xml b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
new file mode 100644
index 0000000..17d9432
--- /dev/null
+++ b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">1월</string>
+ <string name="month_long_standalone_february">2월</string>
+ <string name="month_long_standalone_march">3월</string>
+ <string name="month_long_standalone_april">4월</string>
+ <string name="month_long_standalone_may">5월</string>
+ <string name="month_long_standalone_june">6월</string>
+ <string name="month_long_standalone_july">7월</string>
+ <string name="month_long_standalone_august">8월</string>
+ <string name="month_long_standalone_september">9월</string>
+ <string name="month_long_standalone_october">10월</string>
+ <string name="month_long_standalone_november">11월</string>
+ <string name="month_long_standalone_december">12월</string>
+
+ <string name="month_long_january">1월</string>
+ <string name="month_long_february">2월</string>
+ <string name="month_long_march">3월</string>
+ <string name="month_long_april">4월</string>
+ <string name="month_long_may">5월</string>
+ <string name="month_long_june">6월</string>
+ <string name="month_long_july">7월</string>
+ <string name="month_long_august">8월</string>
+ <string name="month_long_september">9월</string>
+ <string name="month_long_october">10월</string>
+ <string name="month_long_november">11월</string>
+ <string name="month_long_december">12월</string>
+
+
+ <string name="month_shortest_january">1월</string>
+ <string name="month_shortest_february">2월</string>
+ <string name="month_shortest_march">3월</string>
+ <string name="month_shortest_april">4월</string>
+ <string name="month_shortest_may">5월</string>
+ <string name="month_shortest_june">6월</string>
+ <string name="month_shortest_july">7월</string>
+ <string name="month_shortest_august">8월</string>
+ <string name="month_shortest_september">9월</string>
+ <string name="month_shortest_october">10월</string>
+ <string name="month_shortest_november">11월</string>
+ <string name="month_shortest_december">12월</string>
+
+ <string name="day_of_week_long_sunday">일요일</string>
+ <string name="day_of_week_long_monday">월요일</string>
+ <string name="day_of_week_long_tuesday">화요일</string>
+ <string name="day_of_week_long_wednesday">수요일</string>
+ <string name="day_of_week_long_thursday">목요일</string>
+ <string name="day_of_week_long_friday">금요일</string>
+ <string name="day_of_week_long_saturday">토요일</string>
+
+ <string name="day_of_week_medium_sunday">일</string>
+ <string name="day_of_week_medium_monday">월</string>
+ <string name="day_of_week_medium_tuesday">화</string>
+ <string name="day_of_week_medium_wednesday">수</string>
+ <string name="day_of_week_medium_thursday">목</string>
+ <string name="day_of_week_medium_friday">금</string>
+ <string name="day_of_week_medium_saturday">토</string>
+
+ <string name="day_of_week_short_sunday">일</string>
+ <string name="day_of_week_short_monday">월</string>
+ <string name="day_of_week_short_tuesday">화</string>
+ <string name="day_of_week_short_wednesday">수</string>
+ <string name="day_of_week_short_thursday">목</string>
+ <string name="day_of_week_short_friday">금</string>
+ <string name="day_of_week_short_saturday">토</string>
+
+ <string name="day_of_week_shortest_sunday">일</string>
+ <string name="day_of_week_shortest_monday">월</string>
+ <string name="day_of_week_shortest_tuesday">화</string>
+ <string name="day_of_week_shortest_wednesday">수</string>
+ <string name="day_of_week_shortest_thursday">목</string>
+ <string name="day_of_week_shortest_friday">금</string>
+ <string name="day_of_week_shortest_saturday">토</string>
+
+ <string name="am">오전</string>
+ <string name="pm">오후</string>
+ <string name="yesterday">어제</string>
+ <string name="today">오늘</string>
+ <string name="tomorrow">내일</string>
+
+ <string name="hour_minute_ampm">%p %-l:%M</string>
+ <string name="hour_minute_cap_ampm">%^p %-l:%M</string>
+ <string name="numeric_date">%Y. %-m. %-e.</string>
+ <string name="numeric_date_format">yyyy. M. d.</string>
+ <string name="month_day_year">%Y년 %-m월 %-e일</string>
+ <string name="time_of_day">%p %-l:%M:%S</string>
+ <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string>
+ <string name="abbrev_month_day_year">%Y. %-m. %-e.</string>
+ <string name="month_day">%B %-e일</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y년 %B</string>
+ <string name="abbrev_month_day">%b %-e일</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y년 %b</string>
+</resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
new file mode 100644
index 0000000..17d9432
--- /dev/null
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">1월</string>
+ <string name="month_long_standalone_february">2월</string>
+ <string name="month_long_standalone_march">3월</string>
+ <string name="month_long_standalone_april">4월</string>
+ <string name="month_long_standalone_may">5월</string>
+ <string name="month_long_standalone_june">6월</string>
+ <string name="month_long_standalone_july">7월</string>
+ <string name="month_long_standalone_august">8월</string>
+ <string name="month_long_standalone_september">9월</string>
+ <string name="month_long_standalone_october">10월</string>
+ <string name="month_long_standalone_november">11월</string>
+ <string name="month_long_standalone_december">12월</string>
+
+ <string name="month_long_january">1월</string>
+ <string name="month_long_february">2월</string>
+ <string name="month_long_march">3월</string>
+ <string name="month_long_april">4월</string>
+ <string name="month_long_may">5월</string>
+ <string name="month_long_june">6월</string>
+ <string name="month_long_july">7월</string>
+ <string name="month_long_august">8월</string>
+ <string name="month_long_september">9월</string>
+ <string name="month_long_october">10월</string>
+ <string name="month_long_november">11월</string>
+ <string name="month_long_december">12월</string>
+
+
+ <string name="month_shortest_january">1월</string>
+ <string name="month_shortest_february">2월</string>
+ <string name="month_shortest_march">3월</string>
+ <string name="month_shortest_april">4월</string>
+ <string name="month_shortest_may">5월</string>
+ <string name="month_shortest_june">6월</string>
+ <string name="month_shortest_july">7월</string>
+ <string name="month_shortest_august">8월</string>
+ <string name="month_shortest_september">9월</string>
+ <string name="month_shortest_october">10월</string>
+ <string name="month_shortest_november">11월</string>
+ <string name="month_shortest_december">12월</string>
+
+ <string name="day_of_week_long_sunday">일요일</string>
+ <string name="day_of_week_long_monday">월요일</string>
+ <string name="day_of_week_long_tuesday">화요일</string>
+ <string name="day_of_week_long_wednesday">수요일</string>
+ <string name="day_of_week_long_thursday">목요일</string>
+ <string name="day_of_week_long_friday">금요일</string>
+ <string name="day_of_week_long_saturday">토요일</string>
+
+ <string name="day_of_week_medium_sunday">일</string>
+ <string name="day_of_week_medium_monday">월</string>
+ <string name="day_of_week_medium_tuesday">화</string>
+ <string name="day_of_week_medium_wednesday">수</string>
+ <string name="day_of_week_medium_thursday">목</string>
+ <string name="day_of_week_medium_friday">금</string>
+ <string name="day_of_week_medium_saturday">토</string>
+
+ <string name="day_of_week_short_sunday">일</string>
+ <string name="day_of_week_short_monday">월</string>
+ <string name="day_of_week_short_tuesday">화</string>
+ <string name="day_of_week_short_wednesday">수</string>
+ <string name="day_of_week_short_thursday">목</string>
+ <string name="day_of_week_short_friday">금</string>
+ <string name="day_of_week_short_saturday">토</string>
+
+ <string name="day_of_week_shortest_sunday">일</string>
+ <string name="day_of_week_shortest_monday">월</string>
+ <string name="day_of_week_shortest_tuesday">화</string>
+ <string name="day_of_week_shortest_wednesday">수</string>
+ <string name="day_of_week_shortest_thursday">목</string>
+ <string name="day_of_week_shortest_friday">금</string>
+ <string name="day_of_week_shortest_saturday">토</string>
+
+ <string name="am">오전</string>
+ <string name="pm">오후</string>
+ <string name="yesterday">어제</string>
+ <string name="today">오늘</string>
+ <string name="tomorrow">내일</string>
+
+ <string name="hour_minute_ampm">%p %-l:%M</string>
+ <string name="hour_minute_cap_ampm">%^p %-l:%M</string>
+ <string name="numeric_date">%Y. %-m. %-e.</string>
+ <string name="numeric_date_format">yyyy. M. d.</string>
+ <string name="month_day_year">%Y년 %-m월 %-e일</string>
+ <string name="time_of_day">%p %-l:%M:%S</string>
+ <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string>
+ <string name="abbrev_month_day_year">%Y. %-m. %-e.</string>
+ <string name="month_day">%B %-e일</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y년 %B</string>
+ <string name="abbrev_month_day">%b %-e일</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y년 %b</string>
+</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 96b897a..06b85e8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"비밀번호"</string>
<string name="lockscreen_glogin_submit_button">"로그인"</string>
<string name="lockscreen_glogin_invalid_input">"사용자 이름 또는 비밀번호가 잘못되었습니다."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"알림 지우기"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"입력"</string>
<string name="menu_delete_shortcut_label">"삭제"</string>
<string name="search_go">"검색"</string>
- <string name="today">"오늘"</string>
- <string name="yesterday">"어제"</string>
- <string name="tomorrow">"내일"</string>
<string name="oneMonthDurationPast">"한 달 전"</string>
<string name="beforeOneMonthDurationPast">"한 달 전"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"주"</string>
<string name="year">"년"</string>
<string name="years">"년"</string>
- <string name="sunday">"일요일"</string>
- <string name="monday">"월요일"</string>
- <string name="tuesday">"화요일"</string>
- <string name="wednesday">"수요일"</string>
- <string name="thursday">"목요일"</string>
- <string name="friday">"금요일"</string>
- <string name="saturday">"토요일"</string>
<string name="every_weekday">"주중 매일(월-금)"</string>
<string name="daily">"매일"</string>
<string name="weekly">"매주 <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"죄송합니다. 이 기기로의 스트리밍에 적합하지 않은 동영상입니다."</string>
<string name="VideoView_error_text_unknown">"죄송합니다. 동영상을 재생할 수 없습니다."</string>
<string name="VideoView_error_button">"확인"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="DAY">d</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="DAY">d</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"정오"</string>
<string name="Noon">"정오"</string>
<string name="midnight">"자정"</string>
<string name="Midnight">"자정"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="DAY">%-d</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"일요일"</string>
- <string name="day_of_week_long_monday">"월요일"</string>
- <string name="day_of_week_long_tuesday">"화요일"</string>
- <string name="day_of_week_long_wednesday">"수요일"</string>
- <string name="day_of_week_long_thursday">"목요일"</string>
- <string name="day_of_week_long_friday">"금요일"</string>
- <string name="day_of_week_long_saturday">"토요일"</string>
- <string name="day_of_week_medium_sunday">"일요일"</string>
- <string name="day_of_week_medium_monday">"월"</string>
- <string name="day_of_week_medium_tuesday">"화"</string>
- <string name="day_of_week_medium_wednesday">"수"</string>
- <string name="day_of_week_medium_thursday">"목"</string>
- <string name="day_of_week_medium_friday">"금"</string>
- <string name="day_of_week_medium_saturday">"토"</string>
- <string name="day_of_week_short_sunday">"일"</string>
- <string name="day_of_week_short_monday">"월"</string>
- <string name="day_of_week_short_tuesday">"화"</string>
- <string name="day_of_week_short_wednesday">"수"</string>
- <string name="day_of_week_short_thursday">"목"</string>
- <string name="day_of_week_short_friday">"금"</string>
- <string name="day_of_week_short_saturday">"토"</string>
- <string name="day_of_week_shorter_sunday">"일"</string>
- <string name="day_of_week_shorter_monday">"월"</string>
- <string name="day_of_week_shorter_tuesday">"화"</string>
- <string name="day_of_week_shorter_wednesday">"수"</string>
- <string name="day_of_week_shorter_thursday">"목"</string>
- <string name="day_of_week_shorter_friday">"금"</string>
- <string name="day_of_week_shorter_saturday">"토"</string>
- <string name="day_of_week_shortest_sunday">"일"</string>
- <string name="day_of_week_shortest_monday">"3월"</string>
- <string name="day_of_week_shortest_tuesday">"목"</string>
- <string name="day_of_week_shortest_wednesday">"수"</string>
- <string name="day_of_week_shortest_thursday">"목"</string>
- <string name="day_of_week_shortest_friday">"금"</string>
- <string name="day_of_week_shortest_saturday">"토"</string>
- <string name="month_long_january">"1월"</string>
- <string name="month_long_february">"2월"</string>
- <string name="month_long_march">"3월"</string>
- <string name="month_long_april">"4월"</string>
- <string name="month_long_may">"5월"</string>
- <string name="month_long_june">"6월"</string>
- <string name="month_long_july">"7월"</string>
- <string name="month_long_august">"8월"</string>
- <string name="month_long_september">"9월"</string>
- <string name="month_long_october">"10월"</string>
- <string name="month_long_november">"11월"</string>
- <string name="month_long_december">"12월"</string>
- <string name="month_medium_january">"1월"</string>
- <string name="month_medium_february">"2월"</string>
- <string name="month_medium_march">"3월"</string>
- <string name="month_medium_april">"4월"</string>
- <string name="month_medium_may">"5월"</string>
- <string name="month_medium_june">"6월"</string>
- <string name="month_medium_july">"7월"</string>
- <string name="month_medium_august">"8월"</string>
- <string name="month_medium_september">"9월"</string>
- <string name="month_medium_october">"10월"</string>
- <string name="month_medium_november">"11월"</string>
- <string name="month_medium_december">"12월"</string>
- <string name="month_shortest_january">"1월"</string>
- <string name="month_shortest_february">"금"</string>
- <string name="month_shortest_march">"3월"</string>
- <string name="month_shortest_april">"4월"</string>
- <string name="month_shortest_may">"5월"</string>
- <string name="month_shortest_june">"6월"</string>
- <string name="month_shortest_july">"7월"</string>
- <string name="month_shortest_august">"8월"</string>
- <string name="month_shortest_september">"9월"</string>
- <string name="month_shortest_october">"10월"</string>
- <string name="month_shortest_november">"11월"</string>
- <string name="month_shortest_december">"12월"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"모두 선택"</string>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
new file mode 100644
index 0000000..629937b
--- /dev/null
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Sausis</string>
+ <string name="month_long_standalone_february">Vasaris</string>
+ <string name="month_long_standalone_march">Kovas</string>
+ <string name="month_long_standalone_april">Balandis</string>
+ <string name="month_long_standalone_may">Gegužė</string>
+ <string name="month_long_standalone_june">Birželis</string>
+ <string name="month_long_standalone_july">Liepa</string>
+ <string name="month_long_standalone_august">Rugpjūtis</string>
+ <string name="month_long_standalone_september">Rugsėjis</string>
+ <string name="month_long_standalone_october">Spalis</string>
+ <string name="month_long_standalone_november">Lapkritis</string>
+ <string name="month_long_standalone_december">Gruodis</string>
+
+ <string name="month_long_january">sausio</string>
+ <string name="month_long_february">vasario</string>
+ <string name="month_long_march">kovo</string>
+ <string name="month_long_april">balandžio</string>
+ <string name="month_long_may">gegužės</string>
+ <string name="month_long_june">birželio</string>
+ <string name="month_long_july">liepos</string>
+ <string name="month_long_august">rugpjūčio</string>
+ <string name="month_long_september">rugsėjo</string>
+ <string name="month_long_october">spalio</string>
+ <string name="month_long_november">lapkričio</string>
+ <string name="month_long_december">gruodžio</string>
+
+ <string name="month_medium_january">Sau</string>
+ <string name="month_medium_february">Vas</string>
+ <string name="month_medium_march">Kov</string>
+ <string name="month_medium_april">Bal</string>
+ <string name="month_medium_may">Geg</string>
+ <string name="month_medium_june">Bir</string>
+ <string name="month_medium_july">Lie</string>
+ <string name="month_medium_august">Rgp</string>
+ <string name="month_medium_september">Rgs</string>
+ <string name="month_medium_october">Spl</string>
+ <string name="month_medium_november">Lap</string>
+ <string name="month_medium_december">Grd</string>
+
+ <string name="month_shortest_january">S</string>
+ <string name="month_shortest_february">V</string>
+ <string name="month_shortest_march">K</string>
+ <string name="month_shortest_april">B</string>
+ <string name="month_shortest_may">G</string>
+ <string name="month_shortest_june">B</string>
+ <string name="month_shortest_july">L</string>
+ <string name="month_shortest_august">R</string>
+ <string name="month_shortest_september">R</string>
+ <string name="month_shortest_october">S</string>
+ <string name="month_shortest_november">L</string>
+ <string name="month_shortest_december">G</string>
+
+ <string name="day_of_week_long_sunday">sekmadienis</string>
+ <string name="day_of_week_long_monday">pirmadienis</string>
+ <string name="day_of_week_long_tuesday">antradienis</string>
+ <string name="day_of_week_long_wednesday">trečiadienis</string>
+ <string name="day_of_week_long_thursday">ketvirtadienis</string>
+ <string name="day_of_week_long_friday">penktadienis</string>
+ <string name="day_of_week_long_saturday">šeštadienis</string>
+
+ <string name="day_of_week_medium_sunday">Sk</string>
+ <string name="day_of_week_medium_monday">Pr</string>
+ <string name="day_of_week_medium_tuesday">An</string>
+ <string name="day_of_week_medium_wednesday">Tr</string>
+ <string name="day_of_week_medium_thursday">Kt</string>
+ <string name="day_of_week_medium_friday">Pn</string>
+ <string name="day_of_week_medium_saturday">Št</string>
+
+ <string name="day_of_week_short_sunday">Sk</string>
+ <string name="day_of_week_short_monday">Pr</string>
+ <string name="day_of_week_short_tuesday">An</string>
+ <string name="day_of_week_short_wednesday">Tr</string>
+ <string name="day_of_week_short_thursday">Kt</string>
+ <string name="day_of_week_short_friday">Pn</string>
+ <string name="day_of_week_short_saturday">Št</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">A</string>
+ <string name="day_of_week_shortest_wednesday">T</string>
+ <string name="day_of_week_shortest_thursday">K</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">Š</string>
+
+ <string name="am">priešpiet</string>
+ <string name="pm">popiet</string>
+ <string name="yesterday">vakar</string>
+ <string name="today">šiandien</string>
+ <string name="tomorrow">rytoj</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%Y-%m-%d</string>
+ <string name="numeric_date_format">yyyy-MM-dd</string>
+ <string name="month_day_year">%Y m. %B %-e d.</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %Y.%m.%d</string>
+ <string name="abbrev_month_day_year">%Y.%m.%d</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-lv-rLV/donottranslate-cldr.xml b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
new file mode 100644
index 0000000..d47a18f
--- /dev/null
+++ b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janvāris</string>
+ <string name="month_long_standalone_february">februāris</string>
+ <string name="month_long_standalone_march">marts</string>
+ <string name="month_long_standalone_april">aprīlis</string>
+ <string name="month_long_standalone_may">maijs</string>
+ <string name="month_long_standalone_june">jūnijs</string>
+ <string name="month_long_standalone_july">jūlijs</string>
+ <string name="month_long_standalone_august">augusts</string>
+ <string name="month_long_standalone_september">septembris</string>
+ <string name="month_long_standalone_october">oktobris</string>
+ <string name="month_long_standalone_november">novembris</string>
+ <string name="month_long_standalone_december">decembris</string>
+
+ <string name="month_long_january">janvāris</string>
+ <string name="month_long_february">februāris</string>
+ <string name="month_long_march">marts</string>
+ <string name="month_long_april">aprīlis</string>
+ <string name="month_long_may">maijs</string>
+ <string name="month_long_june">jūnijs</string>
+ <string name="month_long_july">jūlijs</string>
+ <string name="month_long_august">augusts</string>
+ <string name="month_long_september">septembris</string>
+ <string name="month_long_october">oktobris</string>
+ <string name="month_long_november">novembris</string>
+ <string name="month_long_december">decembris</string>
+
+ <string name="month_medium_january">janv.</string>
+ <string name="month_medium_february">febr.</string>
+ <string name="month_medium_march">marts</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">maijs</string>
+ <string name="month_medium_june">jūn.</string>
+ <string name="month_medium_july">jūl.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">svētdiena</string>
+ <string name="day_of_week_long_monday">pirmdiena</string>
+ <string name="day_of_week_long_tuesday">otrdiena</string>
+ <string name="day_of_week_long_wednesday">trešdiena</string>
+ <string name="day_of_week_long_thursday">ceturtdiena</string>
+ <string name="day_of_week_long_friday">piektdiena</string>
+ <string name="day_of_week_long_saturday">sestdiena</string>
+
+ <string name="day_of_week_medium_sunday">Sv</string>
+ <string name="day_of_week_medium_monday">Pr</string>
+ <string name="day_of_week_medium_tuesday">Ot</string>
+ <string name="day_of_week_medium_wednesday">Tr</string>
+ <string name="day_of_week_medium_thursday">Ce</string>
+ <string name="day_of_week_medium_friday">Pk</string>
+ <string name="day_of_week_medium_saturday">Se</string>
+
+ <string name="day_of_week_short_sunday">Sv</string>
+ <string name="day_of_week_short_monday">Pr</string>
+ <string name="day_of_week_short_tuesday">Ot</string>
+ <string name="day_of_week_short_wednesday">Tr</string>
+ <string name="day_of_week_short_thursday">Ce</string>
+ <string name="day_of_week_short_friday">Pk</string>
+ <string name="day_of_week_short_saturday">Se</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">O</string>
+ <string name="day_of_week_shortest_wednesday">T</string>
+ <string name="day_of_week_shortest_thursday">C</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">vakar</string>
+ <string name="today">šodien</string>
+ <string name="tomorrow">rīt</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%Y. gada %-e. %B</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %Y. gada %-e. %b</string>
+ <string name="abbrev_month_day_year">%Y. gada %-e. %b</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y. g. %B</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y. g. %b</string>
+</resources>
diff --git a/core/res/res/values-nb/donottranslate-cldr.xml b/core/res/res/values-nb/donottranslate-cldr.xml
new file mode 100644
index 0000000..f89e819
--- /dev/null
+++ b/core/res/res/values-nb/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januar</string>
+ <string name="month_long_standalone_february">februar</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">august</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">desember</string>
+
+ <string name="month_long_january">januar</string>
+ <string name="month_long_february">februar</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">august</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">desember</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">juni</string>
+ <string name="month_medium_july">juli</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sep.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">des.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">søndag</string>
+ <string name="day_of_week_long_monday">mandag</string>
+ <string name="day_of_week_long_tuesday">tirsdag</string>
+ <string name="day_of_week_long_wednesday">onsdag</string>
+ <string name="day_of_week_long_thursday">torsdag</string>
+ <string name="day_of_week_long_friday">fredag</string>
+ <string name="day_of_week_long_saturday">lørdag</string>
+
+ <string name="day_of_week_medium_sunday">søn.</string>
+ <string name="day_of_week_medium_monday">man.</string>
+ <string name="day_of_week_medium_tuesday">tir.</string>
+ <string name="day_of_week_medium_wednesday">ons.</string>
+ <string name="day_of_week_medium_thursday">tor.</string>
+ <string name="day_of_week_medium_friday">fre.</string>
+ <string name="day_of_week_medium_saturday">lør.</string>
+
+ <string name="day_of_week_short_sunday">søn.</string>
+ <string name="day_of_week_short_monday">man.</string>
+ <string name="day_of_week_short_tuesday">tir.</string>
+ <string name="day_of_week_short_wednesday">ons.</string>
+ <string name="day_of_week_short_thursday">tor.</string>
+ <string name="day_of_week_short_friday">fre.</string>
+ <string name="day_of_week_short_saturday">lør.</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">O</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">L</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">i går</string>
+ <string name="today">i dag</string>
+ <string name="tomorrow">i morgen</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %-e. %b %Y</string>
+ <string name="abbrev_month_day_year">%-e. %b %Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7bed159..a28b12c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -424,9 +424,6 @@
<string name="lockscreen_glogin_password_hint">"Password"</string>
<string name="lockscreen_glogin_submit_button">"Sign in"</string>
<string name="lockscreen_glogin_invalid_input">"Invalid username or password."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Fjern varslinger"</string>
@@ -458,9 +455,6 @@
<string name="menu_enter_shortcut_label">"enter"</string>
<string name="menu_delete_shortcut_label">"slett"</string>
<string name="search_go">"Søk"</string>
- <string name="today">"I dag"</string>
- <string name="yesterday">"I går"</string>
- <string name="tomorrow">"I morgen"</string>
<string name="oneMonthDurationPast">"For en måned siden"</string>
<string name="beforeOneMonthDurationPast">"For over en måned siden"</string>
<plurals name="num_seconds_ago">
@@ -542,13 +536,6 @@
<string name="weeks">"uker"</string>
<string name="year">"år"</string>
<string name="years">"år"</string>
- <string name="sunday">"søndag"</string>
- <string name="monday">"mandag"</string>
- <string name="tuesday">"tirsdag"</string>
- <string name="wednesday">"onsdag"</string>
- <string name="thursday">"torsdag"</string>
- <string name="friday">"fredag"</string>
- <string name="saturday">"lørdag"</string>
<string name="every_weekday">"Hverdager (man–fre)"</string>
<string name="daily">"Hver dag"</string>
<string name="weekly">"Hver <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -558,9 +545,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Beklager, denne videoen er ikke gyldig for streaming til denne enheten."</string>
<string name="VideoView_error_text_unknown">"Beklager, kan ikke spille denne videoen."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g>-<xliff:g id="MONTH">%m</xliff:g>-<xliff:g id="DAY">%d</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -572,12 +556,6 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>'., '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"middag"</string>
<string name="Noon">"Middag"</string>
<string name="midnight">"midnatt"</string>
@@ -586,10 +564,6 @@
<skip />
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -614,83 +588,10 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for abbrev_month_day (3156047263406783231) -->
<skip />
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"søndag"</string>
- <string name="day_of_week_long_monday">"mandag"</string>
- <string name="day_of_week_long_tuesday">"tirsdag"</string>
- <string name="day_of_week_long_wednesday">"onsdag"</string>
- <string name="day_of_week_long_thursday">"torsdag"</string>
- <string name="day_of_week_long_friday">"fredag"</string>
- <string name="day_of_week_long_saturday">"lørdag"</string>
- <string name="day_of_week_medium_sunday">"søn"</string>
- <string name="day_of_week_medium_monday">"man"</string>
- <string name="day_of_week_medium_tuesday">"tir"</string>
- <string name="day_of_week_medium_wednesday">"ons"</string>
- <string name="day_of_week_medium_thursday">"tor"</string>
- <string name="day_of_week_medium_friday">"fre"</string>
- <string name="day_of_week_medium_saturday">"lør"</string>
- <string name="day_of_week_short_sunday">"sø"</string>
- <string name="day_of_week_short_monday">"ma"</string>
- <string name="day_of_week_short_tuesday">"ti"</string>
- <string name="day_of_week_short_wednesday">"on"</string>
- <string name="day_of_week_short_thursday">"to"</string>
- <string name="day_of_week_short_friday">"fr"</string>
- <string name="day_of_week_short_saturday">"lø"</string>
- <string name="day_of_week_shorter_sunday">"S"</string>
- <string name="day_of_week_shorter_monday">"M"</string>
- <string name="day_of_week_shorter_tuesday">"Ti"</string>
- <string name="day_of_week_shorter_wednesday">"O"</string>
- <string name="day_of_week_shorter_thursday">"To"</string>
- <string name="day_of_week_shorter_friday">"F"</string>
- <string name="day_of_week_shorter_saturday">"L"</string>
- <string name="day_of_week_shortest_sunday">"S"</string>
- <string name="day_of_week_shortest_monday">"M"</string>
- <string name="day_of_week_shortest_tuesday">"T"</string>
- <string name="day_of_week_shortest_wednesday">"O"</string>
- <string name="day_of_week_shortest_thursday">"T"</string>
- <string name="day_of_week_shortest_friday">"F"</string>
- <string name="day_of_week_shortest_saturday">"L"</string>
- <string name="month_long_january">"januar"</string>
- <string name="month_long_february">"februar"</string>
- <string name="month_long_march">"mars"</string>
- <string name="month_long_april">"april"</string>
- <string name="month_long_may">"mai"</string>
- <string name="month_long_june">"juni"</string>
- <string name="month_long_july">"juli"</string>
- <string name="month_long_august">"august"</string>
- <string name="month_long_september">"september"</string>
- <string name="month_long_october">"oktober"</string>
- <string name="month_long_november">"november"</string>
- <string name="month_long_december">"desember"</string>
- <string name="month_medium_january">"jan"</string>
- <string name="month_medium_february">"feb"</string>
- <string name="month_medium_march">"mar"</string>
- <string name="month_medium_april">"apr"</string>
- <string name="month_medium_may">"mai"</string>
- <string name="month_medium_june">"jun"</string>
- <string name="month_medium_july">"jul"</string>
- <string name="month_medium_august">"aug"</string>
- <string name="month_medium_september">"sep"</string>
- <string name="month_medium_october">"okt"</string>
- <string name="month_medium_november">"nov"</string>
- <string name="month_medium_december">"des"</string>
- <string name="month_shortest_january">"J"</string>
- <string name="month_shortest_february">"F"</string>
- <string name="month_shortest_march">"M"</string>
- <string name="month_shortest_april">"A"</string>
- <string name="month_shortest_may">"M"</string>
- <string name="month_shortest_june">"J"</string>
- <string name="month_shortest_july">"J"</string>
- <string name="month_shortest_august">"A"</string>
- <string name="month_shortest_september">"S"</string>
- <string name="month_shortest_october">"O"</string>
- <string name="month_shortest_november">"N"</string>
- <string name="month_shortest_december">"D"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Merk alt"</string>
diff --git a/core/res/res/values-nl-rBE/donottranslate-cldr.xml b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
new file mode 100644
index 0000000..c3050c6
--- /dev/null
+++ b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januari</string>
+ <string name="month_long_standalone_february">februari</string>
+ <string name="month_long_standalone_march">maart</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">mei</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">augustus</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januari</string>
+ <string name="month_long_february">februari</string>
+ <string name="month_long_march">maart</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">mei</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">augustus</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mrt.</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">mei</string>
+ <string name="month_medium_june">jun.</string>
+ <string name="month_medium_july">jul.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sep.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">zondag</string>
+ <string name="day_of_week_long_monday">maandag</string>
+ <string name="day_of_week_long_tuesday">dinsdag</string>
+ <string name="day_of_week_long_wednesday">woensdag</string>
+ <string name="day_of_week_long_thursday">donderdag</string>
+ <string name="day_of_week_long_friday">vrijdag</string>
+ <string name="day_of_week_long_saturday">zaterdag</string>
+
+ <string name="day_of_week_medium_sunday">zo</string>
+ <string name="day_of_week_medium_monday">ma</string>
+ <string name="day_of_week_medium_tuesday">di</string>
+ <string name="day_of_week_medium_wednesday">wo</string>
+ <string name="day_of_week_medium_thursday">do</string>
+ <string name="day_of_week_medium_friday">vr</string>
+ <string name="day_of_week_medium_saturday">za</string>
+
+ <string name="day_of_week_short_sunday">zo</string>
+ <string name="day_of_week_short_monday">ma</string>
+ <string name="day_of_week_short_tuesday">di</string>
+ <string name="day_of_week_short_wednesday">wo</string>
+ <string name="day_of_week_short_thursday">do</string>
+ <string name="day_of_week_short_friday">vr</string>
+ <string name="day_of_week_short_saturday">za</string>
+
+ <string name="day_of_week_shortest_sunday">Z</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">Z</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Gisteren</string>
+ <string name="today">Vandaag</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%-e/%m/%Y</string>
+ <string name="numeric_date_format">d/MM/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e-%b-%Y</string>
+ <string name="abbrev_month_day_year">%-e-%b-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e-%b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-nl-rNL/donottranslate-cldr.xml b/core/res/res/values-nl-rNL/donottranslate-cldr.xml
new file mode 100644
index 0000000..b9e0407
--- /dev/null
+++ b/core/res/res/values-nl-rNL/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januari</string>
+ <string name="month_long_standalone_february">februari</string>
+ <string name="month_long_standalone_march">maart</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">mei</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">augustus</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januari</string>
+ <string name="month_long_february">februari</string>
+ <string name="month_long_march">maart</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">mei</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">augustus</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mrt.</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">mei</string>
+ <string name="month_medium_june">jun.</string>
+ <string name="month_medium_july">jul.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sep.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">zondag</string>
+ <string name="day_of_week_long_monday">maandag</string>
+ <string name="day_of_week_long_tuesday">dinsdag</string>
+ <string name="day_of_week_long_wednesday">woensdag</string>
+ <string name="day_of_week_long_thursday">donderdag</string>
+ <string name="day_of_week_long_friday">vrijdag</string>
+ <string name="day_of_week_long_saturday">zaterdag</string>
+
+ <string name="day_of_week_medium_sunday">zo</string>
+ <string name="day_of_week_medium_monday">ma</string>
+ <string name="day_of_week_medium_tuesday">di</string>
+ <string name="day_of_week_medium_wednesday">wo</string>
+ <string name="day_of_week_medium_thursday">do</string>
+ <string name="day_of_week_medium_friday">vr</string>
+ <string name="day_of_week_medium_saturday">za</string>
+
+ <string name="day_of_week_short_sunday">zo</string>
+ <string name="day_of_week_short_monday">ma</string>
+ <string name="day_of_week_short_tuesday">di</string>
+ <string name="day_of_week_short_wednesday">wo</string>
+ <string name="day_of_week_short_thursday">do</string>
+ <string name="day_of_week_short_friday">vr</string>
+ <string name="day_of_week_short_saturday">za</string>
+
+ <string name="day_of_week_shortest_sunday">Z</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">Z</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Gisteren</string>
+ <string name="today">Vandaag</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d-%m-%Y</string>
+ <string name="numeric_date_format">dd-MM-yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e-%b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-nl/donottranslate-cldr.xml b/core/res/res/values-nl/donottranslate-cldr.xml
new file mode 100644
index 0000000..b9e0407
--- /dev/null
+++ b/core/res/res/values-nl/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januari</string>
+ <string name="month_long_standalone_february">februari</string>
+ <string name="month_long_standalone_march">maart</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">mei</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">augustus</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januari</string>
+ <string name="month_long_february">februari</string>
+ <string name="month_long_march">maart</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">mei</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">augustus</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mrt.</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">mei</string>
+ <string name="month_medium_june">jun.</string>
+ <string name="month_medium_july">jul.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sep.</string>
+ <string name="month_medium_october">okt.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">zondag</string>
+ <string name="day_of_week_long_monday">maandag</string>
+ <string name="day_of_week_long_tuesday">dinsdag</string>
+ <string name="day_of_week_long_wednesday">woensdag</string>
+ <string name="day_of_week_long_thursday">donderdag</string>
+ <string name="day_of_week_long_friday">vrijdag</string>
+ <string name="day_of_week_long_saturday">zaterdag</string>
+
+ <string name="day_of_week_medium_sunday">zo</string>
+ <string name="day_of_week_medium_monday">ma</string>
+ <string name="day_of_week_medium_tuesday">di</string>
+ <string name="day_of_week_medium_wednesday">wo</string>
+ <string name="day_of_week_medium_thursday">do</string>
+ <string name="day_of_week_medium_friday">vr</string>
+ <string name="day_of_week_medium_saturday">za</string>
+
+ <string name="day_of_week_short_sunday">zo</string>
+ <string name="day_of_week_short_monday">ma</string>
+ <string name="day_of_week_short_tuesday">di</string>
+ <string name="day_of_week_short_wednesday">wo</string>
+ <string name="day_of_week_short_thursday">do</string>
+ <string name="day_of_week_short_friday">vr</string>
+ <string name="day_of_week_short_saturday">za</string>
+
+ <string name="day_of_week_shortest_sunday">Z</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">D</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">D</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">Z</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Gisteren</string>
+ <string name="today">Vandaag</string>
+ <string name="tomorrow">Morgen</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d-%m-%Y</string>
+ <string name="numeric_date_format">dd-MM-yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e-%b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3a9e32c..4437f29 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Wachtwoord"</string>
<string name="lockscreen_glogin_submit_button">"Aanmelden"</string>
<string name="lockscreen_glogin_invalid_input">"Gebruikersnaam of wachtwoord ongeldig."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Meldingen wissen"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"invoeren"</string>
<string name="menu_delete_shortcut_label">"verwijderen"</string>
<string name="search_go">"Zoeken"</string>
- <string name="today">"Vandaag"</string>
- <string name="yesterday">"Gisteren"</string>
- <string name="tomorrow">"Morgen"</string>
<string name="oneMonthDurationPast">"1 maand geleden"</string>
<string name="beforeOneMonthDurationPast">"Meer dan 1 maand geleden"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"weken"</string>
<string name="year">"jaar"</string>
<string name="years">"jaren"</string>
- <string name="sunday">"Zondag"</string>
- <string name="monday">"Maandag"</string>
- <string name="tuesday">"Dinsdag"</string>
- <string name="wednesday">"Woensdag"</string>
- <string name="thursday">"Donderdag"</string>
- <string name="friday">"Vrijdag"</string>
- <string name="saturday">"Zaterdag"</string>
<string name="every_weekday">"Elke weekdag (ma-vr)"</string>
<string name="daily">"Dagelijks"</string>
<string name="weekly">"Wekelijks op <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Deze video kan helaas niet worden gestreamd naar dit apparaat."</string>
<string name="VideoView_error_text_unknown">"Deze video kan niet worden afgespeeld."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"am"</string>
- <string name="pm">"pm"</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>-<xliff:g id="MONTH">%m</xliff:g>-<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"twaalf uur \'s middags"</string>
<string name="Noon">"Twaalf uur \'s middags"</string>
<string name="midnight">"middernacht"</string>
<string name="Midnight">"Middernacht"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"Zondag"</string>
- <string name="day_of_week_long_monday">"Maandag"</string>
- <string name="day_of_week_long_tuesday">"Dinsdag"</string>
- <string name="day_of_week_long_wednesday">"Woensdag"</string>
- <string name="day_of_week_long_thursday">"Donderdag"</string>
- <string name="day_of_week_long_friday">"Vrijdag"</string>
- <string name="day_of_week_long_saturday">"Zaterdag"</string>
- <string name="day_of_week_medium_sunday">"Zo"</string>
- <string name="day_of_week_medium_monday">"Ma"</string>
- <string name="day_of_week_medium_tuesday">"Di"</string>
- <string name="day_of_week_medium_wednesday">"Wo"</string>
- <string name="day_of_week_medium_thursday">"Do"</string>
- <string name="day_of_week_medium_friday">"Vr"</string>
- <string name="day_of_week_medium_saturday">"Za"</string>
- <string name="day_of_week_short_sunday">"Zo"</string>
- <string name="day_of_week_short_monday">"Ma"</string>
- <string name="day_of_week_short_tuesday">"Di"</string>
- <string name="day_of_week_short_wednesday">"Wo"</string>
- <string name="day_of_week_short_thursday">"Do"</string>
- <string name="day_of_week_short_friday">"Vr"</string>
- <string name="day_of_week_short_saturday">"Za"</string>
- <string name="day_of_week_shorter_sunday">"Zo"</string>
- <string name="day_of_week_shorter_monday">"M"</string>
- <string name="day_of_week_shorter_tuesday">"Di"</string>
- <string name="day_of_week_shorter_wednesday">"W"</string>
- <string name="day_of_week_shorter_thursday">"Do"</string>
- <string name="day_of_week_shorter_friday">"V"</string>
- <string name="day_of_week_shorter_saturday">"Za"</string>
- <string name="day_of_week_shortest_sunday">"Z"</string>
- <string name="day_of_week_shortest_monday">"M"</string>
- <string name="day_of_week_shortest_tuesday">"D"</string>
- <string name="day_of_week_shortest_wednesday">"W"</string>
- <string name="day_of_week_shortest_thursday">"D"</string>
- <string name="day_of_week_shortest_friday">"V"</string>
- <string name="day_of_week_shortest_saturday">"Z"</string>
- <string name="month_long_january">"Januari"</string>
- <string name="month_long_february">"Februari"</string>
- <string name="month_long_march">"Maart"</string>
- <string name="month_long_april">"April"</string>
- <string name="month_long_may">"Mei"</string>
- <string name="month_long_june">"Juni"</string>
- <string name="month_long_july">"Juli"</string>
- <string name="month_long_august">"Augustus"</string>
- <string name="month_long_september">"September"</string>
- <string name="month_long_october">"Oktober"</string>
- <string name="month_long_november">"November"</string>
- <string name="month_long_december">"December"</string>
- <string name="month_medium_january">"Jan"</string>
- <string name="month_medium_february">"Feb"</string>
- <string name="month_medium_march">"Mrt"</string>
- <string name="month_medium_april">"Apr"</string>
- <string name="month_medium_may">"Mei"</string>
- <string name="month_medium_june">"Jun"</string>
- <string name="month_medium_july">"Jul"</string>
- <string name="month_medium_august">"Aug"</string>
- <string name="month_medium_september">"Sep"</string>
- <string name="month_medium_october">"Okt"</string>
- <string name="month_medium_november">"Nov"</string>
- <string name="month_medium_december">"Dec"</string>
- <string name="month_shortest_january">"J"</string>
- <string name="month_shortest_february">"V"</string>
- <string name="month_shortest_march">"M"</string>
- <string name="month_shortest_april">"A"</string>
- <string name="month_shortest_may">"M"</string>
- <string name="month_shortest_june">"J"</string>
- <string name="month_shortest_july">"J"</string>
- <string name="month_shortest_august">"A"</string>
- <string name="month_shortest_september">"S"</string>
- <string name="month_shortest_october">"O"</string>
- <string name="month_shortest_november">"N"</string>
- <string name="month_shortest_december">"D"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Alles selecteren"</string>
diff --git a/core/res/res/values-pl-rPL/donottranslate-cldr.xml b/core/res/res/values-pl-rPL/donottranslate-cldr.xml
new file mode 100644
index 0000000..0ae8b48
--- /dev/null
+++ b/core/res/res/values-pl-rPL/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">styczeń</string>
+ <string name="month_long_standalone_february">luty</string>
+ <string name="month_long_standalone_march">marzec</string>
+ <string name="month_long_standalone_april">kwiecień</string>
+ <string name="month_long_standalone_may">maj</string>
+ <string name="month_long_standalone_june">czerwiec</string>
+ <string name="month_long_standalone_july">lipiec</string>
+ <string name="month_long_standalone_august">sierpień</string>
+ <string name="month_long_standalone_september">wrzesień</string>
+ <string name="month_long_standalone_october">październik</string>
+ <string name="month_long_standalone_november">listopad</string>
+ <string name="month_long_standalone_december">grudzień</string>
+
+ <string name="month_long_january">stycznia</string>
+ <string name="month_long_february">lutego</string>
+ <string name="month_long_march">marca</string>
+ <string name="month_long_april">kwietnia</string>
+ <string name="month_long_may">maja</string>
+ <string name="month_long_june">czerwca</string>
+ <string name="month_long_july">lipca</string>
+ <string name="month_long_august">sierpnia</string>
+ <string name="month_long_september">września</string>
+ <string name="month_long_october">października</string>
+ <string name="month_long_november">listopada</string>
+ <string name="month_long_december">grudnia</string>
+
+ <string name="month_medium_january">sty</string>
+ <string name="month_medium_february">lut</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">kwi</string>
+ <string name="month_medium_may">maj</string>
+ <string name="month_medium_june">cze</string>
+ <string name="month_medium_july">lip</string>
+ <string name="month_medium_august">sie</string>
+ <string name="month_medium_september">wrz</string>
+ <string name="month_medium_october">paź</string>
+ <string name="month_medium_november">lis</string>
+ <string name="month_medium_december">gru</string>
+
+ <string name="month_shortest_january">s</string>
+ <string name="month_shortest_february">l</string>
+ <string name="month_shortest_march">m</string>
+ <string name="month_shortest_april">k</string>
+ <string name="month_shortest_may">m</string>
+ <string name="month_shortest_june">c</string>
+ <string name="month_shortest_july">l</string>
+ <string name="month_shortest_august">s</string>
+ <string name="month_shortest_september">w</string>
+ <string name="month_shortest_october">p</string>
+ <string name="month_shortest_november">l</string>
+ <string name="month_shortest_december">g</string>
+
+ <string name="day_of_week_long_sunday">niedziela</string>
+ <string name="day_of_week_long_monday">poniedziałek</string>
+ <string name="day_of_week_long_tuesday">wtorek</string>
+ <string name="day_of_week_long_wednesday">środa</string>
+ <string name="day_of_week_long_thursday">czwartek</string>
+ <string name="day_of_week_long_friday">piątek</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">niedz.</string>
+ <string name="day_of_week_medium_monday">pon.</string>
+ <string name="day_of_week_medium_tuesday">wt.</string>
+ <string name="day_of_week_medium_wednesday">śr.</string>
+ <string name="day_of_week_medium_thursday">czw.</string>
+ <string name="day_of_week_medium_friday">pt.</string>
+ <string name="day_of_week_medium_saturday">sob.</string>
+
+ <string name="day_of_week_short_sunday">niedz.</string>
+ <string name="day_of_week_short_monday">pon.</string>
+ <string name="day_of_week_short_tuesday">wt.</string>
+ <string name="day_of_week_short_wednesday">śr.</string>
+ <string name="day_of_week_short_thursday">czw.</string>
+ <string name="day_of_week_short_friday">pt.</string>
+ <string name="day_of_week_short_saturday">sob.</string>
+
+ <string name="day_of_week_shortest_sunday">N</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">W</string>
+ <string name="day_of_week_shortest_wednesday">Ś</string>
+ <string name="day_of_week_shortest_thursday">C</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Wczoraj</string>
+ <string name="today">Dzisiaj</string>
+ <string name="tomorrow">Jutro</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d-%m-%Y</string>
+ <string name="numeric_date_format">dd-MM-yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d-%m-%Y</string>
+ <string name="abbrev_month_day_year">%d-%m-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-pl/donottranslate-cldr.xml b/core/res/res/values-pl/donottranslate-cldr.xml
new file mode 100644
index 0000000..0ae8b48
--- /dev/null
+++ b/core/res/res/values-pl/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">styczeń</string>
+ <string name="month_long_standalone_february">luty</string>
+ <string name="month_long_standalone_march">marzec</string>
+ <string name="month_long_standalone_april">kwiecień</string>
+ <string name="month_long_standalone_may">maj</string>
+ <string name="month_long_standalone_june">czerwiec</string>
+ <string name="month_long_standalone_july">lipiec</string>
+ <string name="month_long_standalone_august">sierpień</string>
+ <string name="month_long_standalone_september">wrzesień</string>
+ <string name="month_long_standalone_october">październik</string>
+ <string name="month_long_standalone_november">listopad</string>
+ <string name="month_long_standalone_december">grudzień</string>
+
+ <string name="month_long_january">stycznia</string>
+ <string name="month_long_february">lutego</string>
+ <string name="month_long_march">marca</string>
+ <string name="month_long_april">kwietnia</string>
+ <string name="month_long_may">maja</string>
+ <string name="month_long_june">czerwca</string>
+ <string name="month_long_july">lipca</string>
+ <string name="month_long_august">sierpnia</string>
+ <string name="month_long_september">września</string>
+ <string name="month_long_october">października</string>
+ <string name="month_long_november">listopada</string>
+ <string name="month_long_december">grudnia</string>
+
+ <string name="month_medium_january">sty</string>
+ <string name="month_medium_february">lut</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">kwi</string>
+ <string name="month_medium_may">maj</string>
+ <string name="month_medium_june">cze</string>
+ <string name="month_medium_july">lip</string>
+ <string name="month_medium_august">sie</string>
+ <string name="month_medium_september">wrz</string>
+ <string name="month_medium_october">paź</string>
+ <string name="month_medium_november">lis</string>
+ <string name="month_medium_december">gru</string>
+
+ <string name="month_shortest_january">s</string>
+ <string name="month_shortest_february">l</string>
+ <string name="month_shortest_march">m</string>
+ <string name="month_shortest_april">k</string>
+ <string name="month_shortest_may">m</string>
+ <string name="month_shortest_june">c</string>
+ <string name="month_shortest_july">l</string>
+ <string name="month_shortest_august">s</string>
+ <string name="month_shortest_september">w</string>
+ <string name="month_shortest_october">p</string>
+ <string name="month_shortest_november">l</string>
+ <string name="month_shortest_december">g</string>
+
+ <string name="day_of_week_long_sunday">niedziela</string>
+ <string name="day_of_week_long_monday">poniedziałek</string>
+ <string name="day_of_week_long_tuesday">wtorek</string>
+ <string name="day_of_week_long_wednesday">środa</string>
+ <string name="day_of_week_long_thursday">czwartek</string>
+ <string name="day_of_week_long_friday">piątek</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">niedz.</string>
+ <string name="day_of_week_medium_monday">pon.</string>
+ <string name="day_of_week_medium_tuesday">wt.</string>
+ <string name="day_of_week_medium_wednesday">śr.</string>
+ <string name="day_of_week_medium_thursday">czw.</string>
+ <string name="day_of_week_medium_friday">pt.</string>
+ <string name="day_of_week_medium_saturday">sob.</string>
+
+ <string name="day_of_week_short_sunday">niedz.</string>
+ <string name="day_of_week_short_monday">pon.</string>
+ <string name="day_of_week_short_tuesday">wt.</string>
+ <string name="day_of_week_short_wednesday">śr.</string>
+ <string name="day_of_week_short_thursday">czw.</string>
+ <string name="day_of_week_short_friday">pt.</string>
+ <string name="day_of_week_short_saturday">sob.</string>
+
+ <string name="day_of_week_shortest_sunday">N</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">W</string>
+ <string name="day_of_week_shortest_wednesday">Ś</string>
+ <string name="day_of_week_shortest_thursday">C</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Wczoraj</string>
+ <string name="today">Dzisiaj</string>
+ <string name="tomorrow">Jutro</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d-%m-%Y</string>
+ <string name="numeric_date_format">dd-MM-yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d-%m-%Y</string>
+ <string name="abbrev_month_day_year">%d-%m-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 50d245b..2cd4841 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Hasło"</string>
<string name="lockscreen_glogin_submit_button">"Zaloguj"</string>
<string name="lockscreen_glogin_invalid_input">"Błędna nazwa użytkownika lub hasło."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Wyczyść powiadomienia"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"enter"</string>
<string name="menu_delete_shortcut_label">"usuń"</string>
<string name="search_go">"Szukaj"</string>
- <string name="today">"Dzisiaj"</string>
- <string name="yesterday">"Wczoraj"</string>
- <string name="tomorrow">"Jutro"</string>
<string name="oneMonthDurationPast">"1 miesiąc temu"</string>
<string name="beforeOneMonthDurationPast">"Ponad 1 miesiąc temu"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"tygodni"</string>
<string name="year">"rok"</string>
<string name="years">"lat"</string>
- <string name="sunday">"niedziela"</string>
- <string name="monday">"poniedziałek"</string>
- <string name="tuesday">"wtorek"</string>
- <string name="wednesday">"środa"</string>
- <string name="thursday">"czwartek"</string>
- <string name="friday">"piątek"</string>
- <string name="saturday">"sobota"</string>
<string name="every_weekday">"W każdy dzień roboczy (pon–pt)"</string>
<string name="daily">"Codziennie"</string>
<string name="weekly">"Co tydzień w <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"Przepraszamy, ten film wideo nie nadaje się do przesyłania strumieniowego do tego urządzenia."</string>
<string name="VideoView_error_text_unknown">"Niestety, nie można odtworzyć tego filmu wideo."</string>
<string name="VideoView_error_button">"OK"</string>
- <string name="am">"rano"</string>
- <string name="pm">"po południu"</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"południe"</string>
<string name="Noon">"Południe"</string>
<string name="midnight">"północ"</string>
<string name="Midnight">"Północ"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"niedziela"</string>
- <string name="day_of_week_long_monday">"poniedziałek"</string>
- <string name="day_of_week_long_tuesday">"wtorek"</string>
- <string name="day_of_week_long_wednesday">"środa"</string>
- <string name="day_of_week_long_thursday">"czwartek"</string>
- <string name="day_of_week_long_friday">"piątek"</string>
- <string name="day_of_week_long_saturday">"sobota"</string>
- <string name="day_of_week_medium_sunday">"Nie"</string>
- <string name="day_of_week_medium_monday">"Pon"</string>
- <string name="day_of_week_medium_tuesday">"Wt"</string>
- <string name="day_of_week_medium_wednesday">"Śro"</string>
- <string name="day_of_week_medium_thursday">"Czw"</string>
- <string name="day_of_week_medium_friday">"Pią"</string>
- <string name="day_of_week_medium_saturday">"Sob"</string>
- <string name="day_of_week_short_sunday">"Nd"</string>
- <string name="day_of_week_short_monday">"Pn"</string>
- <string name="day_of_week_short_tuesday">"Wt"</string>
- <string name="day_of_week_short_wednesday">"Śr"</string>
- <string name="day_of_week_short_thursday">"Czw"</string>
- <string name="day_of_week_short_friday">"Pt"</string>
- <string name="day_of_week_short_saturday">"So"</string>
- <string name="day_of_week_shorter_sunday">"Nd"</string>
- <string name="day_of_week_shorter_monday">"Pon"</string>
- <string name="day_of_week_shorter_tuesday">"Wt"</string>
- <string name="day_of_week_shorter_wednesday">"Śr"</string>
- <string name="day_of_week_shorter_thursday">"Czw"</string>
- <string name="day_of_week_shorter_friday">"Pt"</string>
- <string name="day_of_week_shorter_saturday">"So"</string>
- <string name="day_of_week_shortest_sunday">"Nd"</string>
- <string name="day_of_week_shortest_monday">"Pon"</string>
- <string name="day_of_week_shortest_tuesday">"Czw"</string>
- <string name="day_of_week_shortest_wednesday">"Śr"</string>
- <string name="day_of_week_shortest_thursday">"Czw"</string>
- <string name="day_of_week_shortest_friday">"Pt"</string>
- <string name="day_of_week_shortest_saturday">"Sob"</string>
- <string name="month_long_january">"Styczeń"</string>
- <string name="month_long_february">"Luty"</string>
- <string name="month_long_march">"Marzec"</string>
- <string name="month_long_april">"Kwiecień"</string>
- <string name="month_long_may">"Maj"</string>
- <string name="month_long_june">"Czerwiec"</string>
- <string name="month_long_july">"Lipiec"</string>
- <string name="month_long_august">"Sierpień"</string>
- <string name="month_long_september">"Wrzesień"</string>
- <string name="month_long_october">"Październik"</string>
- <string name="month_long_november">"Listopad"</string>
- <string name="month_long_december">"Grudzień"</string>
- <string name="month_medium_january">"Sty"</string>
- <string name="month_medium_february">"Lut"</string>
- <string name="month_medium_march">"Mar"</string>
- <string name="month_medium_april">"Kwi"</string>
- <string name="month_medium_may">"Maj"</string>
- <string name="month_medium_june">"Cze"</string>
- <string name="month_medium_july">"Lip"</string>
- <string name="month_medium_august">"Sie"</string>
- <string name="month_medium_september">"Wrz"</string>
- <string name="month_medium_october">"Paź"</string>
- <string name="month_medium_november">"Lis"</string>
- <string name="month_medium_december">"Gru"</string>
- <string name="month_shortest_january">"Sty"</string>
- <string name="month_shortest_february">"Lut"</string>
- <string name="month_shortest_march">"Pon"</string>
- <string name="month_shortest_april">"Kwi"</string>
- <string name="month_shortest_may">"Maj"</string>
- <string name="month_shortest_june">"Cze"</string>
- <string name="month_shortest_july">"Lip"</string>
- <string name="month_shortest_august">"Sie"</string>
- <string name="month_shortest_september">"Wrz"</string>
- <string name="month_shortest_october">"Paź"</string>
- <string name="month_shortest_november">"Lis"</string>
- <string name="month_shortest_december">"Gru"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Zaznacz wszystko"</string>
diff --git a/core/res/res/values-pt-rBR/donottranslate-cldr.xml b/core/res/res/values-pt-rBR/donottranslate-cldr.xml
new file mode 100644
index 0000000..cf0c29e
--- /dev/null
+++ b/core/res/res/values-pt-rBR/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">janeiro</string>
+ <string name="month_long_standalone_february">fevereiro</string>
+ <string name="month_long_standalone_march">março</string>
+ <string name="month_long_standalone_april">abril</string>
+ <string name="month_long_standalone_may">maio</string>
+ <string name="month_long_standalone_june">junho</string>
+ <string name="month_long_standalone_july">julho</string>
+ <string name="month_long_standalone_august">agosto</string>
+ <string name="month_long_standalone_september">setembro</string>
+ <string name="month_long_standalone_october">outubro</string>
+ <string name="month_long_standalone_november">novembro</string>
+ <string name="month_long_standalone_december">dezembro</string>
+
+ <string name="month_long_january">janeiro</string>
+ <string name="month_long_february">fevereiro</string>
+ <string name="month_long_march">março</string>
+ <string name="month_long_april">abril</string>
+ <string name="month_long_may">maio</string>
+ <string name="month_long_june">junho</string>
+ <string name="month_long_july">julho</string>
+ <string name="month_long_august">agosto</string>
+ <string name="month_long_september">setembro</string>
+ <string name="month_long_october">outubro</string>
+ <string name="month_long_november">novembro</string>
+ <string name="month_long_december">dezembro</string>
+
+ <string name="month_medium_january">jan</string>
+ <string name="month_medium_february">fev</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">abr</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">ago</string>
+ <string name="month_medium_september">set</string>
+ <string name="month_medium_october">out</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domingo</string>
+ <string name="day_of_week_long_monday">segunda-feira</string>
+ <string name="day_of_week_long_tuesday">terça-feira</string>
+ <string name="day_of_week_long_wednesday">quarta-feira</string>
+ <string name="day_of_week_long_thursday">quinta-feira</string>
+ <string name="day_of_week_long_friday">sexta-feira</string>
+ <string name="day_of_week_long_saturday">sábado</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">seg</string>
+ <string name="day_of_week_medium_tuesday">ter</string>
+ <string name="day_of_week_medium_wednesday">qua</string>
+ <string name="day_of_week_medium_thursday">qui</string>
+ <string name="day_of_week_medium_friday">sex</string>
+ <string name="day_of_week_medium_saturday">sáb</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">seg</string>
+ <string name="day_of_week_short_tuesday">ter</string>
+ <string name="day_of_week_short_wednesday">qua</string>
+ <string name="day_of_week_short_thursday">qui</string>
+ <string name="day_of_week_short_friday">sex</string>
+ <string name="day_of_week_short_saturday">sáb</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">S</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">Q</string>
+ <string name="day_of_week_shortest_thursday">Q</string>
+ <string name="day_of_week_shortest_friday">S</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Ontem</string>
+ <string name="today">Hoje</string>
+ <string name="tomorrow">Amanhã</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d/%m/%Y</string>
+ <string name="abbrev_month_day_year">%d/%m/%Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B de %Y</string>
+ <string name="abbrev_month_day">%-e de %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b de %Y</string>
+</resources>
diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
new file mode 100644
index 0000000..d42dc8f
--- /dev/null
+++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Janeiro</string>
+ <string name="month_long_standalone_february">Fevereiro</string>
+ <string name="month_long_standalone_march">Março</string>
+ <string name="month_long_standalone_april">Abril</string>
+ <string name="month_long_standalone_may">Maio</string>
+ <string name="month_long_standalone_june">Junho</string>
+ <string name="month_long_standalone_july">Julho</string>
+ <string name="month_long_standalone_august">Agosto</string>
+ <string name="month_long_standalone_september">Setembro</string>
+ <string name="month_long_standalone_october">Outubro</string>
+ <string name="month_long_standalone_november">Novembro</string>
+ <string name="month_long_standalone_december">Dezembro</string>
+
+ <string name="month_long_january">Janeiro</string>
+ <string name="month_long_february">Fevereiro</string>
+ <string name="month_long_march">Março</string>
+ <string name="month_long_april">Abril</string>
+ <string name="month_long_may">Maio</string>
+ <string name="month_long_june">Junho</string>
+ <string name="month_long_july">Julho</string>
+ <string name="month_long_august">Agosto</string>
+ <string name="month_long_september">Setembro</string>
+ <string name="month_long_october">Outubro</string>
+ <string name="month_long_november">Novembro</string>
+ <string name="month_long_december">Dezembro</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Fev</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Abr</string>
+ <string name="month_medium_may">Mai</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Ago</string>
+ <string name="month_medium_september">Set</string>
+ <string name="month_medium_october">Out</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dez</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">domingo</string>
+ <string name="day_of_week_long_monday">segunda-feira</string>
+ <string name="day_of_week_long_tuesday">terça-feira</string>
+ <string name="day_of_week_long_wednesday">quarta-feira</string>
+ <string name="day_of_week_long_thursday">quinta-feira</string>
+ <string name="day_of_week_long_friday">sexta-feira</string>
+ <string name="day_of_week_long_saturday">sábado</string>
+
+ <string name="day_of_week_medium_sunday">dom</string>
+ <string name="day_of_week_medium_monday">seg</string>
+ <string name="day_of_week_medium_tuesday">ter</string>
+ <string name="day_of_week_medium_wednesday">qua</string>
+ <string name="day_of_week_medium_thursday">qui</string>
+ <string name="day_of_week_medium_friday">sex</string>
+ <string name="day_of_week_medium_saturday">sáb</string>
+
+ <string name="day_of_week_short_sunday">dom</string>
+ <string name="day_of_week_short_monday">seg</string>
+ <string name="day_of_week_short_tuesday">ter</string>
+ <string name="day_of_week_short_wednesday">qua</string>
+ <string name="day_of_week_short_thursday">qui</string>
+ <string name="day_of_week_short_friday">sex</string>
+ <string name="day_of_week_short_saturday">sáb</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">S</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">Q</string>
+ <string name="day_of_week_shortest_thursday">Q</string>
+ <string name="day_of_week_shortest_friday">S</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">Antes do meio-dia</string>
+ <string name="pm">Depois do meio-dia</string>
+ <string name="yesterday">Ontem</string>
+ <string name="today">Hoje</string>
+ <string name="tomorrow">Amanhã</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">%-e de %B de %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e de %b de %Y</string>
+ <string name="abbrev_month_day_year">%-e de %b de %Y</string>
+ <string name="month_day">%-e de %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B de %Y</string>
+ <string name="abbrev_month_day">%-e de %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b de %Y</string>
+</resources>
diff --git a/core/res/res/values-ro-rRO/donottranslate-cldr.xml b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
new file mode 100644
index 0000000..1ed2c81
--- /dev/null
+++ b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">ianuarie</string>
+ <string name="month_long_standalone_february">februarie</string>
+ <string name="month_long_standalone_march">martie</string>
+ <string name="month_long_standalone_april">aprilie</string>
+ <string name="month_long_standalone_may">mai</string>
+ <string name="month_long_standalone_june">iunie</string>
+ <string name="month_long_standalone_july">iulie</string>
+ <string name="month_long_standalone_august">august</string>
+ <string name="month_long_standalone_september">septembrie</string>
+ <string name="month_long_standalone_october">octombrie</string>
+ <string name="month_long_standalone_november">noiembrie</string>
+ <string name="month_long_standalone_december">decembrie</string>
+
+ <string name="month_long_january">ianuarie</string>
+ <string name="month_long_february">februarie</string>
+ <string name="month_long_march">martie</string>
+ <string name="month_long_april">aprilie</string>
+ <string name="month_long_may">mai</string>
+ <string name="month_long_june">iunie</string>
+ <string name="month_long_july">iulie</string>
+ <string name="month_long_august">august</string>
+ <string name="month_long_september">septembrie</string>
+ <string name="month_long_october">octombrie</string>
+ <string name="month_long_november">noiembrie</string>
+ <string name="month_long_december">decembrie</string>
+
+ <string name="month_medium_january">ian.</string>
+ <string name="month_medium_february">feb.</string>
+ <string name="month_medium_march">mar.</string>
+ <string name="month_medium_april">apr.</string>
+ <string name="month_medium_may">mai</string>
+ <string name="month_medium_june">iun.</string>
+ <string name="month_medium_july">iul.</string>
+ <string name="month_medium_august">aug.</string>
+ <string name="month_medium_september">sept.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">I</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">I</string>
+ <string name="month_shortest_july">I</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">duminică</string>
+ <string name="day_of_week_long_monday">luni</string>
+ <string name="day_of_week_long_tuesday">marți</string>
+ <string name="day_of_week_long_wednesday">miercuri</string>
+ <string name="day_of_week_long_thursday">joi</string>
+ <string name="day_of_week_long_friday">vineri</string>
+ <string name="day_of_week_long_saturday">sâmbătă</string>
+
+ <string name="day_of_week_medium_sunday">Du</string>
+ <string name="day_of_week_medium_monday">Lu</string>
+ <string name="day_of_week_medium_tuesday">Ma</string>
+ <string name="day_of_week_medium_wednesday">Mi</string>
+ <string name="day_of_week_medium_thursday">Jo</string>
+ <string name="day_of_week_medium_friday">Vi</string>
+ <string name="day_of_week_medium_saturday">Sâ</string>
+
+ <string name="day_of_week_short_sunday">Du</string>
+ <string name="day_of_week_short_monday">Lu</string>
+ <string name="day_of_week_short_tuesday">Ma</string>
+ <string name="day_of_week_short_wednesday">Mi</string>
+ <string name="day_of_week_short_thursday">Jo</string>
+ <string name="day_of_week_short_friday">Vi</string>
+ <string name="day_of_week_short_saturday">Sâ</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">L</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">J</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">ieri</string>
+ <string name="today">azi</string>
+ <string name="tomorrow">mâine</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S, %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-ru-rRU/donottranslate-cldr.xml b/core/res/res/values-ru-rRU/donottranslate-cldr.xml
new file mode 100644
index 0000000..8faeb44
--- /dev/null
+++ b/core/res/res/values-ru-rRU/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Январь</string>
+ <string name="month_long_standalone_february">Февраль</string>
+ <string name="month_long_standalone_march">Март</string>
+ <string name="month_long_standalone_april">Апрель</string>
+ <string name="month_long_standalone_may">Май</string>
+ <string name="month_long_standalone_june">Июнь</string>
+ <string name="month_long_standalone_july">Июль</string>
+ <string name="month_long_standalone_august">Август</string>
+ <string name="month_long_standalone_september">Сентябрь</string>
+ <string name="month_long_standalone_october">Октябрь</string>
+ <string name="month_long_standalone_november">Ноябрь</string>
+ <string name="month_long_standalone_december">Декабрь</string>
+
+ <string name="month_long_january">января</string>
+ <string name="month_long_february">февраля</string>
+ <string name="month_long_march">марта</string>
+ <string name="month_long_april">апреля</string>
+ <string name="month_long_may">мая</string>
+ <string name="month_long_june">июня</string>
+ <string name="month_long_july">июля</string>
+ <string name="month_long_august">августа</string>
+ <string name="month_long_september">сентября</string>
+ <string name="month_long_october">октября</string>
+ <string name="month_long_november">ноября</string>
+ <string name="month_long_december">декабря</string>
+
+ <string name="month_medium_january">янв.</string>
+ <string name="month_medium_february">февр.</string>
+ <string name="month_medium_march">марта</string>
+ <string name="month_medium_april">апр.</string>
+ <string name="month_medium_may">мая</string>
+ <string name="month_medium_june">июня</string>
+ <string name="month_medium_july">июля</string>
+ <string name="month_medium_august">авг.</string>
+ <string name="month_medium_september">сент.</string>
+ <string name="month_medium_october">окт.</string>
+ <string name="month_medium_november">нояб.</string>
+ <string name="month_medium_december">дек.</string>
+
+ <string name="month_shortest_january">Я</string>
+ <string name="month_shortest_february">Ф</string>
+ <string name="month_shortest_march">М</string>
+ <string name="month_shortest_april">А</string>
+ <string name="month_shortest_may">М</string>
+ <string name="month_shortest_june">И</string>
+ <string name="month_shortest_july">И</string>
+ <string name="month_shortest_august">А</string>
+ <string name="month_shortest_september">С</string>
+ <string name="month_shortest_october">О</string>
+ <string name="month_shortest_november">Н</string>
+ <string name="month_shortest_december">Д</string>
+
+ <string name="day_of_week_long_sunday">воскресенье</string>
+ <string name="day_of_week_long_monday">понедельник</string>
+ <string name="day_of_week_long_tuesday">вторник</string>
+ <string name="day_of_week_long_wednesday">среда</string>
+ <string name="day_of_week_long_thursday">четверг</string>
+ <string name="day_of_week_long_friday">пятница</string>
+ <string name="day_of_week_long_saturday">суббота</string>
+
+ <string name="day_of_week_medium_sunday">Вс</string>
+ <string name="day_of_week_medium_monday">Пн</string>
+ <string name="day_of_week_medium_tuesday">Вт</string>
+ <string name="day_of_week_medium_wednesday">Ср</string>
+ <string name="day_of_week_medium_thursday">Чт</string>
+ <string name="day_of_week_medium_friday">Пт</string>
+ <string name="day_of_week_medium_saturday">Сб</string>
+
+ <string name="day_of_week_short_sunday">Вс</string>
+ <string name="day_of_week_short_monday">Пн</string>
+ <string name="day_of_week_short_tuesday">Вт</string>
+ <string name="day_of_week_short_wednesday">Ср</string>
+ <string name="day_of_week_short_thursday">Чт</string>
+ <string name="day_of_week_short_friday">Пт</string>
+ <string name="day_of_week_short_saturday">Сб</string>
+
+ <string name="day_of_week_shortest_sunday">В</string>
+ <string name="day_of_week_shortest_monday">П</string>
+ <string name="day_of_week_shortest_tuesday">В</string>
+ <string name="day_of_week_shortest_wednesday">С</string>
+ <string name="day_of_week_shortest_thursday">Ч</string>
+ <string name="day_of_week_shortest_friday">П</string>
+ <string name="day_of_week_shortest_saturday">С</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Вчера</string>
+ <string name="today">Сегодня</string>
+ <string name="tomorrow">Завтра</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y г.</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-ru/donottranslate-cldr.xml b/core/res/res/values-ru/donottranslate-cldr.xml
new file mode 100644
index 0000000..8faeb44
--- /dev/null
+++ b/core/res/res/values-ru/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Январь</string>
+ <string name="month_long_standalone_february">Февраль</string>
+ <string name="month_long_standalone_march">Март</string>
+ <string name="month_long_standalone_april">Апрель</string>
+ <string name="month_long_standalone_may">Май</string>
+ <string name="month_long_standalone_june">Июнь</string>
+ <string name="month_long_standalone_july">Июль</string>
+ <string name="month_long_standalone_august">Август</string>
+ <string name="month_long_standalone_september">Сентябрь</string>
+ <string name="month_long_standalone_october">Октябрь</string>
+ <string name="month_long_standalone_november">Ноябрь</string>
+ <string name="month_long_standalone_december">Декабрь</string>
+
+ <string name="month_long_january">января</string>
+ <string name="month_long_february">февраля</string>
+ <string name="month_long_march">марта</string>
+ <string name="month_long_april">апреля</string>
+ <string name="month_long_may">мая</string>
+ <string name="month_long_june">июня</string>
+ <string name="month_long_july">июля</string>
+ <string name="month_long_august">августа</string>
+ <string name="month_long_september">сентября</string>
+ <string name="month_long_october">октября</string>
+ <string name="month_long_november">ноября</string>
+ <string name="month_long_december">декабря</string>
+
+ <string name="month_medium_january">янв.</string>
+ <string name="month_medium_february">февр.</string>
+ <string name="month_medium_march">марта</string>
+ <string name="month_medium_april">апр.</string>
+ <string name="month_medium_may">мая</string>
+ <string name="month_medium_june">июня</string>
+ <string name="month_medium_july">июля</string>
+ <string name="month_medium_august">авг.</string>
+ <string name="month_medium_september">сент.</string>
+ <string name="month_medium_october">окт.</string>
+ <string name="month_medium_november">нояб.</string>
+ <string name="month_medium_december">дек.</string>
+
+ <string name="month_shortest_january">Я</string>
+ <string name="month_shortest_february">Ф</string>
+ <string name="month_shortest_march">М</string>
+ <string name="month_shortest_april">А</string>
+ <string name="month_shortest_may">М</string>
+ <string name="month_shortest_june">И</string>
+ <string name="month_shortest_july">И</string>
+ <string name="month_shortest_august">А</string>
+ <string name="month_shortest_september">С</string>
+ <string name="month_shortest_october">О</string>
+ <string name="month_shortest_november">Н</string>
+ <string name="month_shortest_december">Д</string>
+
+ <string name="day_of_week_long_sunday">воскресенье</string>
+ <string name="day_of_week_long_monday">понедельник</string>
+ <string name="day_of_week_long_tuesday">вторник</string>
+ <string name="day_of_week_long_wednesday">среда</string>
+ <string name="day_of_week_long_thursday">четверг</string>
+ <string name="day_of_week_long_friday">пятница</string>
+ <string name="day_of_week_long_saturday">суббота</string>
+
+ <string name="day_of_week_medium_sunday">Вс</string>
+ <string name="day_of_week_medium_monday">Пн</string>
+ <string name="day_of_week_medium_tuesday">Вт</string>
+ <string name="day_of_week_medium_wednesday">Ср</string>
+ <string name="day_of_week_medium_thursday">Чт</string>
+ <string name="day_of_week_medium_friday">Пт</string>
+ <string name="day_of_week_medium_saturday">Сб</string>
+
+ <string name="day_of_week_short_sunday">Вс</string>
+ <string name="day_of_week_short_monday">Пн</string>
+ <string name="day_of_week_short_tuesday">Вт</string>
+ <string name="day_of_week_short_wednesday">Ср</string>
+ <string name="day_of_week_short_thursday">Чт</string>
+ <string name="day_of_week_short_friday">Пт</string>
+ <string name="day_of_week_short_saturday">Сб</string>
+
+ <string name="day_of_week_shortest_sunday">В</string>
+ <string name="day_of_week_shortest_monday">П</string>
+ <string name="day_of_week_shortest_tuesday">В</string>
+ <string name="day_of_week_shortest_wednesday">С</string>
+ <string name="day_of_week_shortest_thursday">Ч</string>
+ <string name="day_of_week_shortest_friday">П</string>
+ <string name="day_of_week_shortest_saturday">С</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Вчера</string>
+ <string name="today">Сегодня</string>
+ <string name="tomorrow">Завтра</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y г.</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fac6cb7..2a15c43 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"Пароль"</string>
<string name="lockscreen_glogin_submit_button">"Войти"</string>
<string name="lockscreen_glogin_invalid_input">"Недействительное имя пользователя или пароль."</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"Очистить уведомления"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"ввод"</string>
<string name="menu_delete_shortcut_label">"удалить"</string>
<string name="search_go">"Поиск"</string>
- <string name="today">"Сегодня"</string>
- <string name="yesterday">"Вчера"</string>
- <string name="tomorrow">"Завтра"</string>
<string name="oneMonthDurationPast">"1 месяц назад"</string>
<string name="beforeOneMonthDurationPast">"Больше 1 месяца назад"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"недели"</string>
<string name="year">"год"</string>
<string name="years">"годы"</string>
- <string name="sunday">"воскресенье"</string>
- <string name="monday">"понедельник"</string>
- <string name="tuesday">"вторник"</string>
- <string name="wednesday">"среда"</string>
- <string name="thursday">"четверг"</string>
- <string name="friday">"пятница"</string>
- <string name="saturday">"суббота"</string>
<string name="every_weekday">"По рабочим дням (пн-пт)"</string>
<string name="daily">"Ежедневно"</string>
<string name="weekly">"Еженедельно в: <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"К сожалению, это видео не подходит для потокового воспроизведения на данном устройстве."</string>
<string name="VideoView_error_text_unknown">"К сожалению, это видео нельзя воспроизвести."</string>
<string name="VideoView_error_button">"ОК"</string>
- <string name="am">"AM"</string>
- <string name="pm">"PM"</string>
- <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"полдень"</string>
<string name="Noon">"Полдень"</string>
<string name="midnight">"полночь"</string>
<string name="Midnight">"Полночь"</string>
- <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%B</xliff:g> г."</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g> г."</string>
- <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"воскресенье"</string>
- <string name="day_of_week_long_monday">"понедельник"</string>
- <string name="day_of_week_long_tuesday">"вторник"</string>
- <string name="day_of_week_long_wednesday">"среда"</string>
- <string name="day_of_week_long_thursday">"четверг"</string>
- <string name="day_of_week_long_friday">"пятница"</string>
- <string name="day_of_week_long_saturday">"суббота"</string>
- <string name="day_of_week_medium_sunday">"вс"</string>
- <string name="day_of_week_medium_monday">"пн"</string>
- <string name="day_of_week_medium_tuesday">"вт"</string>
- <string name="day_of_week_medium_wednesday">"ср"</string>
- <string name="day_of_week_medium_thursday">"чт"</string>
- <string name="day_of_week_medium_friday">"пт"</string>
- <string name="day_of_week_medium_saturday">"сб"</string>
- <string name="day_of_week_short_sunday">"вс"</string>
- <string name="day_of_week_short_monday">"пн"</string>
- <string name="day_of_week_short_tuesday">"вт"</string>
- <string name="day_of_week_short_wednesday">"ср"</string>
- <string name="day_of_week_short_thursday">"чт"</string>
- <string name="day_of_week_short_friday">"пт"</string>
- <string name="day_of_week_short_saturday">"сб"</string>
- <string name="day_of_week_shorter_sunday">"вс"</string>
- <string name="day_of_week_shorter_monday">"пн"</string>
- <string name="day_of_week_shorter_tuesday">"вт"</string>
- <string name="day_of_week_shorter_wednesday">"с"</string>
- <string name="day_of_week_shorter_thursday">"чт"</string>
- <string name="day_of_week_shorter_friday">"пт"</string>
- <string name="day_of_week_shorter_saturday">"сб"</string>
- <string name="day_of_week_shortest_sunday">"в"</string>
- <string name="day_of_week_shortest_monday">"п"</string>
- <string name="day_of_week_shortest_tuesday">"в"</string>
- <string name="day_of_week_shortest_wednesday">"с"</string>
- <string name="day_of_week_shortest_thursday">"ч"</string>
- <string name="day_of_week_shortest_friday">"п"</string>
- <string name="day_of_week_shortest_saturday">"с"</string>
- <string name="month_long_january">"январь"</string>
- <string name="month_long_february">"февраль"</string>
- <string name="month_long_march">"март"</string>
- <string name="month_long_april">"апрель"</string>
- <string name="month_long_may">"май"</string>
- <string name="month_long_june">"июнь"</string>
- <string name="month_long_july">"июль"</string>
- <string name="month_long_august">"август"</string>
- <string name="month_long_september">"сентябрь"</string>
- <string name="month_long_october">"октябрь"</string>
- <string name="month_long_november">"ноябрь"</string>
- <string name="month_long_december">"декабрь"</string>
- <string name="month_medium_january">"янв"</string>
- <string name="month_medium_february">"фев"</string>
- <string name="month_medium_march">"мар"</string>
- <string name="month_medium_april">"апр"</string>
- <string name="month_medium_may">"май"</string>
- <string name="month_medium_june">"июн"</string>
- <string name="month_medium_july">"июл"</string>
- <string name="month_medium_august">"авг"</string>
- <string name="month_medium_september">"сен"</string>
- <string name="month_medium_october">"окт"</string>
- <string name="month_medium_november">"ноя"</string>
- <string name="month_medium_december">"дек"</string>
- <string name="month_shortest_january">"Я"</string>
- <string name="month_shortest_february">"ф"</string>
- <string name="month_shortest_march">"м"</string>
- <string name="month_shortest_april">"а"</string>
- <string name="month_shortest_may">"м"</string>
- <string name="month_shortest_june">"и"</string>
- <string name="month_shortest_july">"и"</string>
- <string name="month_shortest_august">"а"</string>
- <string name="month_shortest_september">"с"</string>
- <string name="month_shortest_october">"о"</string>
- <string name="month_shortest_november">"н"</string>
- <string name="month_shortest_december">"д"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"Выбрать все"</string>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
new file mode 100644
index 0000000..05bc5d3
--- /dev/null
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">január</string>
+ <string name="month_long_standalone_february">február</string>
+ <string name="month_long_standalone_march">marec</string>
+ <string name="month_long_standalone_april">apríl</string>
+ <string name="month_long_standalone_may">máj</string>
+ <string name="month_long_standalone_june">jún</string>
+ <string name="month_long_standalone_july">júl</string>
+ <string name="month_long_standalone_august">august</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">október</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januára</string>
+ <string name="month_long_february">februára</string>
+ <string name="month_long_march">marca</string>
+ <string name="month_long_april">apríla</string>
+ <string name="month_long_may">mája</string>
+ <string name="month_long_june">júna</string>
+ <string name="month_long_july">júla</string>
+ <string name="month_long_august">augusta</string>
+ <string name="month_long_september">septembra</string>
+ <string name="month_long_october">októbra</string>
+ <string name="month_long_november">novembra</string>
+ <string name="month_long_december">decembra</string>
+
+ <string name="month_medium_january">jan</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">máj</string>
+ <string name="month_medium_june">jún</string>
+ <string name="month_medium_july">júl</string>
+ <string name="month_medium_august">aug</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">okt</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dec</string>
+
+ <string name="month_shortest_january">j</string>
+ <string name="month_shortest_february">f</string>
+ <string name="month_shortest_march">m</string>
+ <string name="month_shortest_april">a</string>
+ <string name="month_shortest_may">m</string>
+ <string name="month_shortest_june">j</string>
+ <string name="month_shortest_july">j</string>
+ <string name="month_shortest_august">a</string>
+ <string name="month_shortest_september">s</string>
+ <string name="month_shortest_october">o</string>
+ <string name="month_shortest_november">n</string>
+ <string name="month_shortest_december">d</string>
+
+ <string name="day_of_week_long_sunday">nedeľa</string>
+ <string name="day_of_week_long_monday">pondelok</string>
+ <string name="day_of_week_long_tuesday">utorok</string>
+ <string name="day_of_week_long_wednesday">streda</string>
+ <string name="day_of_week_long_thursday">štvrtok</string>
+ <string name="day_of_week_long_friday">piatok</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">ne</string>
+ <string name="day_of_week_medium_monday">po</string>
+ <string name="day_of_week_medium_tuesday">ut</string>
+ <string name="day_of_week_medium_wednesday">st</string>
+ <string name="day_of_week_medium_thursday">št</string>
+ <string name="day_of_week_medium_friday">pi</string>
+ <string name="day_of_week_medium_saturday">so</string>
+
+ <string name="day_of_week_short_sunday">ne</string>
+ <string name="day_of_week_short_monday">po</string>
+ <string name="day_of_week_short_tuesday">ut</string>
+ <string name="day_of_week_short_wednesday">st</string>
+ <string name="day_of_week_short_thursday">št</string>
+ <string name="day_of_week_short_friday">pi</string>
+ <string name="day_of_week_short_saturday">so</string>
+
+ <string name="day_of_week_shortest_sunday">N</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">U</string>
+ <string name="day_of_week_shortest_wednesday">S</string>
+ <string name="day_of_week_shortest_thursday">Š</string>
+ <string name="day_of_week_shortest_friday">P</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">dopoludnia</string>
+ <string name="pm">popoludní</string>
+ <string name="yesterday">Včera</string>
+ <string name="today">Dnes</string>
+ <string name="tomorrow">Zajtra</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%-e.%-m.%Y</string>
+ <string name="numeric_date_format">d.M.yyyy</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string>
+ <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
new file mode 100644
index 0000000..e24b070
--- /dev/null
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januar</string>
+ <string name="month_long_standalone_february">februar</string>
+ <string name="month_long_standalone_march">marec</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">maj</string>
+ <string name="month_long_standalone_june">junij</string>
+ <string name="month_long_standalone_july">julij</string>
+ <string name="month_long_standalone_august">avgust</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januar</string>
+ <string name="month_long_february">februar</string>
+ <string name="month_long_march">marec</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">maj</string>
+ <string name="month_long_june">junij</string>
+ <string name="month_long_july">julij</string>
+ <string name="month_long_august">avgust</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">maj</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">avg</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">okt</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dec</string>
+
+ <string name="month_shortest_january">j</string>
+ <string name="month_shortest_february">f</string>
+ <string name="month_shortest_march">m</string>
+ <string name="month_shortest_april">a</string>
+ <string name="month_shortest_may">m</string>
+ <string name="month_shortest_june">j</string>
+ <string name="month_shortest_july">j</string>
+ <string name="month_shortest_august">a</string>
+ <string name="month_shortest_september">s</string>
+ <string name="month_shortest_october">o</string>
+ <string name="month_shortest_november">n</string>
+ <string name="month_shortest_december">d</string>
+
+ <string name="day_of_week_long_sunday">nedelja</string>
+ <string name="day_of_week_long_monday">ponedeljek</string>
+ <string name="day_of_week_long_tuesday">torek</string>
+ <string name="day_of_week_long_wednesday">sreda</string>
+ <string name="day_of_week_long_thursday">četrtek</string>
+ <string name="day_of_week_long_friday">petek</string>
+ <string name="day_of_week_long_saturday">sobota</string>
+
+ <string name="day_of_week_medium_sunday">ned</string>
+ <string name="day_of_week_medium_monday">pon</string>
+ <string name="day_of_week_medium_tuesday">tor</string>
+ <string name="day_of_week_medium_wednesday">sre</string>
+ <string name="day_of_week_medium_thursday">čet</string>
+ <string name="day_of_week_medium_friday">pet</string>
+ <string name="day_of_week_medium_saturday">sob</string>
+
+ <string name="day_of_week_short_sunday">ned</string>
+ <string name="day_of_week_short_monday">pon</string>
+ <string name="day_of_week_short_tuesday">tor</string>
+ <string name="day_of_week_short_wednesday">sre</string>
+ <string name="day_of_week_short_thursday">čet</string>
+ <string name="day_of_week_short_friday">pet</string>
+ <string name="day_of_week_short_saturday">sob</string>
+
+ <string name="day_of_week_shortest_sunday">n</string>
+ <string name="day_of_week_shortest_monday">p</string>
+ <string name="day_of_week_shortest_tuesday">t</string>
+ <string name="day_of_week_shortest_wednesday">s</string>
+ <string name="day_of_week_shortest_thursday">č</string>
+ <string name="day_of_week_shortest_friday">p</string>
+ <string name="day_of_week_shortest_saturday">s</string>
+
+ <string name="am">dop.</string>
+ <string name="pm">pop.</string>
+ <string name="yesterday">Včeraj</string>
+ <string name="today">Danes</string>
+ <string name="tomorrow">Jutri</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%-e. %m. %Y</string>
+ <string name="numeric_date_format">d. MM. yyyy</string>
+ <string name="month_day_year">%d. %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e. %b. %Y</string>
+ <string name="abbrev_month_day_year">%-e. %b. %Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-sr-rRS/donottranslate-cldr.xml b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
new file mode 100644
index 0000000..7f98ae2
--- /dev/null
+++ b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">јануар</string>
+ <string name="month_long_standalone_february">фебруар</string>
+ <string name="month_long_standalone_march">март</string>
+ <string name="month_long_standalone_april">април</string>
+ <string name="month_long_standalone_may">мај</string>
+ <string name="month_long_standalone_june">јун</string>
+ <string name="month_long_standalone_july">јул</string>
+ <string name="month_long_standalone_august">август</string>
+ <string name="month_long_standalone_september">септембар</string>
+ <string name="month_long_standalone_october">октобар</string>
+ <string name="month_long_standalone_november">новембар</string>
+ <string name="month_long_standalone_december">децембар</string>
+
+ <string name="month_long_january">јануар</string>
+ <string name="month_long_february">фебруар</string>
+ <string name="month_long_march">март</string>
+ <string name="month_long_april">април</string>
+ <string name="month_long_may">мај</string>
+ <string name="month_long_june">јун</string>
+ <string name="month_long_july">јул</string>
+ <string name="month_long_august">август</string>
+ <string name="month_long_september">септембар</string>
+ <string name="month_long_october">октобар</string>
+ <string name="month_long_november">новембар</string>
+ <string name="month_long_december">децембар</string>
+
+ <string name="month_medium_january">јан</string>
+ <string name="month_medium_february">феб</string>
+ <string name="month_medium_march">мар</string>
+ <string name="month_medium_april">апр</string>
+ <string name="month_medium_may">мај</string>
+ <string name="month_medium_june">јун</string>
+ <string name="month_medium_july">јул</string>
+ <string name="month_medium_august">авг</string>
+ <string name="month_medium_september">сеп</string>
+ <string name="month_medium_october">окт</string>
+ <string name="month_medium_november">нов</string>
+ <string name="month_medium_december">дец</string>
+
+ <string name="month_shortest_january">ј</string>
+ <string name="month_shortest_february">ф</string>
+ <string name="month_shortest_march">м</string>
+ <string name="month_shortest_april">а</string>
+ <string name="month_shortest_may">м</string>
+ <string name="month_shortest_june">ј</string>
+ <string name="month_shortest_july">ј</string>
+ <string name="month_shortest_august">а</string>
+ <string name="month_shortest_september">с</string>
+ <string name="month_shortest_october">о</string>
+ <string name="month_shortest_november">н</string>
+ <string name="month_shortest_december">д</string>
+
+ <string name="day_of_week_long_sunday">недеља</string>
+ <string name="day_of_week_long_monday">понедељак</string>
+ <string name="day_of_week_long_tuesday">уторак</string>
+ <string name="day_of_week_long_wednesday">среда</string>
+ <string name="day_of_week_long_thursday">четвртак</string>
+ <string name="day_of_week_long_friday">петак</string>
+ <string name="day_of_week_long_saturday">субота</string>
+
+ <string name="day_of_week_medium_sunday">нед</string>
+ <string name="day_of_week_medium_monday">пон</string>
+ <string name="day_of_week_medium_tuesday">уто</string>
+ <string name="day_of_week_medium_wednesday">сре</string>
+ <string name="day_of_week_medium_thursday">чет</string>
+ <string name="day_of_week_medium_friday">пет</string>
+ <string name="day_of_week_medium_saturday">суб</string>
+
+ <string name="day_of_week_short_sunday">нед</string>
+ <string name="day_of_week_short_monday">пон</string>
+ <string name="day_of_week_short_tuesday">уто</string>
+ <string name="day_of_week_short_wednesday">сре</string>
+ <string name="day_of_week_short_thursday">чет</string>
+ <string name="day_of_week_short_friday">пет</string>
+ <string name="day_of_week_short_saturday">суб</string>
+
+ <string name="day_of_week_shortest_sunday">н</string>
+ <string name="day_of_week_shortest_monday">п</string>
+ <string name="day_of_week_shortest_tuesday">у</string>
+ <string name="day_of_week_shortest_wednesday">с</string>
+ <string name="day_of_week_shortest_thursday">ч</string>
+ <string name="day_of_week_shortest_friday">п</string>
+ <string name="day_of_week_shortest_saturday">с</string>
+
+ <string name="am">пре подне</string>
+ <string name="pm">поподне</string>
+ <string name="yesterday">јуче</string>
+ <string name="today">данас</string>
+ <string name="tomorrow">сутра</string>
+
+ <string name="hour_minute_ampm">%H.%M</string>
+ <string name="hour_minute_cap_ampm">%H.%M</string>
+ <string name="numeric_date">%-e.%-m.%Y.</string>
+ <string name="numeric_date_format">d.M.yyyy.</string>
+ <string name="month_day_year">%d. %B %Y.</string>
+ <string name="time_of_day">%H.%M.%S</string>
+ <string name="date_and_time">%H.%M.%S %d.%m.%Y.</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y.</string>
+ <string name="month_day">%B %-e.</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%b %-e.</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b. %Y</string>
+</resources>
diff --git a/core/res/res/values-sv-rSE/donottranslate-cldr.xml b/core/res/res/values-sv-rSE/donottranslate-cldr.xml
new file mode 100644
index 0000000..4570245
--- /dev/null
+++ b/core/res/res/values-sv-rSE/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">januari</string>
+ <string name="month_long_standalone_february">februari</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">april</string>
+ <string name="month_long_standalone_may">maj</string>
+ <string name="month_long_standalone_june">juni</string>
+ <string name="month_long_standalone_july">juli</string>
+ <string name="month_long_standalone_august">augusti</string>
+ <string name="month_long_standalone_september">september</string>
+ <string name="month_long_standalone_october">oktober</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">januari</string>
+ <string name="month_long_february">februari</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">april</string>
+ <string name="month_long_may">maj</string>
+ <string name="month_long_june">juni</string>
+ <string name="month_long_july">juli</string>
+ <string name="month_long_august">augusti</string>
+ <string name="month_long_september">september</string>
+ <string name="month_long_october">oktober</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">jan</string>
+ <string name="month_medium_february">feb</string>
+ <string name="month_medium_march">mar</string>
+ <string name="month_medium_april">apr</string>
+ <string name="month_medium_may">maj</string>
+ <string name="month_medium_june">jun</string>
+ <string name="month_medium_july">jul</string>
+ <string name="month_medium_august">aug</string>
+ <string name="month_medium_september">sep</string>
+ <string name="month_medium_october">okt</string>
+ <string name="month_medium_november">nov</string>
+ <string name="month_medium_december">dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">söndag</string>
+ <string name="day_of_week_long_monday">måndag</string>
+ <string name="day_of_week_long_tuesday">tisdag</string>
+ <string name="day_of_week_long_wednesday">onsdag</string>
+ <string name="day_of_week_long_thursday">torsdag</string>
+ <string name="day_of_week_long_friday">fredag</string>
+ <string name="day_of_week_long_saturday">lördag</string>
+
+ <string name="day_of_week_medium_sunday">sön</string>
+ <string name="day_of_week_medium_monday">mån</string>
+ <string name="day_of_week_medium_tuesday">tis</string>
+ <string name="day_of_week_medium_wednesday">ons</string>
+ <string name="day_of_week_medium_thursday">tors</string>
+ <string name="day_of_week_medium_friday">fre</string>
+ <string name="day_of_week_medium_saturday">lör</string>
+
+ <string name="day_of_week_short_sunday">sön</string>
+ <string name="day_of_week_short_monday">mån</string>
+ <string name="day_of_week_short_tuesday">tis</string>
+ <string name="day_of_week_short_wednesday">ons</string>
+ <string name="day_of_week_short_thursday">tors</string>
+ <string name="day_of_week_short_friday">fre</string>
+ <string name="day_of_week_short_saturday">lör</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">O</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">L</string>
+
+ <string name="am">f.m.</string>
+ <string name="pm">e.m.</string>
+ <string name="yesterday">igår</string>
+ <string name="today">idag</string>
+ <string name="tomorrow">imorgon</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%Y-%m-%d</string>
+ <string name="numeric_date_format">yyyy-MM-dd</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y %B</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y %b</string>
+</resources>
diff --git a/core/res/res/values-th-rTH/donottranslate-cldr.xml b/core/res/res/values-th-rTH/donottranslate-cldr.xml
new file mode 100644
index 0000000..cc680f6
--- /dev/null
+++ b/core/res/res/values-th-rTH/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">มกราคม</string>
+ <string name="month_long_standalone_february">กุมภาพันธ์</string>
+ <string name="month_long_standalone_march">มีนาคม</string>
+ <string name="month_long_standalone_april">เมษายน</string>
+ <string name="month_long_standalone_may">พฤษภาคม</string>
+ <string name="month_long_standalone_june">มิถุนายน</string>
+ <string name="month_long_standalone_july">กรกฎาคม</string>
+ <string name="month_long_standalone_august">สิงหาคม</string>
+ <string name="month_long_standalone_september">กันยายน</string>
+ <string name="month_long_standalone_october">ตุลาคม</string>
+ <string name="month_long_standalone_november">พฤศจิกายน</string>
+ <string name="month_long_standalone_december">ธันวาคม</string>
+
+ <string name="month_long_january">มกราคม</string>
+ <string name="month_long_february">กุมภาพันธ์</string>
+ <string name="month_long_march">มีนาคม</string>
+ <string name="month_long_april">เมษายน</string>
+ <string name="month_long_may">พฤษภาคม</string>
+ <string name="month_long_june">มิถุนายน</string>
+ <string name="month_long_july">กรกฎาคม</string>
+ <string name="month_long_august">สิงหาคม</string>
+ <string name="month_long_september">กันยายน</string>
+ <string name="month_long_october">ตุลาคม</string>
+ <string name="month_long_november">พฤศจิกายน</string>
+ <string name="month_long_december">ธันวาคม</string>
+
+ <string name="month_medium_january">ม.ค.</string>
+ <string name="month_medium_february">ก.พ.</string>
+ <string name="month_medium_march">มี.ค.</string>
+ <string name="month_medium_april">เม.ย.</string>
+ <string name="month_medium_may">พ.ค.</string>
+ <string name="month_medium_june">มิ.ย.</string>
+ <string name="month_medium_july">ก.ค.</string>
+ <string name="month_medium_august">ส.ค.</string>
+ <string name="month_medium_september">ก.ย.</string>
+ <string name="month_medium_october">ต.ค.</string>
+ <string name="month_medium_november">พ.ย.</string>
+ <string name="month_medium_december">ธ.ค.</string>
+
+ <string name="month_shortest_january">ม.ค.</string>
+ <string name="month_shortest_february">ก.พ.</string>
+ <string name="month_shortest_march">มี.ค.</string>
+ <string name="month_shortest_april">เม.ย.</string>
+ <string name="month_shortest_may">พ.ค.</string>
+ <string name="month_shortest_june">มิ.ย.</string>
+ <string name="month_shortest_july">ก.ค.</string>
+ <string name="month_shortest_august">ส.ค.</string>
+ <string name="month_shortest_september">ก.ย.</string>
+ <string name="month_shortest_october">ต.ค.</string>
+ <string name="month_shortest_november">พ.ย.</string>
+ <string name="month_shortest_december">ธ.ค.</string>
+
+ <string name="day_of_week_long_sunday">วันอาทิตย์</string>
+ <string name="day_of_week_long_monday">วันจันทร์</string>
+ <string name="day_of_week_long_tuesday">วันอังคาร</string>
+ <string name="day_of_week_long_wednesday">วันพุธ</string>
+ <string name="day_of_week_long_thursday">วันพฤหัสบดี</string>
+ <string name="day_of_week_long_friday">วันศุกร์</string>
+ <string name="day_of_week_long_saturday">วันเสาร์</string>
+
+ <string name="day_of_week_medium_sunday">อา.</string>
+ <string name="day_of_week_medium_monday">จ.</string>
+ <string name="day_of_week_medium_tuesday">อ.</string>
+ <string name="day_of_week_medium_wednesday">พ.</string>
+ <string name="day_of_week_medium_thursday">พฤ.</string>
+ <string name="day_of_week_medium_friday">ศ.</string>
+ <string name="day_of_week_medium_saturday">ส.</string>
+
+ <string name="day_of_week_short_sunday">อา.</string>
+ <string name="day_of_week_short_monday">จ.</string>
+ <string name="day_of_week_short_tuesday">อ.</string>
+ <string name="day_of_week_short_wednesday">พ.</string>
+ <string name="day_of_week_short_thursday">พฤ.</string>
+ <string name="day_of_week_short_friday">ศ.</string>
+ <string name="day_of_week_short_saturday">ส.</string>
+
+ <string name="day_of_week_shortest_sunday">อ</string>
+ <string name="day_of_week_shortest_monday">จ</string>
+ <string name="day_of_week_shortest_tuesday">อ</string>
+ <string name="day_of_week_shortest_wednesday">พ</string>
+ <string name="day_of_week_shortest_thursday">พ</string>
+ <string name="day_of_week_shortest_friday">ศ</string>
+ <string name="day_of_week_shortest_saturday">ส</string>
+
+ <string name="am">ก่อนเที่ยง</string>
+ <string name="pm">หลังเที่ยง</string>
+ <string name="yesterday">เมื่อวาน</string>
+ <string name="today">วันนี้</string>
+ <string name="tomorrow">พรุ่งนี้</string>
+
+ <string name="hour_minute_ampm">%-k:%M</string>
+ <string name="hour_minute_cap_ampm">%-k:%M</string>
+ <string name="numeric_date">%-e/%-m/%Y</string>
+ <string name="numeric_date_format">d/M/yyyy</string>
+ <string name="month_day_year">%-e %B %Y</string>
+ <string name="time_of_day">%-k:%M:%S</string>
+ <string name="date_and_time">%-k:%M:%S, %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-tr-rTR/donottranslate-cldr.xml b/core/res/res/values-tr-rTR/donottranslate-cldr.xml
new file mode 100644
index 0000000..acc0121
--- /dev/null
+++ b/core/res/res/values-tr-rTR/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Ocak</string>
+ <string name="month_long_standalone_february">Şubat</string>
+ <string name="month_long_standalone_march">Mart</string>
+ <string name="month_long_standalone_april">Nisan</string>
+ <string name="month_long_standalone_may">Mayıs</string>
+ <string name="month_long_standalone_june">Haziran</string>
+ <string name="month_long_standalone_july">Temmuz</string>
+ <string name="month_long_standalone_august">Ağustos</string>
+ <string name="month_long_standalone_september">Eylül</string>
+ <string name="month_long_standalone_october">Ekim</string>
+ <string name="month_long_standalone_november">Kasım</string>
+ <string name="month_long_standalone_december">Aralık</string>
+
+ <string name="month_long_january">Ocak</string>
+ <string name="month_long_february">Şubat</string>
+ <string name="month_long_march">Mart</string>
+ <string name="month_long_april">Nisan</string>
+ <string name="month_long_may">Mayıs</string>
+ <string name="month_long_june">Haziran</string>
+ <string name="month_long_july">Temmuz</string>
+ <string name="month_long_august">Ağustos</string>
+ <string name="month_long_september">Eylül</string>
+ <string name="month_long_october">Ekim</string>
+ <string name="month_long_november">Kasım</string>
+ <string name="month_long_december">Aralık</string>
+
+ <string name="month_medium_january">Oca</string>
+ <string name="month_medium_february">Şub</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Nis</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Haz</string>
+ <string name="month_medium_july">Tem</string>
+ <string name="month_medium_august">Ağu</string>
+ <string name="month_medium_september">Eyl</string>
+ <string name="month_medium_october">Eki</string>
+ <string name="month_medium_november">Kas</string>
+ <string name="month_medium_december">Ara</string>
+
+ <string name="month_shortest_january">O</string>
+ <string name="month_shortest_february">Ş</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">N</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">H</string>
+ <string name="month_shortest_july">T</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">E</string>
+ <string name="month_shortest_october">E</string>
+ <string name="month_shortest_november">K</string>
+ <string name="month_shortest_december">A</string>
+
+ <string name="day_of_week_long_sunday">Pazar</string>
+ <string name="day_of_week_long_monday">Pazartesi</string>
+ <string name="day_of_week_long_tuesday">Salı</string>
+ <string name="day_of_week_long_wednesday">Çarşamba</string>
+ <string name="day_of_week_long_thursday">Perşembe</string>
+ <string name="day_of_week_long_friday">Cuma</string>
+ <string name="day_of_week_long_saturday">Cumartesi</string>
+
+ <string name="day_of_week_medium_sunday">Paz</string>
+ <string name="day_of_week_medium_monday">Pzt</string>
+ <string name="day_of_week_medium_tuesday">Sal</string>
+ <string name="day_of_week_medium_wednesday">Çar</string>
+ <string name="day_of_week_medium_thursday">Per</string>
+ <string name="day_of_week_medium_friday">Cum</string>
+ <string name="day_of_week_medium_saturday">Cmt</string>
+
+ <string name="day_of_week_short_sunday">Paz</string>
+ <string name="day_of_week_short_monday">Pzt</string>
+ <string name="day_of_week_short_tuesday">Sal</string>
+ <string name="day_of_week_short_wednesday">Çar</string>
+ <string name="day_of_week_short_thursday">Per</string>
+ <string name="day_of_week_short_friday">Cum</string>
+ <string name="day_of_week_short_saturday">Cmt</string>
+
+ <string name="day_of_week_shortest_sunday">P</string>
+ <string name="day_of_week_shortest_monday">P</string>
+ <string name="day_of_week_shortest_tuesday">S</string>
+ <string name="day_of_week_shortest_wednesday">Ç</string>
+ <string name="day_of_week_shortest_thursday">P</string>
+ <string name="day_of_week_shortest_friday">C</string>
+ <string name="day_of_week_shortest_saturday">C</string>
+
+ <string name="am">AM</string>
+ <string name="pm">PM</string>
+ <string name="yesterday">Dün</string>
+ <string name="today">Bugün</string>
+ <string name="tomorrow">Yarın</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d %m %Y</string>
+ <string name="numeric_date_format">dd MM yyyy</string>
+ <string name="month_day_year">%d %B %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %d %b %Y</string>
+ <string name="abbrev_month_day_year">%d %b %Y</string>
+ <string name="month_day">%d %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%d %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
new file mode 100644
index 0000000..888df36
--- /dev/null
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">Січень</string>
+ <string name="month_long_standalone_february">Лютий</string>
+ <string name="month_long_standalone_march">Березень</string>
+ <string name="month_long_standalone_april">Квітень</string>
+ <string name="month_long_standalone_may">Травень</string>
+ <string name="month_long_standalone_june">Червень</string>
+ <string name="month_long_standalone_july">Липень</string>
+ <string name="month_long_standalone_august">Серпень</string>
+ <string name="month_long_standalone_september">Вересень</string>
+ <string name="month_long_standalone_october">Жовтень</string>
+ <string name="month_long_standalone_november">Листопад</string>
+ <string name="month_long_standalone_december">Грудень</string>
+
+ <string name="month_long_january">січня</string>
+ <string name="month_long_february">лютого</string>
+ <string name="month_long_march">березня</string>
+ <string name="month_long_april">квітня</string>
+ <string name="month_long_may">травня</string>
+ <string name="month_long_june">червня</string>
+ <string name="month_long_july">липня</string>
+ <string name="month_long_august">серпня</string>
+ <string name="month_long_september">вересня</string>
+ <string name="month_long_october">жовтня</string>
+ <string name="month_long_november">листопада</string>
+ <string name="month_long_december">грудня</string>
+
+ <string name="month_medium_january">січ.</string>
+ <string name="month_medium_february">лют.</string>
+ <string name="month_medium_march">бер.</string>
+ <string name="month_medium_april">квіт.</string>
+ <string name="month_medium_may">трав.</string>
+ <string name="month_medium_june">черв.</string>
+ <string name="month_medium_july">лип.</string>
+ <string name="month_medium_august">серп.</string>
+ <string name="month_medium_september">вер.</string>
+ <string name="month_medium_october">жовт.</string>
+ <string name="month_medium_november">лист.</string>
+ <string name="month_medium_december">груд.</string>
+
+ <string name="month_shortest_january">С</string>
+ <string name="month_shortest_february">Л</string>
+ <string name="month_shortest_march">Б</string>
+ <string name="month_shortest_april">К</string>
+ <string name="month_shortest_may">Т</string>
+ <string name="month_shortest_june">Ч</string>
+ <string name="month_shortest_july">Л</string>
+ <string name="month_shortest_august">С</string>
+ <string name="month_shortest_september">В</string>
+ <string name="month_shortest_october">Ж</string>
+ <string name="month_shortest_november">Л</string>
+ <string name="month_shortest_december">Г</string>
+
+ <string name="day_of_week_long_sunday">Неділя</string>
+ <string name="day_of_week_long_monday">Понеділок</string>
+ <string name="day_of_week_long_tuesday">Вівторок</string>
+ <string name="day_of_week_long_wednesday">Середа</string>
+ <string name="day_of_week_long_thursday">Четвер</string>
+ <string name="day_of_week_long_friday">Пʼятниця</string>
+ <string name="day_of_week_long_saturday">Субота</string>
+
+ <string name="day_of_week_medium_sunday">Нд</string>
+ <string name="day_of_week_medium_monday">Пн</string>
+ <string name="day_of_week_medium_tuesday">Вт</string>
+ <string name="day_of_week_medium_wednesday">Ср</string>
+ <string name="day_of_week_medium_thursday">Чт</string>
+ <string name="day_of_week_medium_friday">Пт</string>
+ <string name="day_of_week_medium_saturday">Сб</string>
+
+ <string name="day_of_week_short_sunday">Нд</string>
+ <string name="day_of_week_short_monday">Пн</string>
+ <string name="day_of_week_short_tuesday">Вт</string>
+ <string name="day_of_week_short_wednesday">Ср</string>
+ <string name="day_of_week_short_thursday">Чт</string>
+ <string name="day_of_week_short_friday">Пт</string>
+ <string name="day_of_week_short_saturday">Сб</string>
+
+ <string name="day_of_week_shortest_sunday">Н</string>
+ <string name="day_of_week_shortest_monday">П</string>
+ <string name="day_of_week_shortest_tuesday">В</string>
+ <string name="day_of_week_shortest_wednesday">С</string>
+ <string name="day_of_week_shortest_thursday">Ч</string>
+ <string name="day_of_week_shortest_friday">П</string>
+ <string name="day_of_week_shortest_saturday">С</string>
+
+ <string name="am">дп</string>
+ <string name="pm">пп</string>
+ <string name="yesterday">Вчора</string>
+ <string name="today">Сьогодні</string>
+ <string name="tomorrow">Завтра</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="month_day_year">%-e %B %Y р.</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%H:%M:%S %-e %b %Y</string>
+ <string name="abbrev_month_day_year">%-e %b %Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%-B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%-b %Y</string>
+</resources>
diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
new file mode 100644
index 0000000..2a28b32
--- /dev/null
+++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">tháng một</string>
+ <string name="month_long_standalone_february">tháng hai</string>
+ <string name="month_long_standalone_march">tháng ba</string>
+ <string name="month_long_standalone_april">tháng tư</string>
+ <string name="month_long_standalone_may">tháng năm</string>
+ <string name="month_long_standalone_june">tháng sáu</string>
+ <string name="month_long_standalone_july">tháng bảy</string>
+ <string name="month_long_standalone_august">tháng tám</string>
+ <string name="month_long_standalone_september">tháng chín</string>
+ <string name="month_long_standalone_october">tháng mười</string>
+ <string name="month_long_standalone_november">tháng mười một</string>
+ <string name="month_long_standalone_december">tháng mười hai</string>
+
+ <string name="month_long_january">tháng một</string>
+ <string name="month_long_february">tháng hai</string>
+ <string name="month_long_march">tháng ba</string>
+ <string name="month_long_april">tháng tư</string>
+ <string name="month_long_may">tháng năm</string>
+ <string name="month_long_june">tháng sáu</string>
+ <string name="month_long_july">tháng bảy</string>
+ <string name="month_long_august">tháng tám</string>
+ <string name="month_long_september">tháng chín</string>
+ <string name="month_long_october">tháng mười</string>
+ <string name="month_long_november">tháng mười một</string>
+ <string name="month_long_december">tháng mười hai</string>
+
+ <string name="month_medium_january">thg 1</string>
+ <string name="month_medium_february">thg 2</string>
+ <string name="month_medium_march">thg 3</string>
+ <string name="month_medium_april">thg 4</string>
+ <string name="month_medium_may">thg 5</string>
+ <string name="month_medium_june">thg 6</string>
+ <string name="month_medium_july">thg 7</string>
+ <string name="month_medium_august">thg 8</string>
+ <string name="month_medium_september">thg 9</string>
+ <string name="month_medium_october">thg 10</string>
+ <string name="month_medium_november">thg 11</string>
+ <string name="month_medium_december">thg 12</string>
+
+ <string name="month_shortest_january">1</string>
+ <string name="month_shortest_february">2</string>
+ <string name="month_shortest_march">3</string>
+ <string name="month_shortest_april">4</string>
+ <string name="month_shortest_may">5</string>
+ <string name="month_shortest_june">6</string>
+ <string name="month_shortest_july">7</string>
+ <string name="month_shortest_august">8</string>
+ <string name="month_shortest_september">9</string>
+ <string name="month_shortest_october">10</string>
+ <string name="month_shortest_november">11</string>
+ <string name="month_shortest_december">12</string>
+
+ <string name="day_of_week_long_sunday">Chủ nhật</string>
+ <string name="day_of_week_long_monday">Thứ hai</string>
+ <string name="day_of_week_long_tuesday">Thứ ba</string>
+ <string name="day_of_week_long_wednesday">Thứ tư</string>
+ <string name="day_of_week_long_thursday">Thứ năm</string>
+ <string name="day_of_week_long_friday">Thứ sáu</string>
+ <string name="day_of_week_long_saturday">Thứ bảy</string>
+
+ <string name="day_of_week_medium_sunday">CN</string>
+ <string name="day_of_week_medium_monday">Th 2</string>
+ <string name="day_of_week_medium_tuesday">Th 3</string>
+ <string name="day_of_week_medium_wednesday">Th 4</string>
+ <string name="day_of_week_medium_thursday">Th 5</string>
+ <string name="day_of_week_medium_friday">Th 6</string>
+ <string name="day_of_week_medium_saturday">Th 7</string>
+
+ <string name="day_of_week_short_sunday">CN</string>
+ <string name="day_of_week_short_monday">Th 2</string>
+ <string name="day_of_week_short_tuesday">Th 3</string>
+ <string name="day_of_week_short_wednesday">Th 4</string>
+ <string name="day_of_week_short_thursday">Th 5</string>
+ <string name="day_of_week_short_friday">Th 6</string>
+ <string name="day_of_week_short_saturday">Th 7</string>
+
+ <string name="day_of_week_shortest_sunday">1</string>
+ <string name="day_of_week_shortest_monday">2</string>
+ <string name="day_of_week_shortest_tuesday">3</string>
+ <string name="day_of_week_shortest_wednesday">4</string>
+ <string name="day_of_week_shortest_thursday">5</string>
+ <string name="day_of_week_shortest_friday">6</string>
+ <string name="day_of_week_shortest_saturday">7</string>
+
+ <string name="am">SA</string>
+ <string name="pm">CH</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%H:%M</string>
+ <string name="hour_minute_cap_ampm">%H:%M</string>
+ <string name="numeric_date">%d/%m/%Y</string>
+ <string name="numeric_date_format">dd/MM/yyyy</string>
+ <string name="month_day_year">Ngày %d tháng %-m năm %Y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="date_and_time">%d-%m-%Y %H:%M:%S</string>
+ <string name="abbrev_month_day_year">%d-%m-%Y</string>
+ <string name="month_day">%-e %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
new file mode 100644
index 0000000..18e37a9
--- /dev/null
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">一月</string>
+ <string name="month_long_standalone_february">二月</string>
+ <string name="month_long_standalone_march">三月</string>
+ <string name="month_long_standalone_april">四月</string>
+ <string name="month_long_standalone_may">五月</string>
+ <string name="month_long_standalone_june">六月</string>
+ <string name="month_long_standalone_july">七月</string>
+ <string name="month_long_standalone_august">八月</string>
+ <string name="month_long_standalone_september">九月</string>
+ <string name="month_long_standalone_october">十月</string>
+ <string name="month_long_standalone_november">十一月</string>
+ <string name="month_long_standalone_december">十二月</string>
+
+ <string name="month_long_january">1月</string>
+ <string name="month_long_february">2月</string>
+ <string name="month_long_march">3月</string>
+ <string name="month_long_april">4月</string>
+ <string name="month_long_may">5月</string>
+ <string name="month_long_june">6月</string>
+ <string name="month_long_july">7月</string>
+ <string name="month_long_august">8月</string>
+ <string name="month_long_september">9月</string>
+ <string name="month_long_october">10月</string>
+ <string name="month_long_november">11月</string>
+ <string name="month_long_december">12月</string>
+
+ <string name="month_medium_january">1月</string>
+ <string name="month_medium_february">2月</string>
+ <string name="month_medium_march">3月</string>
+ <string name="month_medium_april">4月</string>
+ <string name="month_medium_may">5月</string>
+ <string name="month_medium_june">6月</string>
+ <string name="month_medium_july">7月</string>
+ <string name="month_medium_august">8月</string>
+ <string name="month_medium_september">9月</string>
+ <string name="month_medium_october">10月</string>
+ <string name="month_medium_november">11月</string>
+ <string name="month_medium_december">12月</string>
+
+ <string name="month_shortest_january">1月</string>
+ <string name="month_shortest_february">2月</string>
+ <string name="month_shortest_march">3月</string>
+ <string name="month_shortest_april">4月</string>
+ <string name="month_shortest_may">5月</string>
+ <string name="month_shortest_june">6月</string>
+ <string name="month_shortest_july">7月</string>
+ <string name="month_shortest_august">8月</string>
+ <string name="month_shortest_september">9月</string>
+ <string name="month_shortest_october">10月</string>
+ <string name="month_shortest_november">11月</string>
+ <string name="month_shortest_december">12月</string>
+
+ <string name="day_of_week_long_sunday">星期日</string>
+ <string name="day_of_week_long_monday">星期一</string>
+ <string name="day_of_week_long_tuesday">星期二</string>
+ <string name="day_of_week_long_wednesday">星期三</string>
+ <string name="day_of_week_long_thursday">星期四</string>
+ <string name="day_of_week_long_friday">星期五</string>
+ <string name="day_of_week_long_saturday">星期六</string>
+
+ <string name="day_of_week_medium_sunday">周日</string>
+ <string name="day_of_week_medium_monday">周一</string>
+ <string name="day_of_week_medium_tuesday">周二</string>
+ <string name="day_of_week_medium_wednesday">周三</string>
+ <string name="day_of_week_medium_thursday">周四</string>
+ <string name="day_of_week_medium_friday">周五</string>
+ <string name="day_of_week_medium_saturday">周六</string>
+
+ <string name="day_of_week_short_sunday">周日</string>
+ <string name="day_of_week_short_monday">周一</string>
+ <string name="day_of_week_short_tuesday">周二</string>
+ <string name="day_of_week_short_wednesday">周三</string>
+ <string name="day_of_week_short_thursday">周四</string>
+ <string name="day_of_week_short_friday">周五</string>
+ <string name="day_of_week_short_saturday">周六</string>
+
+ <string name="day_of_week_shortest_sunday">日</string>
+ <string name="day_of_week_shortest_monday">一</string>
+ <string name="day_of_week_shortest_tuesday">二</string>
+ <string name="day_of_week_shortest_wednesday">三</string>
+ <string name="day_of_week_shortest_thursday">四</string>
+ <string name="day_of_week_shortest_friday">五</string>
+ <string name="day_of_week_shortest_saturday">六</string>
+
+ <string name="am">上午</string>
+ <string name="pm">下午</string>
+ <string name="yesterday">昨天</string>
+ <string name="today">今天</string>
+ <string name="tomorrow">明天</string>
+
+ <string name="hour_minute_ampm">%p%-l:%M</string>
+ <string name="hour_minute_cap_ampm">%^p%-l:%M</string>
+ <string name="numeric_date">%Y-%-m-%-e</string>
+ <string name="numeric_date_format">yyyy-M-d</string>
+ <string name="month_day_year">%Y年%-m月%-e日</string>
+ <string name="time_of_day">%p%I:%M:%S</string>
+ <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string>
+ <string name="abbrev_month_day_year">%Y-%-m-%-e</string>
+ <string name="month_day">%B%-e日</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y年%B</string>
+ <string name="abbrev_month_day">%b%-e日</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y年%b</string>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 54b0b97..ee7b3cd 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -424,9 +424,6 @@
<string name="lockscreen_glogin_password_hint">"密码"</string>
<string name="lockscreen_glogin_submit_button">"登录"</string>
<string name="lockscreen_glogin_invalid_input">"用户名或密码无效。"</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="AMPM">%P</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string>
<string name="hour_cap_ampm">"<xliff:g id="AMPM">%p</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string>
<string name="status_bar_clear_all_button">"清除通知"</string>
@@ -458,9 +455,6 @@
<string name="menu_enter_shortcut_label">"Enter 键"</string>
<string name="menu_delete_shortcut_label">"删除"</string>
<string name="search_go">"搜索"</string>
- <string name="today">"今天"</string>
- <string name="yesterday">"昨天"</string>
- <string name="tomorrow">"明天"</string>
<string name="oneMonthDurationPast">"1 个月前"</string>
<string name="beforeOneMonthDurationPast">"1 个月前"</string>
<plurals name="num_seconds_ago">
@@ -542,13 +536,6 @@
<string name="weeks">"周"</string>
<string name="year">"年"</string>
<string name="years">"年"</string>
- <string name="sunday">"周日"</string>
- <string name="monday">"周一"</string>
- <string name="tuesday">"周二"</string>
- <string name="wednesday">"周三"</string>
- <string name="thursday">"周四"</string>
- <string name="friday">"周五"</string>
- <string name="saturday">"周六"</string>
<string name="every_weekday">"每个工作日(周一到周五)"</string>
<string name="daily">"每天"</string>
<string name="weekly">"每周的<xliff:g id="DAY">%s</xliff:g>"</string>
@@ -558,9 +545,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"抱歉,该视频不适合在此设备上播放。"</string>
<string name="VideoView_error_text_unknown">"很抱歉,此视频不能播放。"</string>
<string name="VideoView_error_button">"确定"</string>
- <string name="am">"上午"</string>
- <string name="pm">"下午"</string>
- <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%m</xliff:g> 月 <xliff:g id="DAY">%d</xliff:g> 日"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> 至 <xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> 至 <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -572,23 +556,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="DAY">d</xliff:g>' 月 '<xliff:g id="MONTH">MMM</xliff:g>' 日'"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"中午"</string>
<string name="Noon">"中午"</string>
<string name="midnight">"午夜"</string>
<string name="Midnight">"午夜"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string>
- <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日 <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string>
@@ -613,82 +586,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string>
- <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> 月"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"周日"</string>
- <string name="day_of_week_long_monday">"周一"</string>
- <string name="day_of_week_long_tuesday">"周二"</string>
- <string name="day_of_week_long_wednesday">"周三"</string>
- <string name="day_of_week_long_thursday">"周四"</string>
- <string name="day_of_week_long_friday">"周五"</string>
- <string name="day_of_week_long_saturday">"周六"</string>
- <string name="day_of_week_medium_sunday">"周日"</string>
- <string name="day_of_week_medium_monday">"周一"</string>
- <string name="day_of_week_medium_tuesday">"周二"</string>
- <string name="day_of_week_medium_wednesday">"周三"</string>
- <string name="day_of_week_medium_thursday">"周四"</string>
- <string name="day_of_week_medium_friday">"周五"</string>
- <string name="day_of_week_medium_saturday">"周六"</string>
- <string name="day_of_week_short_sunday">"周日"</string>
- <string name="day_of_week_short_monday">"周一"</string>
- <string name="day_of_week_short_tuesday">"周二"</string>
- <string name="day_of_week_short_wednesday">"周三"</string>
- <string name="day_of_week_short_thursday">"周四"</string>
- <string name="day_of_week_short_friday">"周五"</string>
- <string name="day_of_week_short_saturday">"周六"</string>
- <string name="day_of_week_shorter_sunday">"周日"</string>
- <string name="day_of_week_shorter_monday">"周一"</string>
- <string name="day_of_week_shorter_tuesday">"周二"</string>
- <string name="day_of_week_shorter_wednesday">"周三"</string>
- <string name="day_of_week_shorter_thursday">"周四"</string>
- <string name="day_of_week_shorter_friday">"周五"</string>
- <string name="day_of_week_shorter_saturday">"周六"</string>
- <string name="day_of_week_shortest_sunday">"周日"</string>
- <string name="day_of_week_shortest_monday">"周一"</string>
- <string name="day_of_week_shortest_tuesday">"周二"</string>
- <string name="day_of_week_shortest_wednesday">"周三"</string>
- <string name="day_of_week_shortest_thursday">"周四"</string>
- <string name="day_of_week_shortest_friday">"周五"</string>
- <string name="day_of_week_shortest_saturday">"周六"</string>
- <string name="month_long_january">"1 月"</string>
- <string name="month_long_february">"2 月"</string>
- <string name="month_long_march">"3 月"</string>
- <string name="month_long_april">"4 月"</string>
- <string name="month_long_may">"5 月"</string>
- <string name="month_long_june">"6 月"</string>
- <string name="month_long_july">"7 月"</string>
- <string name="month_long_august">"8 月"</string>
- <string name="month_long_september">"9 月"</string>
- <string name="month_long_october">"10 月"</string>
- <string name="month_long_november">"11 月"</string>
- <string name="month_long_december">"12 月"</string>
- <string name="month_medium_january">"1 月"</string>
- <string name="month_medium_february">"2 月"</string>
- <string name="month_medium_march">"3 月"</string>
- <string name="month_medium_april">"4 月"</string>
- <string name="month_medium_may">"5 月"</string>
- <string name="month_medium_june">"6 月"</string>
- <string name="month_medium_july">"7 月"</string>
- <string name="month_medium_august">"8 月"</string>
- <string name="month_medium_september">"9 月"</string>
- <string name="month_medium_october">"10 月"</string>
- <string name="month_medium_november">"11 月"</string>
- <string name="month_medium_december">"12 月"</string>
- <string name="month_shortest_january">"1 月"</string>
- <string name="month_shortest_february">"2 月"</string>
- <string name="month_shortest_march">"3 月"</string>
- <string name="month_shortest_april">"4 月"</string>
- <string name="month_shortest_may">"5 月"</string>
- <string name="month_shortest_june">"6 月"</string>
- <string name="month_shortest_july">"7 月"</string>
- <string name="month_shortest_august">"8 月"</string>
- <string name="month_shortest_september">"9 月"</string>
- <string name="month_shortest_october">"10 月"</string>
- <string name="month_shortest_november">"11 月"</string>
- <string name="month_shortest_december">"12 月"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"全选"</string>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
new file mode 100644
index 0000000..18e37a9
--- /dev/null
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">一月</string>
+ <string name="month_long_standalone_february">二月</string>
+ <string name="month_long_standalone_march">三月</string>
+ <string name="month_long_standalone_april">四月</string>
+ <string name="month_long_standalone_may">五月</string>
+ <string name="month_long_standalone_june">六月</string>
+ <string name="month_long_standalone_july">七月</string>
+ <string name="month_long_standalone_august">八月</string>
+ <string name="month_long_standalone_september">九月</string>
+ <string name="month_long_standalone_october">十月</string>
+ <string name="month_long_standalone_november">十一月</string>
+ <string name="month_long_standalone_december">十二月</string>
+
+ <string name="month_long_january">1月</string>
+ <string name="month_long_february">2月</string>
+ <string name="month_long_march">3月</string>
+ <string name="month_long_april">4月</string>
+ <string name="month_long_may">5月</string>
+ <string name="month_long_june">6月</string>
+ <string name="month_long_july">7月</string>
+ <string name="month_long_august">8月</string>
+ <string name="month_long_september">9月</string>
+ <string name="month_long_october">10月</string>
+ <string name="month_long_november">11月</string>
+ <string name="month_long_december">12月</string>
+
+ <string name="month_medium_january">1月</string>
+ <string name="month_medium_february">2月</string>
+ <string name="month_medium_march">3月</string>
+ <string name="month_medium_april">4月</string>
+ <string name="month_medium_may">5月</string>
+ <string name="month_medium_june">6月</string>
+ <string name="month_medium_july">7月</string>
+ <string name="month_medium_august">8月</string>
+ <string name="month_medium_september">9月</string>
+ <string name="month_medium_october">10月</string>
+ <string name="month_medium_november">11月</string>
+ <string name="month_medium_december">12月</string>
+
+ <string name="month_shortest_january">1月</string>
+ <string name="month_shortest_february">2月</string>
+ <string name="month_shortest_march">3月</string>
+ <string name="month_shortest_april">4月</string>
+ <string name="month_shortest_may">5月</string>
+ <string name="month_shortest_june">6月</string>
+ <string name="month_shortest_july">7月</string>
+ <string name="month_shortest_august">8月</string>
+ <string name="month_shortest_september">9月</string>
+ <string name="month_shortest_october">10月</string>
+ <string name="month_shortest_november">11月</string>
+ <string name="month_shortest_december">12月</string>
+
+ <string name="day_of_week_long_sunday">星期日</string>
+ <string name="day_of_week_long_monday">星期一</string>
+ <string name="day_of_week_long_tuesday">星期二</string>
+ <string name="day_of_week_long_wednesday">星期三</string>
+ <string name="day_of_week_long_thursday">星期四</string>
+ <string name="day_of_week_long_friday">星期五</string>
+ <string name="day_of_week_long_saturday">星期六</string>
+
+ <string name="day_of_week_medium_sunday">周日</string>
+ <string name="day_of_week_medium_monday">周一</string>
+ <string name="day_of_week_medium_tuesday">周二</string>
+ <string name="day_of_week_medium_wednesday">周三</string>
+ <string name="day_of_week_medium_thursday">周四</string>
+ <string name="day_of_week_medium_friday">周五</string>
+ <string name="day_of_week_medium_saturday">周六</string>
+
+ <string name="day_of_week_short_sunday">周日</string>
+ <string name="day_of_week_short_monday">周一</string>
+ <string name="day_of_week_short_tuesday">周二</string>
+ <string name="day_of_week_short_wednesday">周三</string>
+ <string name="day_of_week_short_thursday">周四</string>
+ <string name="day_of_week_short_friday">周五</string>
+ <string name="day_of_week_short_saturday">周六</string>
+
+ <string name="day_of_week_shortest_sunday">日</string>
+ <string name="day_of_week_shortest_monday">一</string>
+ <string name="day_of_week_shortest_tuesday">二</string>
+ <string name="day_of_week_shortest_wednesday">三</string>
+ <string name="day_of_week_shortest_thursday">四</string>
+ <string name="day_of_week_shortest_friday">五</string>
+ <string name="day_of_week_shortest_saturday">六</string>
+
+ <string name="am">上午</string>
+ <string name="pm">下午</string>
+ <string name="yesterday">昨天</string>
+ <string name="today">今天</string>
+ <string name="tomorrow">明天</string>
+
+ <string name="hour_minute_ampm">%p%-l:%M</string>
+ <string name="hour_minute_cap_ampm">%^p%-l:%M</string>
+ <string name="numeric_date">%Y-%-m-%-e</string>
+ <string name="numeric_date_format">yyyy-M-d</string>
+ <string name="month_day_year">%Y年%-m月%-e日</string>
+ <string name="time_of_day">%p%I:%M:%S</string>
+ <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string>
+ <string name="abbrev_month_day_year">%Y-%-m-%-e</string>
+ <string name="month_day">%B%-e日</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%Y年%B</string>
+ <string name="abbrev_month_day">%b%-e日</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%Y年%b</string>
+</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 514e304..a742228 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -418,9 +418,6 @@
<string name="lockscreen_glogin_password_hint">"密碼"</string>
<string name="lockscreen_glogin_submit_button">"登入"</string>
<string name="lockscreen_glogin_invalid_input">"使用者名稱或密碼錯誤。"</string>
- <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
- <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
- <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button">"清除通知"</string>
@@ -452,9 +449,6 @@
<string name="menu_enter_shortcut_label">"輸入"</string>
<string name="menu_delete_shortcut_label">"刪除"</string>
<string name="search_go">"搜尋"</string>
- <string name="today">"今天"</string>
- <string name="yesterday">"昨天"</string>
- <string name="tomorrow">"明天"</string>
<string name="oneMonthDurationPast">"1 個月以前"</string>
<string name="beforeOneMonthDurationPast">"1 個月前"</string>
<plurals name="num_seconds_ago">
@@ -536,13 +530,6 @@
<string name="weeks">"週"</string>
<string name="year">"年"</string>
<string name="years">"年"</string>
- <string name="sunday">"星期日"</string>
- <string name="monday">"星期一"</string>
- <string name="tuesday">"星期二"</string>
- <string name="wednesday">"星期三"</string>
- <string name="thursday">"星期四"</string>
- <string name="friday">"星期五"</string>
- <string name="saturday">"星期六"</string>
<string name="every_weekday">"每天 (週一至週五)"</string>
<string name="daily">"每天"</string>
<string name="weekly">"每週<xliff:g id="DAY">%s</xliff:g>"</string>
@@ -552,9 +539,6 @@
<string name="VideoView_error_text_invalid_progressive_playback">"很抱歉,影片格式無效,裝置無法進行串流處理。"</string>
<string name="VideoView_error_text_unknown">"很抱歉,此影片無法播放。"</string>
<string name="VideoView_error_button">"確定"</string>
- <string name="am">"上午"</string>
- <string name="pm">"下午"</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="WEEKDAY2">%4$s</xliff:g>,<xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,23 +550,12 @@
<string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>,<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
- <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
- <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string>
- <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
- <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
- <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
<string name="noon">"中午"</string>
<string name="Noon">"中午"</string>
<string name="midnight">"午夜"</string>
<string name="Midnight">"午夜"</string>
- <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string>
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string>
- <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年<xliff:g id="MONTH">%B</xliff:g>"</string>
- <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日,<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
<string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
<string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string>
<string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日"</string>
@@ -607,82 +580,8 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string>
- <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g>"</string>
- <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string>
<!-- no translation found for abbrev_month (3131032032850777433) -->
<skip />
- <string name="day_of_week_long_sunday">"星期日"</string>
- <string name="day_of_week_long_monday">"星期一"</string>
- <string name="day_of_week_long_tuesday">"星期二"</string>
- <string name="day_of_week_long_wednesday">"星期三"</string>
- <string name="day_of_week_long_thursday">"星期四"</string>
- <string name="day_of_week_long_friday">"星期五"</string>
- <string name="day_of_week_long_saturday">"星期六"</string>
- <string name="day_of_week_medium_sunday">"週日"</string>
- <string name="day_of_week_medium_monday">"週一"</string>
- <string name="day_of_week_medium_tuesday">"週二"</string>
- <string name="day_of_week_medium_wednesday">"週三"</string>
- <string name="day_of_week_medium_thursday">"週四"</string>
- <string name="day_of_week_medium_friday">"五"</string>
- <string name="day_of_week_medium_saturday">"週六"</string>
- <string name="day_of_week_short_sunday">"日"</string>
- <string name="day_of_week_short_monday">"一"</string>
- <string name="day_of_week_short_tuesday">"二"</string>
- <string name="day_of_week_short_wednesday">"三"</string>
- <string name="day_of_week_short_thursday">"週四"</string>
- <string name="day_of_week_short_friday">"五"</string>
- <string name="day_of_week_short_saturday">"六"</string>
- <string name="day_of_week_shorter_sunday">"日"</string>
- <string name="day_of_week_shorter_monday">"一"</string>
- <string name="day_of_week_shorter_tuesday">"二"</string>
- <string name="day_of_week_shorter_wednesday">"三"</string>
- <string name="day_of_week_shorter_thursday">"四"</string>
- <string name="day_of_week_shorter_friday">"五"</string>
- <string name="day_of_week_shorter_saturday">"六"</string>
- <string name="day_of_week_shortest_sunday">"日"</string>
- <string name="day_of_week_shortest_monday">"一"</string>
- <string name="day_of_week_shortest_tuesday">"二"</string>
- <string name="day_of_week_shortest_wednesday">"三"</string>
- <string name="day_of_week_shortest_thursday">"四"</string>
- <string name="day_of_week_shortest_friday">"五"</string>
- <string name="day_of_week_shortest_saturday">"六"</string>
- <string name="month_long_january">"1 月"</string>
- <string name="month_long_february">"2 月"</string>
- <string name="month_long_march">"3 月"</string>
- <string name="month_long_april">"4 月"</string>
- <string name="month_long_may">"5 月"</string>
- <string name="month_long_june">"6 月"</string>
- <string name="month_long_july">"7 月"</string>
- <string name="month_long_august">"8 月"</string>
- <string name="month_long_september">"9 月"</string>
- <string name="month_long_october">"10 月"</string>
- <string name="month_long_november">"11 月"</string>
- <string name="month_long_december">"12 月"</string>
- <string name="month_medium_january">"1 月"</string>
- <string name="month_medium_february">"2 月"</string>
- <string name="month_medium_march">"3 月"</string>
- <string name="month_medium_april">"4 月"</string>
- <string name="month_medium_may">"5 月"</string>
- <string name="month_medium_june">"6 月"</string>
- <string name="month_medium_july">"7 月"</string>
- <string name="month_medium_august">"8 月"</string>
- <string name="month_medium_september">"9 月"</string>
- <string name="month_medium_october">"10 月"</string>
- <string name="month_medium_november">"11 月"</string>
- <string name="month_medium_december">"12 月"</string>
- <string name="month_shortest_january">"1"</string>
- <string name="month_shortest_february">"2"</string>
- <string name="month_shortest_march">"3"</string>
- <string name="month_shortest_april">"4"</string>
- <string name="month_shortest_may">"5"</string>
- <string name="month_shortest_june">"6"</string>
- <string name="month_shortest_july">"7"</string>
- <string name="month_shortest_august">"8"</string>
- <string name="month_shortest_september">"9"</string>
- <string name="month_shortest_october">"10"</string>
- <string name="month_shortest_november">"11"</string>
- <string name="month_shortest_december">"12"</string>
<string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll">"全部選取"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 7db73f0..eb94812 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -110,7 +110,10 @@
<item><xliff:g id="id">alarm_clock</xliff:g></item>
<item><xliff:g id="id">battery</xliff:g></item>
<item><xliff:g id="id">phone_signal</xliff:g></item>
+ <item><xliff:g id="id">phone_evdo_signal</xliff:g></item>
<item><xliff:g id="id">data_connection</xliff:g></item>
+ <item><xliff:g id="id">cdma_eri</xliff:g></item>
+ <item><xliff:g id="id">tty</xliff:g></item>
<item><xliff:g id="id">volume</xliff:g></item>
<item><xliff:g id="id">mute</xliff:g></item>
<item><xliff:g id="id">speakerphone</xliff:g></item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 40a8af2..60c70cf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -79,6 +79,9 @@
<attr name="textColorPrimaryInverseNoDisable" format="reference|color" />
<!-- Dim inverse text color. This does not differentiate the disabled state. -->
<attr name="textColorSecondaryInverseNoDisable" format="reference|color" />
+
+ <!-- Text color for urls in search suggestions, used by things like global search and the browser. @hide -->
+ <attr name="textColorSearchUrl" format="reference|color" />
<!-- Text color, typeface, size, and style for "large" text. Defaults to primary text color. -->
<attr name="textAppearanceLarge" format="reference" />
@@ -99,6 +102,7 @@
<!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. @hide -->
<attr name="textAppearanceSearchResultSubtitle" format="reference" />
+
<!-- Text color, typeface, size, and style for the text inside of a button. -->
<attr name="textAppearanceButton" format="reference" />
@@ -152,8 +156,8 @@
<!-- The preferred list item height -->
<attr name="listPreferredItemHeight" format="dimension" />
<!-- The drawable for the list divider -->
- <!-- The list item height for search results. @hide -->
- <attr name="searchResultListItemHeight" format="dimension" />
+ <!-- The list item height for search results. @hide -->
+ <attr name="searchResultListItemHeight" format="dimension" />
<attr name="listDivider" format="reference" />
<!-- TextView style for list separators. -->
<attr name="listSeparatorTextViewStyle" format="reference" />
@@ -663,9 +667,9 @@
<attr name="x" format="dimension" />
<!-- A coordinate in the Y dimension. -->
<attr name="y" format="dimension" />
-
- <!-- Specifies how to place an object, both
- its x and y axis, within a larger containing object. -->
+
+ <!-- Specifies how to place the content of an object, both
+ on the x and y axis, within the object itself. -->
<attr name="gravity">
<!-- Push object to the top of its container, not changing its size. -->
<flag name="top" value="0x30" />
@@ -721,8 +725,7 @@
<attr name="entries" format="reference" />
<!-- Standard gravity constant that a child can supply to its parent.
- Defines how to place an object, both
- its x and y axis, within a larger containing object. -->
+ Defines how to place the view, both its x and y axis, within its parent view group. -->
<attr name="layout_gravity">
<!-- Push object to the top of its container, not changing its size. -->
<flag name="top" value="0x30" />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 8150067..96369f4 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -73,5 +73,8 @@
<color name="perms_normal_grp_color">#eeeeee</color>
<color name="perms_normal_perm_color">#c0c0c0</color>
+ <!-- For search-related UIs -->
+ <color name="search_url_text">#7fa87f</color>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 83ac8e2..f655b27 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -34,4 +34,8 @@
<!-- The duration (in milliseconds) of a long animation. -->
<integer name="config_longAnimTime">300</integer>
+
+ <!-- Flag indicating whether Last Name comes before First Name.
+ This becomes true in Japan, for example.-->
+ <bool name="config_lastname_comes_before_firstname">false</bool>
</resources>
diff --git a/core/res/res/values/donottranslate-cldr.xml b/core/res/res/values/donottranslate-cldr.xml
new file mode 100644
index 0000000..f305948
--- /dev/null
+++ b/core/res/res/values/donottranslate-cldr.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">January</string>
+ <string name="month_long_standalone_february">February</string>
+ <string name="month_long_standalone_march">March</string>
+ <string name="month_long_standalone_april">April</string>
+ <string name="month_long_standalone_may">May</string>
+ <string name="month_long_standalone_june">June</string>
+ <string name="month_long_standalone_july">July</string>
+ <string name="month_long_standalone_august">August</string>
+ <string name="month_long_standalone_september">September</string>
+ <string name="month_long_standalone_october">October</string>
+ <string name="month_long_standalone_november">November</string>
+ <string name="month_long_standalone_december">December</string>
+
+ <string name="month_long_january">January</string>
+ <string name="month_long_february">February</string>
+ <string name="month_long_march">March</string>
+ <string name="month_long_april">April</string>
+ <string name="month_long_may">May</string>
+ <string name="month_long_june">June</string>
+ <string name="month_long_july">July</string>
+ <string name="month_long_august">August</string>
+ <string name="month_long_september">September</string>
+ <string name="month_long_october">October</string>
+ <string name="month_long_november">November</string>
+ <string name="month_long_december">December</string>
+
+ <string name="month_medium_january">Jan</string>
+ <string name="month_medium_february">Feb</string>
+ <string name="month_medium_march">Mar</string>
+ <string name="month_medium_april">Apr</string>
+ <string name="month_medium_may">May</string>
+ <string name="month_medium_june">Jun</string>
+ <string name="month_medium_july">Jul</string>
+ <string name="month_medium_august">Aug</string>
+ <string name="month_medium_september">Sep</string>
+ <string name="month_medium_october">Oct</string>
+ <string name="month_medium_november">Nov</string>
+ <string name="month_medium_december">Dec</string>
+
+ <string name="month_shortest_january">J</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">J</string>
+ <string name="month_shortest_july">J</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="day_of_week_long_sunday">Sunday</string>
+ <string name="day_of_week_long_monday">Monday</string>
+ <string name="day_of_week_long_tuesday">Tuesday</string>
+ <string name="day_of_week_long_wednesday">Wednesday</string>
+ <string name="day_of_week_long_thursday">Thursday</string>
+ <string name="day_of_week_long_friday">Friday</string>
+ <string name="day_of_week_long_saturday">Saturday</string>
+
+ <string name="day_of_week_medium_sunday">Sun</string>
+ <string name="day_of_week_medium_monday">Mon</string>
+ <string name="day_of_week_medium_tuesday">Tue</string>
+ <string name="day_of_week_medium_wednesday">Wed</string>
+ <string name="day_of_week_medium_thursday">Thu</string>
+ <string name="day_of_week_medium_friday">Fri</string>
+ <string name="day_of_week_medium_saturday">Sat</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">a.m.</string>
+ <string name="pm">p.m.</string>
+ <string name="yesterday">Yesterday</string>
+ <string name="today">Today</string>
+ <string name="tomorrow">Tomorrow</string>
+
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="numeric_date">%-m/%-e/%Y</string>
+ <string name="numeric_date_format">M/d/yyyy</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%-l:%M:%S %p %b %-e, %Y</string>
+ <string name="abbrev_month_day_year">%b %-e, %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ae45d64..199eac1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1091,30 +1091,56 @@
=============================================================== -->
<eat-comment />
- <public type="attr" name="tension" id="0x0101026a" />
- <public type="attr" name="extraTension" id="0x0101026b" />
- <public type="attr" name="density" id="0x0101026c" />
- <public type="attr" name="searchSuggestThreshold" id="0x0101026d" />
- <public type="attr" name="includeInGlobalSearch" id="0x0101026e" />
- <public type="attr" name="onClick" id="0x0101026f" />
- <public type="attr" name="targetSdkVersion" id="0x01010270" />
- <public type="attr" name="maxSdkVersion" id="0x01010271" />
- <public type="attr" name="testOnly" id="0x01010272" />
- <public type="attr" name="contentDescription" id="0x01010273" />
+ <public type="attr" name="tension" id="0x0101026a" />
+ <public type="attr" name="extraTension" />
+ <public type="attr" name="density" />
+ <public type="attr" name="searchSuggestThreshold" />
+ <public type="attr" name="includeInGlobalSearch" />
+ <public type="attr" name="onClick" />
+ <public type="attr" name="targetSdkVersion" />
+ <public type="attr" name="maxSdkVersion" />
+ <public type="attr" name="testOnly" />
+ <public type="attr" name="contentDescription" />
+
+ <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
- <public type="anim" name="anticipate_interpolator" id="0x010a0007" />
- <public type="anim" name="overshoot_interpolator" id="0x010a0008" />
- <public type="anim" name="anticipate_overshoot_interpolator" id="0x010a0009" />
- <public type="anim" name="bounce_interpolator" id="0x010a000a" />
+ <public-padding type="id" name="donut_resource_pad" end="0x01020040" />
+
+ <public-padding type="style" name="donut_resource_pad" end="0x01030070" />
+
+ <public-padding type="string" name="donut_resource_pad" end="0x01040030" />
- <public type="drawable" name="stat_sys_vp_phone_call" id="0x0108022d" />
- <public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x0108022e" />
+ <public-padding type="dimen" name="donut_resource_pad" end="0x01050010" />
+ <public-padding type="color" name="donut_resource_pad" end="0x01060030" />
+
+ <public-padding type="array" name="donut_resource_pad" end="0x01070010" />
+
+ <public-padding type="anim" name="donut_resource_pad" end="0x010a0020" />
+
+ <public-padding type="integer" name="donut_resource_pad" end="0x010e0010" />
+
+ <public type="anim" name="anticipate_interpolator" />
+ <public type="anim" name="overshoot_interpolator" />
+ <public type="anim" name="anticipate_overshoot_interpolator" />
+ <public type="anim" name="bounce_interpolator" />
+ <public type="anim" name="linear_interpolator" />
+
+ <public-padding type="drawable" name="donut_resource_pad" end="0x010800d0" />
+
+ <public-padding type="layout" name="donut_resource_pad" end="0x01090020" />
+
+
<!-- ===============================================================
- Resources added in version 5 of the platform.
+ Resources added in Eclair.
=============================================================== -->
<eat-comment />
- <public type="attr" name="accountType" id="0x01010274" />
- <public type="attr" name="contentAuthority" id="0x01010275" />
+ <public type="attr" name="accountType" />
+ <public type="attr" name="contentAuthority" />
+
+ <public type="drawable" name="stat_sys_vp_phone_call" />
+ <public type="drawable" name="stat_sys_vp_phone_call_on_hold" />
+
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a8145deb..5bd8308 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -480,6 +480,12 @@
state. Does not perform a complete shutdown.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_stopAppSwitches">prevent app switches</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_stopAppSwitches">Prevents the user from switching to
+ another application.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_runSetActivityWatcher">monitor and control all application launching</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_runSetActivityWatcher">Allows an application to
@@ -770,13 +776,7 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_installLocationProvider">Create mock location sources for testing.
Malicious applications can use this to override the location and/or status returned by real
- location sources such as GPS or Network providers.</string>
-
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_installLocationCollector">permission to install a location collector</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_installLocationCollector">Create mock location sources for testing.
- Malicious applications can use this to monitor and report your location to an external source.</string>
+ location sources such as GPS or Network providers or monitor and report your location to an external source.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessFineLocation">fine (GPS) location</string>
@@ -1076,7 +1076,7 @@
user dictionary.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_sdcardWrite">write to SD card</string>
+ <string name="permlab_sdcardWrite">modify/delete SD card contents</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string>
@@ -1251,15 +1251,6 @@
<!-- Displayed to the user when unlocking the phone with a username and password fails. -->
<string name="lockscreen_glogin_invalid_input">Invalid username or password.</string>
- <!-- A format string for 12-hour time of day (example: "12:30 PM"). -->
- <string name="status_bar_time_format">"<xliff:g id="hour" example="12">h</xliff:g>:<xliff:g id="minute" example="30">mm</xliff:g> <xliff:g id="ampm" example="AM">AA</xliff:g>"</string>
-
- <!-- A format string for 12-hour time of day, with lower-case "am" or "pm" (example: "12:30pm"). -->
- <string name="hour_minute_ampm">"<xliff:g id="hour" example="12">%-l</xliff:g>:<xliff:g id="minute" example="30">%M</xliff:g><xliff:g id="ampm" example="am">%P</xliff:g>"</string>
-
- <!-- A format string for 12-hour time of day, with capital "AM" or "PM" (example: "12:30PM"). -->
- <string name="hour_minute_cap_ampm">"<xliff:g id="hour" example="12">%-l</xliff:g>:<xliff:g id="minute" example="30">%M</xliff:g><xliff:g id="ampm" example="AM">%p</xliff:g>"</string>
-
<!-- A format string for 12-hour time of day, just the hour, not the minute, with lower-case "am" or "pm" (example: "3pm"). -->
<string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
@@ -1360,12 +1351,6 @@
It is also used by the home screen's search "widget". It should be short -->
<string name="search_go">Search</string>
- <!-- String used to display the date. This is shown instead of a date if the date is today's date. -->
- <string name="today">Today</string>
- <!-- String used to display the date. This is shown instead of a date if the date is yesterday's date. -->
- <string name="yesterday">Yesterday</string>
- <!-- String used to display the date. This is shown instead of a date if the date is tomorrow's date. -->
- <string name="tomorrow">Tomorrow</string>
<!-- String used to display the date. This is the string to say something happened 1 month ago. -->
<string name="oneMonthDurationPast">1 month ago</string>
<!-- String used to display the date. This is the string to say something happened more than 1 month ago. -->
@@ -1499,21 +1484,6 @@
<!-- Appened to express the value is this unit of time. -->
<string name="years">years</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="sunday">Sunday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="monday">Monday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="tuesday">Tuesday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="wednesday">Wednesday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="thursday">Thursday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="friday">Friday</string>
- <!-- Used in the list of which days of the week a calendar event recurrs on -->
- <string name="saturday">Saturday</string>
-
<!-- Calendar spinner item, to select that an event recurs every weekday. -->
<string name="every_weekday">"Every weekday (Mon\u2013Fri)"</string>
<!-- Calendar spinner item, to select that an event recurs every day. -->
@@ -1536,17 +1506,7 @@
<string name="VideoView_error_button">OK</string>
- <!-- AM - as in morning - as in 10:30 AM -->
- <string name="am">"AM"</string>
-
- <!-- PM - as in afternoon - as in 10:30 PM -->
- <string name="pm">"PM"</string>
-
-
- <!-- Numeric form of the day. Example: "12/31/2007" -->
- <string name="numeric_date">"<xliff:g id="month" example="12">%m</xliff:g>/<xliff:g id="day" example="31">%d</xliff:g>/<xliff:g id="year" example="2008">%Y</xliff:g>"</string>
-
- <!-- Format indicating a range of time, from a time on one day to a time on another day.
+ <!-- Format indicating a range of time, from a time on one day to a time on another day.
Example: "Mon, Dec 31, 2007, 8am - Tue, Jan 1, 2008, 5pm" -->
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="weekday1" example="Monday">%1$s</xliff:g>, <xliff:g id="date1" example="December 31, 2007">%2$s</xliff:g>, <xliff:g id="time1" example="8am">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Tuesday">%4$s</xliff:g>, <xliff:g id="date2" example="January 1, 2008">%5$s</xliff:g>, <xliff:g id="time2" example="5pm">%6$s</xliff:g>"</string>
@@ -1590,42 +1550,6 @@
Example: "8:00 - 11:00 am, Mon" -->
<string name="time_wday">"<xliff:g id="time_range" example="8:00 - 11:00 am">%1$s</xliff:g>, <xliff:g id="weekday" example="Mon">%2$s</xliff:g>"</string>
- <!-- Date format string used in contexts where the user has said they
- want the month first, as used in the USA, with the month fully
- spelled out. You can remove the comma or add a period,
- or make other punctuation changes appropriate for your locale. -->
- <string name="full_date_month_first" format="date"><xliff:g id="month" example="December">MMMM</xliff:g> <xliff:g id="day" example="31">d</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string>
-
- <!-- Date format string used in contexts where the user has said they
- want the day of the month first, as used in Europe, with the month
- fully spelled out. You can remove the comma or add a period,
- or make other punctuation changes appropriate for your locale. -->
- <string name="full_date_day_first" format="date"><xliff:g id="day" example="31">d</xliff:g> <xliff:g id="month" example="December">MMMM</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string>
-
- <!-- Date format string used in contexts where the user has said they
- want the month first, as used in the USA, with the month
- abbreviated. You can remove the comma or add a period,
- or make other punctuation changes appropriate for your locale. -->
- <string name="medium_date_month_first" format="date"><xliff:g id="month" example="Dec.">MMM</xliff:g> <xliff:g id="day" example="31">d</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string>
-
- <!-- Date format string used in contexts where the user has said they
- want the day of the month first, as used in Europe, with the month
- abbreviated. You can remove the comma or add a period,
- or make other punctuation changes appropriate for your locale. -->
- <string name="medium_date_day_first" format="date"><xliff:g id="day" example="31">d</xliff:g> <xliff:g id="month" example="December">MMM</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string>
-
- <!-- Time format string used in the status bar when the user has said they
- want a 12-hour clock with AM and PM.
- You can remove the colon
- or make other punctuation changes appropriate for your locale. -->
- <string name="twelve_hour_time_format" format="date"><xliff:g id="hour" example="11">h</xliff:g>:<xliff:g id="minute" example="59">mm</xliff:g> <xliff:g id="ampm" example="AM">a</xliff:g></string>
-
- <!-- Time format string used in the status bar when the user has said they
- want a 24-hour clock.
- You can remove the colon
- or make other punctuation changes appropriate for your locale. -->
- <string name="twenty_four_hour_time_format" format="date"><xliff:g id="hour" example="23">HH</xliff:g>:<xliff:g id="minute" example="59">mm</xliff:g></string>
-
<!-- Quoted name for 12pm, lowercase -->
<string name="noon">"noon"</string>
<!-- Quoted name for 12pm, uppercase first letter -->
@@ -1635,29 +1559,6 @@
<!-- Quoted name for 12am, uppercase first letter -->
<string name="Midnight">"Midnight"</string>
- <!-- Date format for month and day of month.
- Example: "October 9". -->
- <string name="month_day">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>"</string>
-
- <!-- Date format for month alone.
- Example: "October" -->
- <string name="month">"<xliff:g id="month" example="October">%B</xliff:g>"</string>
-
- <!-- Date format for month, day, and year.
- Example: "October 9, 2007" -->
- <string name="month_day_year">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>, <xliff:g id="year" example="2007">%Y</xliff:g>"</string>
-
- <!-- Date format for month and year.
- Example: "October 2007" -->
- <string name="month_year">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="year" example="2007">%Y</xliff:g>"</string>
-
- <!-- A format string for 24-hour time of day (example "23:59"). -->
- <string name="time_of_day">"<xliff:g id="hour" example="23">%H</xliff:g>:<xliff:g id="minute" example="59">%M</xliff:g>:<xliff:g id="second" example="59">%S</xliff:g>"</string>
-
- <!-- Format string for date and 24-hour time of day.
- Example: 23:59:15 Jan 31 2008 -->
- <string name="date_and_time">"<xliff:g id="hour" example="23">%H</xliff:g>:<xliff:g id="minute" example="59">%M</xliff:g>:<xliff:g id="second" example="59">%S</xliff:g> <xliff:g id="month" example="Jan">%B</xliff:g> <xliff:g id="day" example="31">%-d</xliff:g>, <xliff:g id="year" example="2008">%Y</xliff:g>"</string>
-
<!-- Format indicating a range of dates in the same year.
Example: "Oct 31 - Nov 3" -->
<string name="same_year_md1_md2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>"</string>
@@ -1756,312 +1657,7 @@
Example: "Tue, Oct 9, 2007, 8:00am - Wed, Oct 10, 2007, 5:00pm" -->
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string>
- <!-- Format string for abbreviated month, day, and year.
- Example: "Oct 9, 2007" -->
- <string name="abbrev_month_day_year">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>, <xliff:g id="year" example="2007">%Y</xliff:g>"</string>
-
- <!-- Format string for abbreviated month and year.
- Example: "Oct 2007" -->
- <string name="abbrev_month_year">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="year" example="2007">%Y</xliff:g>"</string>
-
- <!-- Format string for abbreviated month and day.
- Example: "Oct 9" -->
- <string name="abbrev_month_day">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="day" example="31">%-d</xliff:g>"</string>
-
- <!-- Format string for abbreviated month alone.
- Example: "Oct" -->
- <string name="abbrev_month">"<xliff:g id="month" example="Oct">%b</xliff:g>"</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_sunday">Sunday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_monday">Monday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_tuesday">Tuesday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_wednesday">Wednesday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_thursday">Thursday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_friday">Friday</string>
-
- <!-- The full spelled out version of the day of the week. -->
- <string name="day_of_week_long_saturday">Saturday</string>
-
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Sun" stands for Sunday -->
- <string name="day_of_week_medium_sunday">Sun</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Mon" stands for Monday -->
- <string name="day_of_week_medium_monday">Mon</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Tue" stands for Tuesday -->
- <string name="day_of_week_medium_tuesday">Tue</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Wed" stands for Wednesday -->
- <string name="day_of_week_medium_wednesday">Wed</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Thu" stands for Thursday -->
- <string name="day_of_week_medium_thursday">Thu</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Fri" stands for Friday -->
- <string name="day_of_week_medium_friday">Fri</string>
-
- <!-- An abbreviated day of the week. Three characters typically in western languages.
- In US English: "Sat" stands for Saturday -->
- <string name="day_of_week_medium_saturday">Sat</string>
-
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Su" stands for Sunday -->
- <string name="day_of_week_short_sunday">Su</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Mo" stands for Monday -->
- <string name="day_of_week_short_monday">Mo</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Tu" stands for Tuesday -->
- <string name="day_of_week_short_tuesday">Tu</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "We" stands for Wednesday -->
- <string name="day_of_week_short_wednesday">We</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Th" stands for Thursday -->
- <string name="day_of_week_short_thursday">Th</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Fr" stands for Friday -->
- <string name="day_of_week_short_friday">Fr</string>
-
- <!-- An abbreviated day of the week. Two characters typically in western languages.
- In US English: "Sa" stands for Saturday -->
- <string name="day_of_week_short_saturday">Sa</string>
-
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "Su" stands for Sunday -->
- <string name="day_of_week_shorter_sunday">Su</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "M" stands for Monday -->
- <string name="day_of_week_shorter_monday">M</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "Tu" stands for Tuesday -->
- <string name="day_of_week_shorter_tuesday">Tu</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "W" stands for Wednesday -->
- <string name="day_of_week_shorter_wednesday">W</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "Th" stands for Thursday -->
- <string name="day_of_week_shorter_thursday">Th</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "F" stands for Friday -->
- <string name="day_of_week_shorter_friday">F</string>
-
- <!-- An abbreviated day of the week. One character if that is unique. Two if necessary.
- In US English: "Sa" stands for Saturday -->
- <string name="day_of_week_shorter_saturday">Sa</string>
-
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "S" stands for Sunday -->
- <string name="day_of_week_shortest_sunday">S</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "M" stands for Monday -->
- <string name="day_of_week_shortest_monday">M</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "T" stands for Tuesday -->
- <string name="day_of_week_shortest_tuesday">T</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "W" stands for Wednesday -->
- <string name="day_of_week_shortest_wednesday">W</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "T" stands for Thursday -->
- <string name="day_of_week_shortest_thursday">T</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "F" stands for Friday -->
- <string name="day_of_week_shortest_friday">F</string>
-
- <!-- An abbreviated day of the week. One character long if it makes sense. Does not have
- to be unique.
- In US English: "S" stands for Saturday -->
- <string name="day_of_week_shortest_saturday">S</string>
-
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_january">January</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_february">February</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_march">March</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_april">April</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_may">May</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_june">June</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_july">July</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_august">August</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_september">September</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_october">October</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_november">November</string>
-
- <!-- The full spelled out version of the month. -->
- <string name="month_long_december">December</string>
-
-
- <!-- An abbreviated month name.
- In US English: "Jan" stands for January. -->
- <string name="month_medium_january">Jan</string>
-
- <!-- An abbreviated month name.
- In US English: "Feb" stands for February. -->
- <string name="month_medium_february">Feb</string>
-
- <!-- An abbreviated month name.
- In US English: "Mar" stands for March. -->
- <string name="month_medium_march">Mar</string>
-
- <!-- An abbreviated month name.
- In US English: "Apr" stands for April. -->
- <string name="month_medium_april">Apr</string>
-
- <!-- An abbreviated month name.
- In US English: "May" stands for May. -->
- <string name="month_medium_may">May</string>
-
- <!-- An abbreviated month name.
- In US English: "Jun" stands for June. -->
- <string name="month_medium_june">Jun</string>
-
- <!-- An abbreviated month name.
- In US English: "Jul" stands for July. -->
- <string name="month_medium_july">Jul</string>
-
- <!-- An abbreviated month name.
- In US English: "Aug" stands for August. -->
- <string name="month_medium_august">Aug</string>
-
- <!-- An abbreviated month name.
- In US English: "Sep" stands for September. -->
- <string name="month_medium_september">Sep</string>
-
- <!-- An abbreviated month name.
- In US English: "Oct" stands for October. -->
- <string name="month_medium_october">Oct</string>
-
- <!-- An abbreviated month name.
- In US English: "Nov" stands for November. -->
- <string name="month_medium_november">Nov</string>
-
- <!-- An abbreviated month name.
- In US English: "Dec" stands for December. -->
- <string name="month_medium_december">Dec</string>
-
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "J" stands for January -->
- <string name="month_shortest_january">J</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "F" stands for February. -->
- <string name="month_shortest_february">F</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "M" stands for March. -->
- <string name="month_shortest_march">M</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "A" stands for April. -->
- <string name="month_shortest_april">A</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "M" stands for May. -->
- <string name="month_shortest_may">M</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "J" stands for June. -->
- <string name="month_shortest_june">J</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "J" stands for July. -->
- <string name="month_shortest_july">J</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "A" stands for August. -->
- <string name="month_shortest_august">A</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "S" stands for September. -->
- <string name="month_shortest_september">S</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "O" stands for October. -->
- <string name="month_shortest_october">O</string>
-
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "N" stands for November. -->
- <string name="month_shortest_november">N</string>
- <!-- An abbreviated month name. One character long if it makes sense. Does not have
- to be unique.
- In US English: "D" stands for December. -->
- <string name="month_shortest_december">D</string>
<!-- Format string for durations like "01:23" (1 minute, 23 seconds) -->
<string name="elapsed_time_short_format_mm_ss"><xliff:g id="minutes" example="1">%1$02d</xliff:g>:<xliff:g id="seconds" example="23">%2$02d</xliff:g></string>
@@ -2159,6 +1755,8 @@
<string name="anr_process">Process <xliff:g id="process">%1$s</xliff:g> is not responding.</string>
<!-- Button allowing the user to close an application that is not responding. This will kill the application. -->
<string name="force_close">Force close</string>
+ <!-- Button allowing the user to send a bug report for application which has encountered an error. -->
+ <string name="report">Report</string>
<!-- Button allowing the user to choose to wait for an application that is not responding to become responsive again. -->
<string name="wait">Wait</string>
<!-- Button allowing a developer to connect a debugger to an application that is not responding. -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9567523..b168fb8 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -50,6 +50,7 @@
<item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_light_nodisable</item>
<item name="textColorHint">@android:color/hint_foreground_dark</item>
<item name="textColorHintInverse">@android:color/hint_foreground_light</item>
+ <item name="textColorSearchUrl">@android:color/search_url_text</item>
<item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
<item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
diff --git a/core/res/res/xml/eri.xml b/core/res/res/xml/eri.xml
new file mode 100644
index 0000000..cd66f14
--- /dev/null
+++ b/core/res/res/xml/eri.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<!-- Note that IconMode can be only 0, ON or 1, FLASHING
+ The icon is turned OFF if then IconIndex = 1 -->
+
+<EriFile VersionNumber="1357"
+ NumberOfEriEntries="12"
+ EriFileType="1">
+
+ <CallPromptId Id="0"
+ CallPromptText="CallPromptId0"/>
+
+ <CallPromptId Id="1"
+ CallPromptText="CallPromptId1"/>
+
+ <CallPromptId Id="2"
+ CallPromptText="CallPromptId2"/>
+
+ <EriInfo RoamingIndicator="64"
+ IconIndex="1"
+ IconMode="0"
+ EriText="T-CDMA 64"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="65"
+ IconIndex="65"
+ IconMode="0"
+ EriText="T-CDMA 65"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="66"
+ IconIndex="1"
+ IconMode="0"
+ EriText="T-CDMA Ext 66"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="67"
+ IconIndex="67"
+ IconMode="0"
+ EriText="T-CDMA Ext 67"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="68"
+ IconIndex="68"
+ IconMode="0"
+ EriText="T-CDMA Roam 68"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="69"
+ IconIndex="69"
+ IconMode="1"
+ EriText="T-CDMA Ext 69"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="70"
+ IconIndex="70"
+ IconMode="1"
+ EriText="T-CDMA Roam 70"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="71"
+ IconIndex="1"
+ IconMode="0"
+ EriText="T-CDMA Ext 71"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="72"
+ IconIndex="72"
+ IconMode="0"
+ EriText="T-CDMA Ext 72"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="73"
+ IconIndex="73"
+ IconMode="0"
+ EriText="T-CDMA Roam 73"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="74"
+ IconIndex="74"
+ IconMode="1"
+ EriText="T-CDMA Ext 74"
+ CallPromptId="0"
+ AlertId="0"/>
+
+ <EriInfo RoamingIndicator="75"
+ IconIndex="75"
+ IconMode="1"
+ EriText="T-CDMA Roam 75"
+ CallPromptId="0"
+ AlertId="0"/>
+
+</EriFile>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index f80bd6b..33d6b3b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -54,7 +54,7 @@
<group gid="log" />
</permission>
- <permission name="android.permission.SDCARD_WRITE" >
+ <permission name="android.permission.WRITE_SDCARD" >
<group gid="sdcard_rw" />
</permission>
@@ -84,6 +84,24 @@
others should have a fairly open environment in which to
interact with the system. -->
+ <!-- Standard permissions granted to the shell. -->
+ <assign-permission name="android.permission.WRITE_SDCARD" uid="shell" />
+ <assign-permission name="android.permission.SEND_SMS" uid="shell" />
+ <assign-permission name="android.permission.CALL_PHONE" uid="shell" />
+ <assign-permission name="android.permission.READ_CONTACTS" uid="shell" />
+ <assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" />
+ <assign-permission name="android.permission.READ_OWNER_DATA" uid="shell" />
+ <assign-permission name="android.permission.WRITE_OWNER_DATA" uid="shell" />
+ <assign-permission name="android.permission.READ_CALENDAR" uid="shell" />
+ <assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" />
+ <assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" />
+ <assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" />
+ <assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" />
+ <assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" />
+ <assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" />
+ <assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />
+ <assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />
+ <assign-permission name="android.permission.BLUETOOTH" uid="shell" />
<!-- System tool permissions granted to the shell. -->
<assign-permission name="android.permission.GET_TASKS" uid="shell" />
<assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />
@@ -114,11 +132,14 @@
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" />
<assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" />
<assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
+ <assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
+ <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
+
<!-- This is a list of all the libraries available for application
code to link against. -->
diff --git a/docs/html/guide/tutorials/hello-world.jd b/docs/html/guide/tutorials/hello-world.jd
index 4d1e9cd..79b723d 100644
--- a/docs/html/guide/tutorials/hello-world.jd
+++ b/docs/html/guide/tutorials/hello-world.jd
@@ -29,7 +29,7 @@
<p>Before you start, you should already have the very latest SDK installed, and if you're using
Eclipse, you should have installed the ADT plugin as well. If you have not installed these, see
-<a href="{@docRoot}sdk/1.1_r1/installing.html">Installing the Android SDK</a> and return
+<a href="{@docRoot}sdk/{@sdkCurrent}/installing.html">Installing the Android SDK</a> and return
here when you've completed the installation.</p>
<h2 id="avd">Create an AVD</h2>
@@ -80,7 +80,7 @@
"Android XML File" will also be available.)</p>
</li>
- <li>Selected "Android Project" and click <strong>Next</strong>.
+ <li>Select "Android Project" and click <strong>Next</strong>.<br/>
<a href="images/hello_world_0.png"><img src="images/hello_world_0.png" style="height:230px" alt="" /></a>
</li>
@@ -147,7 +147,7 @@
built against the 1.1 platform library will run normally on the 1.5 platform. The reverse
is not true.</p>
</li>
-</ul>
+</ol>
<p>Your Android project is now ready. It should be visible in the Package
Explorer on the left.
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 0304309..99ab2f0 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -20,7 +20,7 @@
#define _RUNTIME_ANDROID_RUNTIME_H
#include <utils/Errors.h>
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/Vector.h>
diff --git a/include/utils/Binder.h b/include/binder/Binder.h
similarity index 98%
rename from include/utils/Binder.h
rename to include/binder/Binder.h
index b5b8d98..c9b71fd 100644
--- a/include/utils/Binder.h
+++ b/include/binder/Binder.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_BINDER_H
#define ANDROID_BINDER_H
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
// ---------------------------------------------------------------------------
namespace android {
diff --git a/include/utils/BpBinder.h b/include/binder/BpBinder.h
similarity index 98%
rename from include/utils/BpBinder.h
rename to include/binder/BpBinder.h
index 7b96e29..067637e 100644
--- a/include/utils/BpBinder.h
+++ b/include/binder/BpBinder.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_BPBINDER_H
#define ANDROID_BPBINDER_H
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
diff --git a/include/utils/IBinder.h b/include/binder/IBinder.h
similarity index 100%
rename from include/utils/IBinder.h
rename to include/binder/IBinder.h
diff --git a/include/utils/IInterface.h b/include/binder/IInterface.h
similarity index 99%
rename from include/utils/IInterface.h
rename to include/binder/IInterface.h
index 959722a..3b1e33b 100644
--- a/include/utils/IInterface.h
+++ b/include/binder/IInterface.h
@@ -18,7 +18,7 @@
#ifndef ANDROID_IINTERFACE_H
#define ANDROID_IINTERFACE_H
-#include <utils/Binder.h>
+#include <binder/Binder.h>
namespace android {
diff --git a/include/utils/IMemory.h b/include/binder/IMemory.h
similarity index 98%
rename from include/utils/IMemory.h
rename to include/binder/IMemory.h
index 35a3fd7..182792c 100644
--- a/include/utils/IMemory.h
+++ b/include/binder/IMemory.h
@@ -23,7 +23,7 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
namespace android {
diff --git a/include/utils/IPCThreadState.h b/include/binder/IPCThreadState.h
similarity index 98%
rename from include/utils/IPCThreadState.h
rename to include/binder/IPCThreadState.h
index 0490fd3..78306b2b 100644
--- a/include/utils/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -18,8 +18,8 @@
#define ANDROID_IPC_THREAD_STATE_H
#include <utils/Errors.h>
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
#include <utils/Vector.h>
#ifdef HAVE_WIN32_PROC
diff --git a/include/utils/IPermissionController.h b/include/binder/IPermissionController.h
similarity index 97%
rename from include/utils/IPermissionController.h
rename to include/binder/IPermissionController.h
index cb1dd34..f9d371b 100644
--- a/include/utils/IPermissionController.h
+++ b/include/binder/IPermissionController.h
@@ -18,7 +18,7 @@
#ifndef ANDROID_IPERMISSION_CONTROLLER_H
#define ANDROID_IPERMISSION_CONTROLLER_H
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
namespace android {
diff --git a/include/utils/IServiceManager.h b/include/binder/IServiceManager.h
similarity index 97%
rename from include/utils/IServiceManager.h
rename to include/binder/IServiceManager.h
index e3d99fe..ea149dd 100644
--- a/include/utils/IServiceManager.h
+++ b/include/binder/IServiceManager.h
@@ -18,8 +18,8 @@
#ifndef ANDROID_ISERVICE_MANAGER_H
#define ANDROID_ISERVICE_MANAGER_H
-#include <utils/IInterface.h>
-#include <utils/IPermissionController.h>
+#include <binder/IInterface.h>
+#include <binder/IPermissionController.h>
#include <utils/Vector.h>
#include <utils/String16.h>
diff --git a/include/utils/MemoryBase.h b/include/binder/MemoryBase.h
similarity index 97%
rename from include/utils/MemoryBase.h
rename to include/binder/MemoryBase.h
index eb5a9d2..463e26d 100644
--- a/include/utils/MemoryBase.h
+++ b/include/binder/MemoryBase.h
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdint.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/utils/MemoryDealer.h b/include/binder/MemoryDealer.h
similarity index 98%
rename from include/utils/MemoryDealer.h
rename to include/binder/MemoryDealer.h
index 79d7883..2080ea6 100644
--- a/include/utils/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -21,9 +21,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <utils/threads.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
namespace android {
// ----------------------------------------------------------------------------
diff --git a/include/utils/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
similarity index 98%
rename from include/utils/MemoryHeapBase.h
rename to include/binder/MemoryHeapBase.h
index 574acf4..83c7283 100644
--- a/include/utils/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdint.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/utils/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
similarity index 95%
rename from include/utils/MemoryHeapPmem.h
rename to include/binder/MemoryHeapPmem.h
index 60335ad..dbf26ff 100644
--- a/include/utils/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -20,9 +20,9 @@
#include <stdlib.h>
#include <stdint.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/IMemory.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/IMemory.h>
#include <utils/SortedVector.h>
namespace android {
diff --git a/include/utils/Parcel.h b/include/binder/Parcel.h
similarity index 100%
rename from include/utils/Parcel.h
rename to include/binder/Parcel.h
diff --git a/include/utils/ProcessState.h b/include/binder/ProcessState.h
similarity index 98%
rename from include/utils/ProcessState.h
rename to include/binder/ProcessState.h
index 39584f4..feeb3c3 100644
--- a/include/utils/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_PROCESS_STATE_H
#define ANDROID_PROCESS_STATE_H
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/String16.h>
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 6aa40d00..e962db6e 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -26,8 +26,8 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
#include <utils/threads.h>
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index ba0467c..0955819 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -26,8 +26,8 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
#include <utils/threads.h>
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 6f13fe0..031335e 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -23,7 +23,7 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <media/IAudioTrack.h>
#include <media/IAudioRecord.h>
#include <media/IAudioFlingerClient.h>
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
index c3deb0b..383ec0c 100644
--- a/include/media/IAudioFlingerClient.h
+++ b/include/media/IAudioFlingerClient.h
@@ -19,7 +19,7 @@
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
namespace android {
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
index 9d45d2d9..46735de 100644
--- a/include/media/IAudioRecord.h
+++ b/include/media/IAudioRecord.h
@@ -22,8 +22,8 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index 12f2111..de6426a 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -22,8 +22,8 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
index c677e83..9baba8e 100644
--- a/include/media/IMediaMetadataRetriever.h
+++ b/include/media/IMediaMetadataRetriever.h
@@ -19,9 +19,9 @@
#define ANDROID_IMEDIAMETADATARETRIEVER_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index a683e74..2c4bc2a 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -18,8 +18,8 @@
#define ANDROID_IMEDIAPLAYER_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
namespace android {
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
index 5d32811..eee6c97 100644
--- a/include/media/IMediaPlayerClient.h
+++ b/include/media/IMediaPlayerClient.h
@@ -18,8 +18,8 @@
#define ANDROID_IMEDIAPLAYERCLIENT_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
namespace android {
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 8125cc9..469098cc 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -18,8 +18,8 @@
#define ANDROID_IMEDIAPLAYERSERVICE_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
#include <media/IMediaPlayerClient.h>
#include <media/IMediaPlayer.h>
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 64d3a40..24ac82b 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -18,7 +18,7 @@
#ifndef ANDROID_IMEDIARECORDER_H
#define ANDROID_IMEDIARECORDER_H
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
namespace android {
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index f2719d3..3db8a0f 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -20,7 +20,7 @@
#include <utils/Errors.h> // for status_t
#include <utils/threads.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <media/IMediaMetadataRetriever.h>
namespace android {
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 255a67b..704a8cb 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_MEDIAPLAYER_H
#define ANDROID_MEDIAPLAYER_H
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <ui/Surface.h>
#include <media/IMediaPlayerClient.h>
#include <media/IMediaPlayer.h>
diff --git a/include/private/binder/Static.h b/include/private/binder/Static.h
new file mode 100644
index 0000000..5b0f9fc
--- /dev/null
+++ b/include/private/binder/Static.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+#include <utils/threads.h>
+
+#include <binder/IBinder.h>
+#include <binder/IMemory.h>
+#include <binder/ProcessState.h>
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+// For ProcessState.cpp
+extern Mutex gProcessMutex;
+extern sp<ProcessState> gProcess;
+
+// For ServiceManager.cpp
+extern Mutex gDefaultServiceManagerLock;
+extern sp<IServiceManager> gDefaultServiceManager;
+extern sp<IPermissionController> gPermissionController;
+
+} // namespace android
diff --git a/include/private/utils/binder_module.h b/include/private/binder/binder_module.h
similarity index 100%
rename from include/private/utils/binder_module.h
rename to include/private/binder/binder_module.h
diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h
index f1439b7..d95ae0d 100644
--- a/include/private/utils/Static.h
+++ b/include/private/utils/Static.h
@@ -20,14 +20,6 @@
#include <utils/threads.h>
#include <utils/KeyedVector.h>
-#ifndef LIBUTILS_NATIVE
-#include <utils/IBinder.h>
-#include <utils/IMemory.h>
-#include <utils/ProcessState.h>
-#include <utils/IPermissionController.h>
-#include <utils/IServiceManager.h>
-#endif
-
namespace android {
// For TextStream.cpp
extern Vector<int32_t> gTextBuffers;
@@ -40,19 +32,4 @@
extern void initialize_string16();
extern void terminate_string16();
-
-
-#ifndef LIBUTILS_NATIVE
-
-// For ProcessState.cpp
-extern Mutex gProcessMutex;
-extern sp<ProcessState> gProcess;
-
-// For ServiceManager.cpp
-extern Mutex gDefaultServiceManagerLock;
-extern sp<IServiceManager> gDefaultServiceManager;
-extern sp<IPermissionController> gPermissionController;
-
-#endif
-
} // namespace android
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
new file mode 100644
index 0000000..06f3820
--- /dev/null
+++ b/include/tts/TtsEngine.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+#include <media/AudioSystem.h>
+
+// This header defines the interface used by the Android platform
+// to access Text-To-Speech functionality in shared libraries that implement speech
+// synthesis and the management of resources associated with the synthesis.
+// An example of the implementation of this interface can be found in
+// FIXME: add path+name to implementation of default TTS engine
+// Libraries implementing this interface are used in:
+// frameworks/base/tts/jni/android_tts_SpeechSynthesis.cpp
+
+namespace android {
+
+// The callback is used by the implementation of this interface to notify its
+// client, the Android TTS service, that the last requested synthesis has been
+// completed.
+// The callback for synthesis completed takes:
+// void * - The userdata pointer set in the original synth call
+// uint32_t - Track sampling rate in Hz
+// audio_format - The AudioSystem::audio_format enum
+// int - The number of channels
+// int8_t * - A buffer of audio data only valid during the execution of the callback
+// size_t - The size of the buffer
+// Note about memory management:
+// The implementation of TtsEngine is responsible for the management of the memory
+// it allocates to store the synthesized speech. After the execution of the callback
+// to hand the synthesized data to the client of TtsEngine, the TTS engine is
+// free to reuse or free the previously allocated memory.
+// This implies that the implementation of the "synthDoneCB" callback cannot use
+// the pointer to the buffer of audio samples outside of the callback itself.
+typedef void (synthDoneCB_t)(void *, uint32_t, AudioSystem::audio_format, int, int8_t *, size_t);
+
+class TtsEngine;
+extern "C" TtsEngine* getTtsEngine();
+
+enum tts_result {
+ TTS_SUCCESS = 0,
+ TTS_FAILURE = -1,
+ TTS_FEATURE_UNSUPPORTED = -2,
+ TTS_VALUE_INVALID = -3,
+ TTS_PROPERTY_UNSUPPORTED = -4,
+ TTS_PROPERTY_SIZE_TOO_SMALL = -5
+};
+
+class TtsEngine
+{
+public:
+ // Initialize the TTS engine and returns whether initialization succeeded.
+ // @param synthDoneCBPtr synthesis callback function pointer
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ virtual tts_result init(synthDoneCB_t synthDoneCBPtr);
+
+ // Shut down the TTS engine and releases all associated resources.
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ virtual tts_result shutdown();
+
+ // Interrupt synthesis and flushes any synthesized data that hasn't been output yet.
+ // This will block until callbacks underway are completed.
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ virtual tts_result stop();
+
+ // Load the resources associated with the specified language. The loaded language will
+ // only be used once a call to setLanguage() with the same language value is issued.
+ // Language values are based on the Android conventions for localization as described in
+ // the Android platform documentation on internationalization. This implies that language
+ // data is specified in the format xx-rYY, where xx is a two letter ISO 639-1 language code
+ // in lowercase and rYY is a two letter ISO 3166-1-alpha-2 language code in uppercase
+ // preceded by a lowercase "r".
+ // @param value pointer to the language value
+ // @param size length of the language value
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ virtual tts_result loadLanguage(const char *value, const size_t size);
+
+ // Signal the engine to use the specified language. This will force the language to be
+ // loaded if it wasn't loaded previously with loadLanguage().
+ // See loadLanguage for the specification of the language.
+ // @param value pointer to the language value
+ // @param size length of the language value
+ // @return TTS_SUCCESS, or TTS_FAILURE
+ virtual tts_result setLanguage(const char *value, const size_t size);
+
+ // Retrieve the currently set language, or an empty "value" if no language has
+ // been set.
+ // @param[out] value pointer to the retrieved language value
+ // @param[inout] iosize in: stores the size available to store the language value in *value
+ // out: stores the size required to hold the language value if
+ // getLanguage() returned TTS_PROPERTY_SIZE_TOO_SMALL,
+ // unchanged otherwise.
+ // @return TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL, or TTS_FAILURE
+ virtual tts_result getLanguage(char *value, size_t *iosize);
+
+ // Set a property for the the TTS engine
+ // "size" is the maximum size of "value" for properties "property"
+ // @param property pointer to the property name
+ // @param value pointer to the property value
+ // @param size maximum size required to store this type of property
+ // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE,
+ // or TTS_VALUE_INVALID
+ virtual tts_result setProperty(const char *property, const char *value, const size_t size);
+
+ // Retrieve a property from the TTS engine
+ // @param property pointer to the property name
+ // @param[out] value pointer to the retrieved language value
+ // @param[inout] iosize in: stores the size available to store the property value
+ // out: stores the size required to hold the language value if
+ // getLanguage() returned TTS_PROPERTY_SIZE_TOO_SMALL,
+ // unchanged otherwise.
+ // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL
+ virtual tts_result getProperty(const char *property, char *value, size_t *iosize);
+
+ // Synthesize the text.
+ // When synthesis completes, the engine invokes the callback to notify the TTS framework.
+ // Note about the format of the input: the text parameter may use the following elements
+ // and their respective attributes as defined in the SSML 1.0 specification:
+ // * lang
+ // * say-as:
+ // o interpret-as
+ // * phoneme
+ // * voice:
+ // o gender,
+ // o age,
+ // o variant,
+ // o name
+ // * emphasis
+ // * break:
+ // o strength,
+ // o time
+ // * prosody:
+ // o pitch,
+ // o contour,
+ // o range,
+ // o rate,
+ // o duration,
+ // o volume
+ // * mark
+ // Differences between this text format and SSML are:
+ // * full SSML documents are not supported
+ // * namespaces are not supported
+ // Text is coded in UTF-8.
+ // @param text the UTF-8 text to synthesize
+ // @param userdata pointer to be returned when the call is invoked
+ // @return TTS_SUCCESS or TTS_FAILURE
+ virtual tts_result synthesizeText(const char *text, void *userdata);
+
+ // Synthesize IPA text. When synthesis completes, the engine must call the given callback to notify the TTS API.
+ // @param ipa the IPA data to synthesize
+ // @param userdata pointer to be returned when the call is invoked
+ // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported, otherwise TTS_SUCCESS or TTS_FAILURE
+ virtual tts_result synthesizeIpa(const char *ipa, void *userdata);
+};
+
+} // namespace android
+
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index 73036f0..2cdcc06 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <utils/RefBase.h>
#include <ui/CameraParameters.h>
#include <ui/Overlay.h>
diff --git a/include/ui/ICamera.h b/include/ui/ICamera.h
index 241fb63..1df7914 100644
--- a/include/ui/ICamera.h
+++ b/include/ui/ICamera.h
@@ -18,10 +18,10 @@
#define ANDROID_HARDWARE_ICAMERA_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
#include <ui/ISurface.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <utils/String8.h>
#include <ui/Camera.h>
diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h
index c4bdd07..f38a6aa 100644
--- a/include/ui/ICameraClient.h
+++ b/include/ui/ICameraClient.h
@@ -18,9 +18,9 @@
#define ANDROID_HARDWARE_ICAMERA_APP_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
namespace android {
diff --git a/include/ui/ICameraService.h b/include/ui/ICameraService.h
index c652c51..061681a 100644
--- a/include/ui/ICameraService.h
+++ b/include/ui/ICameraService.h
@@ -18,8 +18,8 @@
#define ANDROID_HARDWARE_ICAMERASERVICE_H
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
#include <ui/ICameraClient.h>
#include <ui/ICamera.h>
diff --git a/include/ui/IOverlay.h b/include/ui/IOverlay.h
index 699b1b0..af3add1 100644
--- a/include/ui/IOverlay.h
+++ b/include/ui/IOverlay.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <utils/RefBase.h>
#include <ui/PixelFormat.h>
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index e47b753..adba45a 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <utils/RefBase.h>
#include <ui/PixelFormat.h>
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index fd5a473..ab6dd56 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -22,7 +22,7 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <ui/PixelFormat.h>
#include <ui/ISurfaceFlingerClient.h>
diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h
index 8515e2e..e93a4faf 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/ui/ISurfaceFlingerClient.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <utils/RefBase.h>
#include <ui/ISurface.h>
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index 66514b4..9ba2f7b 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 849369d..e36dcb4 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <utils/Vector.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <ui/Rect.h>
diff --git a/include/utils/AssetManager.h b/include/utils/AssetManager.h
index e94c0e8..c11429e 100644
--- a/include/utils/AssetManager.h
+++ b/include/utils/AssetManager.h
@@ -153,6 +153,18 @@
AssetDir* openDir(const char* dirName);
/*
+ * Open a directory within a particular path of the asset manager.
+ *
+ * The contents of the directory are an amalgam of vendor-specific,
+ * locale-specific, and generic assets stored loosely or in asset
+ * packages. Depending on the cache setting and previous accesses,
+ * this call may incur significant disk overhead.
+ *
+ * To open the top-level directory, pass in "".
+ */
+ AssetDir* openNonAssetDir(void* cookie, const char* dirName);
+
+ /*
* Get the type of a file in the asset hierarchy. They will either
* be "regular" or "directory". [Currently only works for "regular".]
*
diff --git a/include/utils/backup_helpers.h b/include/utils/backup_helpers.h
index 73b9989..24b6c9e 100644
--- a/include/utils/backup_helpers.h
+++ b/include/utils/backup_helpers.h
@@ -22,11 +22,34 @@
namespace android {
-int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
- char const* fileBase, char const* const* files, int fileCount);
+enum {
+ BACKUP_HEADER_APP_V1 = 0x31707041, // App1 (little endian)
+ BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian)
+ BACKUP_FOOTER_APP_V1 = 0x746f6f46, // Foot (little endian)
+};
+
+// the sizes of all of these match.
+typedef struct {
+ int type; // == BACKUP_HEADER_APP_V1
+ int packageLen; // length of the name of the package that follows, not including the null.
+ int cookie;
+} app_header_v1;
+
+typedef struct {
+ int type; // BACKUP_HEADER_ENTITY_V1
+ int keyLen; // length of the key name, not including the null terminator
+ int dataSize; // size of the data, not including the padding, -1 means delete
+} entity_header_v1;
+
+typedef struct {
+ int type; // BACKUP_FOOTER_APP_V1
+ int entityCount; // the number of entities that were written
+ int cookie;
+} app_footer_v1;
+
/**
- * Reads the data.
+ * Writes the data.
*
* If an error occurs, it poisons this object and all write calls will fail
* with the error that occurred.
@@ -38,12 +61,12 @@
// does not close fd
~BackupDataWriter();
- status_t WriteAppHeader(const String8& packageName);
+ status_t WriteAppHeader(const String8& packageName, int cookie);
status_t WriteEntityHeader(const String8& key, size_t dataSize);
status_t WriteEntityData(const void* data, size_t size);
- status_t WriteAppFooter();
+ status_t WriteAppFooter(int cookie);
private:
explicit BackupDataWriter();
@@ -55,13 +78,57 @@
int m_entityCount;
};
-#define TEST_BACKUP_HELPERS 0
+/**
+ * Reads the data.
+ *
+ * If an error occurs, it poisons this object and all write calls will fail
+ * with the error that occurred.
+ */
+class BackupDataReader
+{
+public:
+ BackupDataReader(int fd);
+ // does not close fd
+ ~BackupDataReader();
+
+ status_t Status();
+ status_t ReadNextHeader(int* type = NULL);
+
+ status_t ReadAppHeader(String8* packageName, int* cookie);
+ bool HasEntities();
+ status_t ReadEntityHeader(String8* key, size_t* dataSize);
+ status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
+ status_t ReadEntityData(void* data, size_t size);
+ status_t ReadAppFooter(int* cookie);
+
+private:
+ explicit BackupDataReader();
+ status_t skip_padding();
+
+ int m_fd;
+ status_t m_status;
+ ssize_t m_pos;
+ int m_entityCount;
+ union {
+ int type;
+ app_header_v1 app;
+ entity_header_v1 entity;
+ app_footer_v1 footer;
+ } m_header;
+};
+
+int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
+ char const* fileBase, char const* const* files, int fileCount);
+
+
+#define TEST_BACKUP_HELPERS 1
#if TEST_BACKUP_HELPERS
int backup_helper_test_empty();
int backup_helper_test_four();
int backup_helper_test_files();
int backup_helper_test_data_writer();
+int backup_helper_test_data_reader();
#endif
} // namespace android
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index b6d5078c..16a4f2d 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -71,8 +71,8 @@
}
AudioStreamIn* A2dpAudioInterface::openInputStream(
- int format, int channelCount, uint32_t sampleRate, status_t *status,
- AudioSystem::audio_in_acoustics acoustics)
+ int inputSource, int format, int channelCount, uint32_t sampleRate,
+ status_t *status, AudioSystem::audio_in_acoustics acoustics)
{
if (status)
*status = -1;
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 7901a8c..091e775 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -55,6 +55,7 @@
status_t *status=0);
virtual AudioStreamIn* openInputStream(
+ int inputSource,
int format,
int channelCount,
uint32_t sampleRate,
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index 50d516b..874f2c4 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -11,6 +11,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ libbinder \
libmedia \
libhardware_legacy
@@ -34,6 +35,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ libbinder \
libmedia \
libhardware_legacy
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index 9a94102..b72c94e 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -78,9 +78,9 @@
virtual status_t setParameter(const char* key, const char* value)
{return mFinalInterface->setParameter(key, value);}
- virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status,
- AudioSystem::audio_in_acoustics acoustics)
- {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status, acoustics);}
+ virtual AudioStreamIn* openInputStream(int inputSource, int format, int channelCount,
+ uint32_t sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
+ { return mFinalInterface->openInputStream(inputSource, format, channelCount, sampleRate, status, acoustics); }
virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index a4050b3..4b4fa5e 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -24,10 +24,10 @@
#include <sys/time.h>
#include <sys/resource.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
#include <utils/String16.h>
#include <utils/threads.h>
@@ -2414,7 +2414,9 @@
LOGV("AudioRecordThread: loop starting");
if (mRecordTrack != 0) {
- input = mAudioHardware->openInputStream(mRecordTrack->format(),
+ input = mAudioHardware->openInputStream(
+ mRecordTrack->type(),
+ mRecordTrack->format(),
mRecordTrack->channelCount(),
mRecordTrack->sampleRate(),
&mStartStatus,
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index c7ca9ec..f3e6dc1 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -30,7 +30,7 @@
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/threads.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
#include <utils/Vector.h>
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index 62beada..a97c0bc 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -30,6 +30,7 @@
#include <utils/String8.h>
#include "AudioHardwareGeneric.h"
+#include <media/AudioRecord.h>
namespace android {
@@ -93,9 +94,15 @@
}
AudioStreamIn* AudioHardwareGeneric::openInputStream(
- int format, int channelCount, uint32_t sampleRate, status_t *status,
- AudioSystem::audio_in_acoustics acoustics)
+ int inputSource, int format, int channelCount, uint32_t sampleRate,
+ status_t *status, AudioSystem::audio_in_acoustics acoustics)
{
+ // check for valid input source
+ if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
+ (inputSource != AudioRecord::MIC_INPUT)) {
+ return 0;
+ }
+
AutoMutex lock(mLock);
// only one input stream allowed
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index c949aa1..c89df87 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -112,6 +112,7 @@
status_t *status=0);
virtual AudioStreamIn* openInputStream(
+ int inputSource,
int format,
int channelCount,
uint32_t sampleRate,
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index b13cb1c..c61e6e6 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -23,6 +23,7 @@
#include <utils/String8.h>
#include "AudioHardwareStub.h"
+#include <media/AudioRecord.h>
namespace android {
@@ -56,9 +57,15 @@
}
AudioStreamIn* AudioHardwareStub::openInputStream(
- int format, int channelCount, uint32_t sampleRate,
+ int inputSource, int format, int channelCount, uint32_t sampleRate,
status_t *status, AudioSystem::audio_in_acoustics acoustics)
{
+ // check for valid input source
+ if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
+ (inputSource != AudioRecord::MIC_INPUT)) {
+ return 0;
+ }
+
AudioStreamInStub* in = new AudioStreamInStub();
status_t lStatus = in->set(format, channelCount, sampleRate, acoustics);
if (status) {
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index d406424..bf63cc5 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -78,6 +78,7 @@
status_t *status=0);
virtual AudioStreamIn* openInputStream(
+ int inputSource,
int format,
int channelCount,
uint32_t sampleRate,
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
new file mode 100644
index 0000000..c4d695e
--- /dev/null
+++ b/libs/binder/Android.mk
@@ -0,0 +1,44 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# we have the common sources, plus some device-specific stuff
+LOCAL_SRC_FILES:= \
+ Binder.cpp \
+ BpBinder.cpp \
+ IInterface.cpp \
+ IMemory.cpp \
+ IPCThreadState.cpp \
+ IPermissionController.cpp \
+ IServiceManager.cpp \
+ MemoryDealer.cpp \
+ MemoryBase.cpp \
+ MemoryHeapBase.cpp \
+ MemoryHeapPmem.cpp \
+ Parcel.cpp \
+ ProcessState.cpp \
+ Static.cpp
+
+LOCAL_LDLIBS += -lpthread
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libutils
+
+LOCAL_MODULE:= libbinder
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/utils/Binder.cpp b/libs/binder/Binder.cpp
similarity index 97%
rename from libs/utils/Binder.cpp
rename to libs/binder/Binder.cpp
index 37e4685..26f29f8 100644
--- a/libs/utils/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include <utils/Binder.h>
+#include <binder/Binder.h>
#include <utils/Atomic.h>
-#include <utils/BpBinder.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/BpBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
#include <stdio.h>
diff --git a/libs/utils/BpBinder.cpp b/libs/binder/BpBinder.cpp
similarity index 98%
rename from libs/utils/BpBinder.cpp
rename to libs/binder/BpBinder.cpp
index 69ab195..56bf413 100644
--- a/libs/utils/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -17,9 +17,9 @@
#define LOG_TAG "BpBinder"
//#define LOG_NDEBUG 0
-#include <utils/BpBinder.h>
+#include <binder/BpBinder.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <stdio.h>
diff --git a/libs/utils/IInterface.cpp b/libs/binder/IInterface.cpp
similarity index 96%
rename from libs/utils/IInterface.cpp
rename to libs/binder/IInterface.cpp
index 6ea817887..9f1192f 100644
--- a/libs/utils/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
namespace android {
diff --git a/libs/utils/IMemory.cpp b/libs/binder/IMemory.cpp
similarity index 99%
rename from libs/utils/IMemory.cpp
rename to libs/binder/IMemory.cpp
index 429bc2b..13d67c0 100644
--- a/libs/utils/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -25,11 +25,11 @@
#include <sys/types.h>
#include <sys/mman.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/CallStack.h>
#define VERBOSE 0
diff --git a/libs/utils/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
similarity index 99%
rename from libs/utils/IPCThreadState.cpp
rename to libs/binder/IPCThreadState.cpp
index 04ae142..c3889e9 100644
--- a/libs/utils/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
-#include <utils/Binder.h>
-#include <utils/BpBinder.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <utils/TextOutput.h>
#include <utils/threads.h>
-#include <private/utils/binder_module.h>
-#include <private/utils/Static.h>
+#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
#include <sys/ioctl.h>
#include <signal.h>
diff --git a/libs/utils/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
similarity index 95%
rename from libs/utils/IPermissionController.cpp
rename to libs/binder/IPermissionController.cpp
index f01d38f..a61debf 100644
--- a/libs/utils/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -16,14 +16,14 @@
#define LOG_TAG "PermissionController"
-#include <utils/IPermissionController.h>
+#include <binder/IPermissionController.h>
#include <utils/Debug.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
-#include <private/utils/Static.h>
+#include <private/binder/Static.h>
namespace android {
diff --git a/libs/utils/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
similarity index 97%
rename from libs/utils/IServiceManager.cpp
rename to libs/binder/IServiceManager.cpp
index 9beeadd..2f265b8 100644
--- a/libs/utils/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -16,16 +16,16 @@
#define LOG_TAG "ServiceManager"
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/Debug.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
-#include <private/utils/Static.h>
+#include <private/binder/Static.h>
#include <unistd.h>
diff --git a/libs/utils/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
similarity index 97%
rename from libs/utils/MemoryBase.cpp
rename to libs/binder/MemoryBase.cpp
index f25e11c..033066b 100644
--- a/libs/utils/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -18,7 +18,7 @@
#include <stdlib.h>
#include <stdint.h>
-#include <utils/MemoryBase.h>
+#include <binder/MemoryBase.h>
namespace android {
diff --git a/libs/utils/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
similarity index 98%
rename from libs/utils/MemoryDealer.cpp
rename to libs/binder/MemoryDealer.cpp
index cf8201b..fd6ab7a 100644
--- a/libs/utils/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "MemoryDealer"
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <utils/Log.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
-#include <utils/MemoryBase.h>
+#include <binder/MemoryBase.h>
#include <stdint.h>
#include <stdio.h>
diff --git a/libs/utils/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
similarity index 98%
rename from libs/utils/MemoryHeapBase.cpp
rename to libs/binder/MemoryHeapBase.cpp
index 8251728..ac38f51 100644
--- a/libs/utils/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -29,7 +29,7 @@
#include <cutils/ashmem.h>
#include <cutils/atomic.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
#if HAVE_ANDROID_OS
#include <linux/android_pmem.h>
diff --git a/libs/utils/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
similarity index 98%
rename from libs/utils/MemoryHeapPmem.cpp
rename to libs/binder/MemoryHeapPmem.cpp
index eba2b30..599c9ae 100644
--- a/libs/utils/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -27,8 +27,8 @@
#include <cutils/log.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapPmem.h>
+#include <binder/MemoryHeapBase.h>
#if HAVE_ANDROID_OS
#include <linux/android_pmem.h>
diff --git a/libs/utils/Parcel.cpp b/libs/binder/Parcel.cpp
similarity index 99%
rename from libs/utils/Parcel.cpp
rename to libs/binder/Parcel.cpp
index e74ad4a..0819c29 100644
--- a/libs/utils/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -17,19 +17,19 @@
#define LOG_TAG "Parcel"
//#define LOG_NDEBUG 0
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
-#include <utils/Binder.h>
-#include <utils/BpBinder.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
#include <utils/Debug.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/TextOutput.h>
#include <utils/misc.h>
-#include <private/utils/binder_module.h>
+#include <private/binder/binder_module.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/libs/utils/ProcessState.cpp b/libs/binder/ProcessState.cpp
similarity index 97%
rename from libs/utils/ProcessState.cpp
rename to libs/binder/ProcessState.cpp
index 4567df6..d7daf73 100644
--- a/libs/utils/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -18,19 +18,19 @@
#include <cutils/process_name.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
#include <utils/Atomic.h>
-#include <utils/BpBinder.h>
-#include <utils/IPCThreadState.h>
+#include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <utils/String8.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/String8.h>
#include <utils/threads.h>
-#include <private/utils/binder_module.h>
-#include <private/utils/Static.h>
+#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
#include <errno.h>
#include <fcntl.h>
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
new file mode 100644
index 0000000..12b0308
--- /dev/null
+++ b/libs/binder/Static.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+#include <private/binder/Static.h>
+
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// ------------ ProcessState.cpp
+
+Mutex gProcessMutex;
+sp<ProcessState> gProcess;
+
+class LibUtilsIPCtStatics
+{
+public:
+ LibUtilsIPCtStatics()
+ {
+ }
+
+ ~LibUtilsIPCtStatics()
+ {
+ IPCThreadState::shutdown();
+ }
+};
+
+static LibUtilsIPCtStatics gIPCStatics;
+
+// ------------ ServiceManager.cpp
+
+Mutex gDefaultServiceManagerLock;
+sp<IServiceManager> gDefaultServiceManager;
+sp<IPermissionController> gPermissionController;
+
+} // namespace android
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 639a82e..16936e3 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -5,7 +5,6 @@
clz.cpp.arm \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
- BootAnimation.cpp \
BlurFilter.cpp.arm \
BufferAllocator.cpp \
Layer.cpp \
@@ -32,6 +31,7 @@
LOCAL_SHARED_LIBRARIES := \
libhardware \
libutils \
+ libbinder \
libcutils \
libui \
libcorecg \
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
index 7168bf2..2de628b 100644
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -30,12 +30,12 @@
#include <cutils/log.h>
#include <cutils/properties.h>
-#include <utils/IBinder.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IBinder.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapPmem.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/IPCThreadState.h>
#include <utils/StopWatch.h>
#include <ui/ISurfaceComposer.h>
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 7625931..5b260c4f 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -24,7 +24,6 @@
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/StopWatch.h>
-#include <utils/IMemory.h>
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 4547a83..c678711 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -20,8 +20,8 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 765d90b..a368ca9 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -20,9 +20,9 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/IMemory.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
+#include <binder/IMemory.h>
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 5284409..22af43e 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <private/ui/LayerState.h>
#include "LayerBase.h"
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
index 52d4db8..a027e2b 100644
--- a/libs/surfaceflinger/MessageQueue.cpp
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -21,7 +21,7 @@
#include <utils/threads.h>
#include <utils/Timers.h>
#include <utils/Log.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
#include "MessageQueue.h"
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index e0728eb..70f34a1 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -29,10 +29,10 @@
#include <cutils/log.h>
#include <cutils/properties.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>
@@ -54,6 +54,13 @@
#include "DisplayHardware/DisplayHardware.h"
+/* ideally AID_GRAPHICS would be in a semi-public header
+ * or there would be a way to map a user/group name to its id
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
#define DISPLAY_COUNT 1
namespace android {
@@ -176,7 +183,6 @@
mFreezeDisplayTime(0),
mDebugRegion(0),
mDebugBackground(0),
- mDebugNoBootAnimation(0),
mConsoleSignals(0),
mSecureFrameBuffer(0)
{
@@ -193,12 +199,9 @@
mDebugRegion = atoi(value);
property_get("debug.sf.showbackground", value, "0");
mDebugBackground = atoi(value);
- property_get("debug.sf.nobootanimation", value, "0");
- mDebugNoBootAnimation = atoi(value);
LOGI_IF(mDebugRegion, "showupdates enabled");
LOGI_IF(mDebugBackground, "showbackground enabled");
- LOGI_IF(mDebugNoBootAnimation, "boot animation disabled");
}
SurfaceFlinger::~SurfaceFlinger()
@@ -284,11 +287,8 @@
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
- LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
- if (mBootAnimation != 0) {
- mBootAnimation->requestExit();
- mBootAnimation.clear();
- }
+ LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
+ property_set("ctl.stop", "bootanim");
}
void SurfaceFlinger::onFirstRef()
@@ -396,10 +396,9 @@
* We're now ready to accept clients...
*/
- // the boot animation!
- if (mDebugNoBootAnimation == false)
- mBootAnimation = new BootAnimation(this);
-
+ // start boot animation
+ property_set("ctl.start", "bootanim");
+
return NO_ERROR;
}
@@ -1510,13 +1509,13 @@
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
const int self_pid = getpid();
- if (UNLIKELY(pid != self_pid)) {
+ if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
// we're called from a different process, do the real check
if (!checkCallingPermission(
String16("android.permission.ACCESS_SURFACE_FLINGER")))
{
- const int uid = ipc->getCallingUid();
LOGE("Permission Denial: "
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index d5e5252..6bbb21f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -25,7 +25,7 @@
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <utils/RefBase.h>
#include <ui/PixelFormat.h>
@@ -36,7 +36,6 @@
#include <private/ui/LayerState.h>
#include "Barrier.h"
-#include "BootAnimation.h"
#include "Layer.h"
#include "Tokenizer.h"
@@ -318,7 +317,6 @@
sp<IMemory> mServerCblkMemory;
surface_flinger_cblk_t* mServerCblk;
GLuint mWormholeTexName;
- sp<BootAnimation> mBootAnimation;
nsecs_t mBootTime;
// Can only accessed from the main thread, these members
@@ -337,7 +335,6 @@
// don't use a lock for these, we don't care
int mDebugRegion;
int mDebugBackground;
- int mDebugNoBootAnimation;
// these are thread safe
mutable Barrier mReadyToRunBarrier;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
index 238c602..68c0a5e 100644
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -30,10 +30,12 @@
#include <cutils/log.h>
#include <cutils/properties.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapPmem.h>
+#include <binder/MemoryHeapBase.h>
+
+#include <EGL/eglnatives.h>
#include "GPUHardware/GPUHardware.h"
#include "SurfaceFlinger.h"
diff --git a/libs/surfaceflinger/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h
index 9140167..780a1bc 100644
--- a/libs/surfaceflinger/VRamHeap.h
+++ b/libs/surfaceflinger/VRamHeap.h
@@ -19,7 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
namespace android {
diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnim.h b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h
index 472c45a..a1a2654 100644
--- a/libs/surfaceflinger/purgatory/LayerOrientationAnim.h
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <utils/threads.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include "LayerBase.h"
#include "LayerBitmap.h"
diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
index a675c79..a88eec0 100644
--- a/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
+++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <utils/threads.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include "LayerBase.h"
#include "LayerBitmap.h"
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp
index f3c046f..0b9322e 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/libs/surfaceflinger/tests/overlays/overlays.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <ui/Surface.h>
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 7c367ef..bf886a4 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -31,6 +31,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ libbinder \
libpixelflinger \
libhardware \
libhardware_legacy
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 6613700..4228300 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -19,9 +19,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Camera"
#include <utils/Log.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/threads.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <ui/Surface.h>
#include <ui/Camera.h>
#include <ui/ICameraService.h>
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 7c2fc8e..52aa0c0 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -19,7 +19,6 @@
#include <hardware_legacy/power.h>
#include <cutils/properties.h>
-#include <utils/IServiceManager.h>
#include <utils/Log.h>
#include <utils/Timers.h>
#include <utils.h>
diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp
index ab0fef1..cbe8798 100644
--- a/libs/ui/ICamera.cpp
+++ b/libs/ui/ICamera.cpp
@@ -20,7 +20,7 @@
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <ui/ICamera.h>
namespace android {
diff --git a/libs/ui/ICameraService.cpp b/libs/ui/ICameraService.cpp
index e5687fe..1adb4aa 100644
--- a/libs/ui/ICameraService.cpp
+++ b/libs/ui/ICameraService.cpp
@@ -18,9 +18,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <ui/ICameraService.h>
diff --git a/libs/ui/IOverlay.cpp b/libs/ui/IOverlay.cpp
index fed47c2..a20b36c 100644
--- a/libs/ui/IOverlay.cpp
+++ b/libs/ui/IOverlay.cpp
@@ -18,8 +18,8 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
-#include <utils/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
#include <ui/IOverlay.h>
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index ec922d0..fcc0303 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -20,8 +20,8 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
#include <ui/ISurface.h>
#include <ui/Overlay.h>
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
index 1932bf9..869e428 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -20,10 +20,10 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <ui/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index 597b87e..c2f6f834 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -21,10 +21,10 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <ui/ISurface.h>
#include <ui/ISurfaceFlingerClient.h>
@@ -35,6 +35,13 @@
// ---------------------------------------------------------------------------
+/* ideally AID_GRAPHICS would be in a semi-public header
+ * or there would be a way to map a user/group name to its id
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -136,13 +143,13 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
- const int self_pid = getpid();
- if (UNLIKELY(pid != self_pid)) {
+ const int uid = ipc->getCallingUid();
+ const int self_pid = getpid();
+ if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
// we're called from a different process, do the real check
if (!checkCallingPermission(
String16("android.permission.ACCESS_SURFACE_FLINGER")))
{
- const int uid = ipc->getCallingUid();
LOGE("Permission Denial: "
"can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
diff --git a/libs/ui/LayerState.cpp b/libs/ui/LayerState.cpp
index 0b6374b..a53ffb7 100644
--- a/libs/ui/LayerState.cpp
+++ b/libs/ui/LayerState.cpp
@@ -15,7 +15,7 @@
*/
#include <utils/Errors.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <private/ui/LayerState.h>
namespace android {
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 59c6514..a092f8d 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include <utils/IMemory.h>
-#include <utils/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
#include <utils/Errors.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
#include <ui/IOverlay.h>
#include <ui/Overlay.h>
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 6db30c3..0fe28d4 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -25,8 +25,8 @@
#include <utils/Errors.h>
#include <utils/threads.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IMemory.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IMemory.h>
#include <utils/Log.h>
#include <ui/DisplayInfo.h>
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index 413167f..025bf6e3 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -29,8 +29,8 @@
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
-#include <utils/IServiceManager.h>
-#include <utils/IMemory.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
#include <utils/Log.h>
#include <ui/DisplayInfo.h>
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 5a1a89b..30b6733 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -103,19 +103,6 @@
# we have the common sources, plus some device-specific stuff
LOCAL_SRC_FILES:= \
$(commonSources) \
- Binder.cpp \
- BpBinder.cpp \
- IInterface.cpp \
- IMemory.cpp \
- IPCThreadState.cpp \
- MemoryDealer.cpp \
- MemoryBase.cpp \
- MemoryHeapBase.cpp \
- MemoryHeapPmem.cpp \
- Parcel.cpp \
- ProcessState.cpp \
- IPermissionController.cpp \
- IServiceManager.cpp \
Unicode.cpp \
backup_data.cpp \
backup_helper_file.cpp
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 447b801..4126bfb 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -901,6 +901,60 @@
}
/*
+ * Open a directory in the non-asset namespace.
+ *
+ * An "asset directory" is simply the combination of all files in all
+ * locations, with ".gz" stripped for loose files. With app, locale, and
+ * vendor defined, we have 8 directories and 2 Zip archives to scan.
+ *
+ * Pass in "" for the root dir.
+ */
+AssetDir* AssetManager::openNonAssetDir(void* cookie, const char* dirName)
+{
+ AutoMutex _l(mLock);
+
+ AssetDir* pDir = NULL;
+ SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
+
+ LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
+ assert(dirName != NULL);
+
+ //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
+
+ if (mCacheMode != CACHE_OFF && !mCacheValid)
+ loadFileNameCacheLocked();
+
+ pDir = new AssetDir;
+
+ pMergedInfo = new SortedVector<AssetDir::FileInfo>;
+
+ const size_t which = ((size_t)cookie)-1;
+
+ if (which < mAssetPaths.size()) {
+ const asset_path& ap = mAssetPaths.itemAt(which);
+ if (ap.type == kFileTypeRegular) {
+ LOGV("Adding directory %s from zip %s", dirName, ap.path.string());
+ scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName);
+ } else {
+ LOGV("Adding directory %s from dir %s", dirName, ap.path.string());
+ scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName);
+ }
+ }
+
+#if 0
+ printf("FILE LIST:\n");
+ for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
+ printf(" %d: (%d) '%s'\n", i,
+ pMergedInfo->itemAt(i).getFileType(),
+ (const char*) pMergedInfo->itemAt(i).getFileName());
+ }
+#endif
+
+ pDir->setFileList(pMergedInfo);
+ return pDir;
+}
+
+/*
* Scan the contents of the specified directory and merge them into the
* "pMergedInfo" vector, removing previous entries if we find "exclude"
* directives.
@@ -1143,6 +1197,7 @@
LOGE("ARGH: name too long?\n");
continue;
}
+ //printf("Comparing %s in %s?\n", nameBuf, dirName.string());
if (dirNameLen == 0 ||
(strncmp(nameBuf, dirName.string(), dirNameLen) == 0 &&
nameBuf[dirNameLen] == '/'))
@@ -1165,7 +1220,7 @@
createZipSourceNameLocked(zipName, dirName, info.getFileName()));
contents.add(info);
- //printf("FOUND: file '%s'\n", (const char*) info.mFileName);
+ //printf("FOUND: file '%s'\n", info.getFileName().string());
} else {
/* this is a subdir; add it if we don't already have it*/
String8 subdirName(cp, nextSlash - cp);
@@ -1181,7 +1236,7 @@
dirs.add(subdirName);
}
- //printf("FOUND: dir '%s'\n", (const char*) subdirName);
+ //printf("FOUND: dir '%s'\n", subdirName.string());
}
}
}
diff --git a/libs/utils/IDataConnection.cpp b/libs/utils/IDataConnection.cpp
deleted file mode 100644
index c6d49aa..0000000
--- a/libs/utils/IDataConnection.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Parcel.h>
-
-#include <utils/IDataConnection.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-enum
-{
- CONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
- DISCONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1
-};
-
-class BpDataConnection : public BpInterface<IDataConnection>
-{
-public:
- BpDataConnection::BpDataConnection(const sp<IBinder>& impl)
- : BpInterface<IDataConnection>(impl)
- {
- }
-
- virtual void connect()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IDataConnection::descriptor());
- remote()->transact(CONNECT_TRANSACTION, data, &reply);
- }
-
- virtual void disconnect()
- {
- Parcel data, reply;
- remote()->transact(DISCONNECT_TRANSACTION, data, &reply);
- }
-};
-
-IMPLEMENT_META_INTERFACE(DataConnection, "android.utils.IDataConnection");
-
-#define CHECK_INTERFACE(interface, data, reply) \
- do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
- LOGW("Call incorrectly routed to " #interface); \
- return PERMISSION_DENIED; \
- } } while (0)
-
-status_t BnDataConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code)
- {
- case CONNECT_TRANSACTION:
- {
- CHECK_INTERFACE(IDataConnection, data, reply);
- connect();
- return NO_ERROR;
- }
-
- case DISCONNECT_TRANSACTION:
- {
- CHECK_INTERFACE(IDataConnection, data, reply);
- disconnect();
- return NO_ERROR;
- }
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp
index 93f7e4f..4dfa578 100644
--- a/libs/utils/Static.cpp
+++ b/libs/utils/Static.cpp
@@ -20,7 +20,6 @@
#include <private/utils/Static.h>
#include <utils/BufferedTextOutput.h>
-#include <utils/IPCThreadState.h>
#include <utils/Log.h>
namespace android {
@@ -87,34 +86,4 @@
TextOutput& aout(gStdoutTextOutput);
TextOutput& aerr(gStderrTextOutput);
-#ifndef LIBUTILS_NATIVE
-
-// ------------ ProcessState.cpp
-
-Mutex gProcessMutex;
-sp<ProcessState> gProcess;
-
-class LibUtilsIPCtStatics
-{
-public:
- LibUtilsIPCtStatics()
- {
- }
-
- ~LibUtilsIPCtStatics()
- {
- IPCThreadState::shutdown();
- }
-};
-
-static LibUtilsIPCtStatics gIPCStatics;
-
-// ------------ ServiceManager.cpp
-
-Mutex gDefaultServiceManagerLock;
-sp<IServiceManager> gDefaultServiceManager;
-sp<IPermissionController> gPermissionController;
-
-#endif
-
} // namespace android
diff --git a/libs/utils/backup_data.cpp b/libs/utils/backup_data.cpp
index c7f1fdb..95c05b7 100644
--- a/libs/utils/backup_data.cpp
+++ b/libs/utils/backup_data.cpp
@@ -14,12 +14,16 @@
* limitations under the License.
*/
+#define LOG_TAG "backup_data"
+
#include <utils/backup_helpers.h>
#include <utils/ByteOrder.h>
#include <stdio.h>
#include <unistd.h>
+#include <cutils/log.h>
+
namespace android {
/*
@@ -35,26 +39,6 @@
* - The value, padded to 4 byte boundary
*/
-#define APP_MAGIC_V1 0x31707041 // App1 (little endian)
-#define ENTITY_MAGIC_V1 0x61746144 // Data (little endian)
-#define FOOTER_MAGIC_V1 0x746f6f46 // Foot (little endian)
-
-typedef struct {
- int type; // == APP_MAGIC_V1
- int packageLen; // length of the name of the package that follows, not including the null.
-} app_header_v1;
-
-typedef struct {
- int type; // ENTITY_MAGIC_V1
- int keyLen; // length of the key name, not including the null terminator
- int dataSize; // size of the data, not including the padding
-} entity_header_v1;
-
-typedef struct {
- int type; // FOOTER_MAGIC_V1
- int entityCount; // the number of entities that were written
-} app_footer_v1;
-
const static int ROUND_UP[4] = { 0, 3, 2, 1 };
static inline size_t
@@ -102,7 +86,7 @@
}
status_t
-BackupDataWriter::WriteAppHeader(const String8& packageName)
+BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie)
{
if (m_status != NO_ERROR) {
return m_status;
@@ -120,8 +104,9 @@
nameLen = packageName.length();
- header.type = tolel(APP_MAGIC_V1);
+ header.type = tolel(BACKUP_HEADER_APP_V1);
header.packageLen = tolel(nameLen);
+ header.cookie = cookie;
amt = write(m_fd, &header, sizeof(app_header_v1));
if (amt != sizeof(app_header_v1)) {
@@ -159,7 +144,7 @@
keyLen = key.length();
- header.type = tolel(ENTITY_MAGIC_V1);
+ header.type = tolel(BACKUP_HEADER_ENTITY_V1);
header.keyLen = tolel(keyLen);
header.dataSize = tolel(dataSize);
@@ -204,7 +189,7 @@
}
status_t
-BackupDataWriter::WriteAppFooter()
+BackupDataWriter::WriteAppFooter(int cookie)
{
if (m_status != NO_ERROR) {
return m_status;
@@ -220,8 +205,9 @@
app_footer_v1 footer;
ssize_t nameLen;
- footer.type = tolel(FOOTER_MAGIC_V1);
+ footer.type = tolel(BACKUP_FOOTER_APP_V1);
footer.entityCount = tolel(m_entityCount);
+ footer.cookie = cookie;
amt = write(m_fd, &footer, sizeof(app_footer_v1));
if (amt != sizeof(app_footer_v1)) {
@@ -233,4 +219,221 @@
return NO_ERROR;
}
+
+BackupDataReader::BackupDataReader(int fd)
+ :m_fd(fd),
+ m_status(NO_ERROR),
+ m_pos(0),
+ m_entityCount(0)
+{
+ memset(&m_header, 0, sizeof(m_header));
+}
+
+BackupDataReader::~BackupDataReader()
+{
+}
+
+status_t
+BackupDataReader::Status()
+{
+ return m_status;
+}
+
+#define CHECK_SIZE(actual, expected) \
+ do { \
+ if ((actual) != (expected)) { \
+ if ((actual) == 0) { \
+ m_status = EIO; \
+ } else { \
+ m_status = errno; \
+ } \
+ return m_status; \
+ } \
+ } while(0)
+#define SKIP_PADDING() \
+ do { \
+ status_t err = skip_padding(); \
+ if (err != NO_ERROR) { \
+ m_status = err; \
+ return err; \
+ } \
+ } while(0)
+
+status_t
+BackupDataReader::ReadNextHeader(int* type)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+
+ int amt;
+
+ SKIP_PADDING();
+ amt = read(m_fd, &m_header, sizeof(m_header));
+ CHECK_SIZE(amt, sizeof(m_header));
+
+ // validate and fix up the fields.
+ m_header.type = fromlel(m_header.type);
+ switch (m_header.type)
+ {
+ case BACKUP_HEADER_APP_V1:
+ m_header.app.packageLen = fromlel(m_header.app.packageLen);
+ if (m_header.app.packageLen < 0) {
+ LOGD("App header at %d has packageLen<0: 0x%08x\n", (int)m_pos,
+ (int)m_header.app.packageLen);
+ m_status = EINVAL;
+ }
+ m_header.app.cookie = m_header.app.cookie;
+ break;
+ case BACKUP_HEADER_ENTITY_V1:
+ m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
+ if (m_header.entity.keyLen <= 0) {
+ LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
+ (int)m_header.entity.keyLen);
+ m_status = EINVAL;
+ }
+ m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
+ m_entityCount++;
+ break;
+ case BACKUP_FOOTER_APP_V1:
+ m_header.footer.entityCount = fromlel(m_header.footer.entityCount);
+ if (m_header.footer.entityCount < 0) {
+ LOGD("Entity header at %d has entityCount<0: 0x%08x\n", (int)m_pos,
+ (int)m_header.footer.entityCount);
+ m_status = EINVAL;
+ }
+ m_header.footer.cookie = m_header.footer.cookie;
+ break;
+ default:
+ LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
+ m_status = EINVAL;
+ }
+ m_pos += sizeof(m_header);
+ if (type) {
+ *type = m_header.type;
+ }
+
+ return m_status;
+}
+
+status_t
+BackupDataReader::ReadAppHeader(String8* packageName, int* cookie)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != BACKUP_HEADER_APP_V1) {
+ return EINVAL;
+ }
+ size_t size = m_header.app.packageLen;
+ char* buf = packageName->lockBuffer(size);
+ if (packageName == NULL) {
+ packageName->unlockBuffer();
+ m_status = ENOMEM;
+ return m_status;
+ }
+ int amt = read(m_fd, buf, size+1);
+ CHECK_SIZE(amt, (int)size+1);
+ packageName->unlockBuffer(size);
+ m_pos += size+1;
+ *cookie = m_header.app.cookie;
+ return NO_ERROR;
+}
+
+bool
+BackupDataReader::HasEntities()
+{
+ return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
+}
+
+status_t
+BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
+ return EINVAL;
+ }
+ size_t size = m_header.entity.keyLen;
+ char* buf = key->lockBuffer(size);
+ if (key == NULL) {
+ key->unlockBuffer();
+ m_status = ENOMEM;
+ return m_status;
+ }
+ int amt = read(m_fd, buf, size+1);
+ CHECK_SIZE(amt, (int)size+1);
+ key->unlockBuffer(size);
+ m_pos += size+1;
+ *dataSize = m_header.entity.dataSize;
+ SKIP_PADDING();
+ return NO_ERROR;
+}
+
+status_t
+BackupDataReader::SkipEntityData()
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
+ return EINVAL;
+ }
+ if (m_header.entity.dataSize > 0) {
+ int pos = lseek(m_fd, m_header.entity.dataSize, SEEK_CUR);
+ return pos == -1 ? (int)errno : (int)NO_ERROR;
+ } else {
+ return NO_ERROR;
+ }
+}
+
+status_t
+BackupDataReader::ReadEntityData(void* data, size_t size)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ int amt = read(m_fd, data, size);
+ CHECK_SIZE(amt, (int)size);
+ m_pos += size;
+ return NO_ERROR;
+}
+
+status_t
+BackupDataReader::ReadAppFooter(int* cookie)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != BACKUP_FOOTER_APP_V1) {
+ return EINVAL;
+ }
+ if (m_header.footer.entityCount != m_entityCount) {
+ LOGD("entity count mismatch actual=%d expected=%d", m_entityCount,
+ m_header.footer.entityCount);
+ m_status = EINVAL;
+ return m_status;
+ }
+ *cookie = m_header.footer.cookie;
+ return NO_ERROR;
+}
+
+status_t
+BackupDataReader::skip_padding()
+{
+ ssize_t amt;
+ ssize_t paddingSize;
+
+ paddingSize = padding_extra(m_pos);
+ if (paddingSize > 0) {
+ uint32_t padding;
+ amt = read(m_fd, &padding, paddingSize);
+ CHECK_SIZE(amt, paddingSize);
+ m_pos += amt;
+ }
+ return NO_ERROR;
+}
+
+
} // namespace android
diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/backup_helper_file.cpp
index 1fa6a0f..8efb3eb 100644
--- a/libs/utils/backup_helper_file.cpp
+++ b/libs/utils/backup_helper_file.cpp
@@ -40,7 +40,7 @@
#define MAGIC0 0x70616e53 // Snap
#define MAGIC1 0x656c6946 // File
-#if TEST_BACKUP_HELPERS
+#if 0 // TEST_BACKUP_HELPERS
#define LOGP(x...) printf(x)
#else
#define LOGP(x...) LOGD(x)
@@ -181,45 +181,105 @@
}
static int
-write_delete_file(const String8& key)
+write_delete_file(BackupDataWriter* dataStream, const String8& key)
{
LOGP("write_delete_file %s\n", key.string());
- return 0;
+ return dataStream->WriteEntityHeader(key, -1);
}
static int
-write_update_file(const String8& realFilename, const String8& key)
+write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
+ const String8& realFilename)
{
LOGP("write_update_file %s (%s)\n", realFilename.string(), key.string());
- return 0;
+
+ const int bufsize = 4*1024;
+ int err;
+ int amt;
+ int fileSize;
+ int bytesLeft;
+
+ char* buf = (char*)malloc(bufsize);
+ int crc = crc32(0L, Z_NULL, 0);
+
+
+ bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+
+ err = dataStream->WriteEntityHeader(key, bytesLeft);
+ if (err != 0) {
+ return err;
+ }
+
+ while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
+ bytesLeft -= amt;
+ if (bytesLeft < 0) {
+ amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
+ }
+ err = dataStream->WriteEntityData(buf, amt);
+ if (err != 0) {
+ return err;
+ }
+ }
+ if (bytesLeft != 0) {
+ if (bytesLeft > 0) {
+ // Pad out the space we promised in the buffer. We can't corrupt the buffer,
+ // even though the data we're sending is probably bad.
+ memset(buf, 0, bufsize);
+ while (bytesLeft > 0) {
+ amt = bytesLeft < bufsize ? bytesLeft : bufsize;
+ bytesLeft -= amt;
+ err = dataStream->WriteEntityData(buf, amt);
+ if (err != 0) {
+ return err;
+ }
+ }
+ }
+ LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
+ " You aren't doing proper locking!",
+ realFilename.string(), fileSize, fileSize-bytesLeft);
+ }
+
+ free(buf);
+
+ return NO_ERROR;
}
static int
-compute_crc32(const String8& filename)
+write_update_file(BackupDataWriter* dataStream, const String8& key, const String8& realFilename)
+{
+ int err;
+ int fd = open(realFilename.string(), O_RDONLY);
+ if (fd == -1) {
+ return errno;
+ }
+ err = write_update_file(dataStream, fd, key, realFilename);
+ close(fd);
+ return err;
+}
+
+static int
+compute_crc32(int fd)
{
const int bufsize = 4*1024;
int amt;
- int fd = open(filename.string(), O_RDONLY);
- if (fd == -1) {
- return -1;
- }
-
char* buf = (char*)malloc(bufsize);
int crc = crc32(0L, Z_NULL, 0);
+ lseek(fd, 0, SEEK_SET);
+
while ((amt = read(fd, buf, bufsize)) != 0) {
crc = crc32(crc, (Bytef*)buf, amt);
}
- close(fd);
free(buf);
return crc;
}
int
-back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
+back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
char const* fileBase, char const* const* files, int fileCount)
{
int err;
@@ -252,7 +312,8 @@
s.modTime_nsec = 0; // workaround sim breakage
//s.modTime_nsec = st.st_mtime_nsec;
s.size = st.st_size;
- s.crc32 = compute_crc32(realFilename);
+
+ // we compute the crc32 later down below, when we already have the file open.
newSnapshot.add(name, s);
}
@@ -270,30 +331,42 @@
String8 realFilename(base);
realFilename.appendPath(q);
LOGP("file added: %s\n", realFilename.string());
- write_update_file(realFilename, q);
+ write_update_file(dataStream, q, realFilename);
m++;
}
else if (cmp < 0) {
// file removed
LOGP("file removed: %s\n", p.string());
- write_delete_file(p);
+ dataStream->WriteEntityHeader(p, -1);
n++;
}
else {
+
// both files exist, check them
String8 realFilename(base);
realFilename.appendPath(q);
const FileState& f = oldSnapshot.valueAt(n);
- const FileState& g = newSnapshot.valueAt(m);
+ FileState& g = newSnapshot.editValueAt(m);
- LOGP("%s\n", q.string());
- LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n",
- f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
- LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x\n",
- g.modTime_sec, g.modTime_nsec, g.size, g.crc32);
- if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec
- || f.size != g.size || f.crc32 != g.crc32) {
- write_update_file(realFilename, p);
+ int fd = open(realFilename.string(), O_RDONLY);
+ if (fd != -1) {
+ // We can't open the file. Don't report it as a delete either. Let the
+ // server keep the old version. Maybe they'll be able to deal with it
+ // on restore.
+ } else {
+ g.crc32 = compute_crc32(fd);
+
+ LOGP("%s\n", q.string());
+ LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n",
+ f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
+ LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x\n",
+ g.modTime_sec, g.modTime_nsec, g.size, g.crc32);
+ if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec
+ || f.size != g.size || f.crc32 != g.crc32) {
+ write_update_file(dataStream, fd, p, realFilename);
+ }
+
+ close(fd);
}
n++;
m++;
@@ -302,7 +375,7 @@
// these were deleted
while (n<N) {
- write_delete_file(oldSnapshot.keyAt(n));
+ dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
n++;
}
@@ -311,7 +384,7 @@
const String8& q = newSnapshot.keyAt(m);
String8 realFilename(base);
realFilename.appendPath(q);
- write_update_file(realFilename, q);
+ write_update_file(dataStream, q, realFilename);
m++;
}
@@ -599,13 +672,14 @@
// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
const unsigned char DATA_GOLDEN_FILE[] = {
0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00,
- 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
- 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
- 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
- 0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
+ 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70,
0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
- 0x41, 0x70, 0x70, 0x31, 0x0c, 0x00, 0x00, 0x00,
+ 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
+ 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
+ 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31,
+ 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00,
@@ -614,15 +688,16 @@
0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
- 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+ 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
+ 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
+ 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
+ 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
- 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
- 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
- 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
- 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
- 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
- 0x41, 0x70, 0x70, 0x31, 0x0a, 0x00, 0x00, 0x00,
+ 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
+ 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
+ 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
+ 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61,
0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
@@ -630,6 +705,7 @@
0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc,
0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00,
+ 0x99, 0x99, 0x77, 0x77
};
const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
@@ -639,7 +715,7 @@
int err;
String8 text(str);
- err = writer.WriteAppHeader(text);
+ err = writer.WriteAppHeader(text, 0xaabbccdd);
if (err != 0) {
fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
return err;
@@ -685,7 +761,7 @@
err |= test_write_header_and_entity(writer, "padded_to_2__");
err |= test_write_header_and_entity(writer, "padded_to1");
- writer.WriteAppFooter();
+ writer.WriteAppFooter(0x77779999);
close(fd);
@@ -697,6 +773,162 @@
return err;
}
+int
+test_read_header_and_entity(BackupDataReader& reader, const char* str)
+{
+ int err;
+ int bufSize = strlen(str)+1;
+ char* buf = (char*)malloc(bufSize);
+ String8 string;
+ int cookie = 0x11111111;
+ size_t actualSize;
+
+ // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
+
+ err = reader.ReadNextHeader();
+ if (err != 0) {
+ fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
+ goto done;
+ }
+
+ err = reader.ReadAppHeader(&string, &cookie);
+ if (err != 0) {
+ fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err));
+ goto done;
+ }
+ if (string != str) {
+ fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string());
+ err = EINVAL;
+ goto done;
+ }
+ if (cookie != (int)0xaabbccdd) {
+ fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie);
+ err = EINVAL;
+ goto done;
+ }
+
+ err = reader.ReadNextHeader();
+ if (err != 0) {
+ fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err));
+ goto done;
+ }
+
+ err = reader.ReadEntityHeader(&string, &actualSize);
+ if (err != 0) {
+ fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
+ goto done;
+ }
+ if (string != str) {
+ fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
+ err = EINVAL;
+ goto done;
+ }
+ if ((int)actualSize != bufSize) {
+ fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
+ actualSize);
+ err = EINVAL;
+ goto done;
+ }
+
+ err = reader.ReadEntityData(buf, bufSize);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
+ goto done;
+ }
+
+ if (0 != memcmp(buf, str, bufSize)) {
+ fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
+ "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]);
+ err = EINVAL;
+ goto done;
+ }
+
+ // The next read will confirm whether it got the right amount of data.
+
+done:
+ if (err != NO_ERROR) {
+ fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
+ }
+ free(buf);
+ return err;
+}
+
+int
+backup_helper_test_data_reader()
+{
+ int err;
+ int fd;
+ const char* filename = SCRATCH_DIR "data_reader.data";
+
+ system("rm -r " SCRATCH_DIR);
+ mkdir(SCRATCH_DIR, 0777);
+ mkdir(SCRATCH_DIR "data", 0777);
+
+ fd = creat(filename, 0666);
+ if (fd == -1) {
+ fprintf(stderr, "error creating: %s\n", strerror(errno));
+ return errno;
+ }
+
+ err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
+ if (err != DATA_GOLDEN_FILE_SIZE) {
+ fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
+ return errno;
+ }
+
+ close(fd);
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
+ filename);
+ return errno;
+ }
+
+ {
+ BackupDataReader reader(fd);
+
+ err = 0;
+
+ if (err == NO_ERROR) {
+ err = test_read_header_and_entity(reader, "no_padding_");
+ }
+
+ if (err == NO_ERROR) {
+ err = test_read_header_and_entity(reader, "padded_to__3");
+ }
+
+ if (err == NO_ERROR) {
+ err = test_read_header_and_entity(reader, "padded_to_2__");
+ }
+
+ if (err == NO_ERROR) {
+ err = test_read_header_and_entity(reader, "padded_to1");
+ }
+
+ if (err == NO_ERROR) {
+ err = reader.ReadNextHeader();
+ if (err != 0) {
+ fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
+ }
+
+ if (err == NO_ERROR) {
+ int cookie;
+ err |= reader.ReadAppFooter(&cookie);
+ if (cookie != 0x77779999) {
+ fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n",
+ 0x77779999, cookie);
+ err = EINVAL;
+ }
+ }
+ }
+ }
+
+ close(fd);
+
+ return err;
+}
+
static int
get_mod_time(const char* filename, struct timeval times[2])
{
@@ -752,10 +984,14 @@
fprintf(stderr, "error creating: %s\n", strerror(errno));
return errno;
}
+
+ {
+ BackupDataWriter dataStream(dataStreamFD);
- err = back_up_files(-1, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_before, 5);
- if (err != 0) {
- return err;
+ err = back_up_files(-1, &dataStream, newSnapshotFD, SCRATCH_DIR, files_before, 5);
+ if (err != 0) {
+ return err;
+ }
}
close(dataStreamFD);
@@ -809,10 +1045,15 @@
return errno;
}
- err = back_up_files(oldSnapshotFD, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_after, 6);
- if (err != 0) {
- return err;
- }
+ {
+ BackupDataWriter dataStream(dataStreamFD);
+
+ err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, SCRATCH_DIR,
+ files_after, 6);
+ if (err != 0) {
+ return err;
+ }
+}
close(oldSnapshotFD);
close(dataStreamFD);
diff --git a/location/java/android/location/ILocationCollector.aidl b/location/java/android/location/ILocationCollector.aidl
deleted file mode 100644
index b2e1796..0000000
--- a/location/java/android/location/ILocationCollector.aidl
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 android.location;
-
-import android.location.Location;
-
-/**
- * Listens for GPS and cell/wifi changes and anonymously uploads to server
- * for improving quality of service of NetworkLocationProvider.
- * This service is only enabled when the user has enabled the
- * network location provider.
- *
- * {@hide}
- */
-oneway interface ILocationCollector {
- /**
- * Updates GPS location if collection is enabled
- *
- * @param location location object
- */
- void updateLocation(in Location location);
-}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 2c214c9..caf9516 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -20,7 +20,6 @@
import android.location.Address;
import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
-import android.location.ILocationCollector;
import android.location.ILocationListener;
import android.location.ILocationProvider;
import android.location.Location;
@@ -83,6 +82,5 @@
/* for installing external Location Providers */
void installLocationProvider(String name, ILocationProvider provider);
- void installLocationCollector(ILocationCollector collector);
void installGeocodeProvider(IGeocodeProvider provider);
}
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 6c23f83..4fe0494 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -16,6 +16,7 @@
package android.location;
+import android.location.Location;
import android.os.Bundle;
/**
@@ -41,6 +42,7 @@
void enableLocationTracking(boolean enable);
void setMinTime(long minTime);
void updateNetworkState(int state);
+ void updateLocation(in Location location);
boolean sendExtraCommand(String command, inout Bundle extras);
void addListener(int uid);
void removeListener(int uid);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 872838c..86ea66f 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1279,27 +1279,6 @@
}
/**
- * Installs a location collector.
- *
- * @param provider Binder interface for the location collector
- *
- * @return true if the command succeeds.
- *
- * Requires the android.permission.INSTALL_LOCATION_COLLECTOR permission.
- *
- * {@hide}
- */
- public boolean installLocationCollector(ILocationCollector collector) {
- try {
- mService.installLocationCollector(collector);
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in setLocationCollector: ", e);
- return false;
- }
- }
-
- /**
* Installs a geocoder server.
*
* @param provider Binder interface for the geocoder provider
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 565859c..725fbf9 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -406,6 +406,13 @@
}
/**
+ * This is called to inform us when another location provider returns a location.
+ * Someday we might use this for network location injection to aid the GPS
+ */
+ public void updateLocation(Location location) {
+ }
+
+ /**
* Returns true if the provider requires access to a
* satellite-based positioning system (e.g., GPS), false
* otherwise.
@@ -641,6 +648,16 @@
if ("delete_aiding_data".equals(command)) {
return deleteAidingData(extras);
}
+ if ("force_time_injection".equals(command)) {
+ return forceTimeInjection();
+ }
+ if ("force_xtra_injection".equals(command)) {
+ if (native_supports_xtra() && mNetworkThread != null) {
+ xtraDownloadRequest();
+ return true;
+ }
+ return false;
+ }
Log.w(TAG, "sendExtraCommand: unknown command " + command);
return false;
@@ -676,6 +693,15 @@
return false;
}
+ private boolean forceTimeInjection() {
+ if (Config.LOGD) Log.d(TAG, "forceTimeInjection");
+ if (mNetworkThread != null) {
+ mNetworkThread.timeInjectRequest();
+ return true;
+ }
+ return false;
+ }
+
public void startNavigating() {
if (!mStarted) {
if (DEBUG) Log.d(TAG, "startNavigating");
@@ -1004,6 +1030,7 @@
private long mNextNtpTime = 0;
private long mNextXtraTime = 0;
+ private boolean mTimeInjectRequested = false;
private boolean mXtraDownloadRequested = false;
private boolean mDone = false;
@@ -1054,16 +1081,17 @@
}
waitTime = getWaitTime();
} while (!mDone && ((!mXtraDownloadRequested &&
- !mSetSuplServer && !mSetC2KServer && waitTime > 0)
+ !mTimeInjectRequested && !mSetSuplServer && !mSetC2KServer && waitTime > 0)
|| !mNetworkAvailable));
if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
if (!mDone) {
if (mNtpServer != null &&
- mNextNtpTime <= System.currentTimeMillis()) {
+ (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
if (Config.LOGD) {
Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
}
+ mTimeInjectRequested = false;
if (client.requestTime(mNtpServer, 10000)) {
long time = client.getNtpTime();
long timeReference = client.getNtpTimeReference();
@@ -1096,6 +1124,7 @@
if ((mXtraDownloadRequested ||
(mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
&& xtraDownloader != null) {
+ mXtraDownloadRequested = false;
byte[] data = xtraDownloader.downloadXtraData();
if (data != null) {
if (Config.LOGD) {
@@ -1103,7 +1132,6 @@
}
native_inject_xtra_data(data, data.length);
mNextXtraTime = 0;
- mXtraDownloadRequested = false;
} else {
mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
}
@@ -1118,6 +1146,11 @@
notify();
}
+ synchronized void timeInjectRequest() {
+ mTimeInjectRequested = true;
+ notify();
+ }
+
synchronized void signal() {
notify();
}
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index b40cdca..bd7088c 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -219,6 +219,14 @@
}
}
+ public void updateLocation(Location location) {
+ try {
+ mProvider.updateLocation(location);
+ } catch (RemoteException e) {
+ Log.e(TAG, "updateLocation failed", e);
+ }
+ }
+
public boolean sendExtraCommand(String command, Bundle extras) {
try {
return mProvider.sendExtraCommand(command, extras);
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index f167a44..e2e0562 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -172,6 +172,9 @@
public void updateNetworkState(int state) {
}
+ public void updateLocation(Location location) {
+ }
+
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c0cd5e3..c46f64e 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -53,7 +53,45 @@
import java.util.Iterator;
/**
- * Internal service that no-one should use directly.
+ * Internal service helper that no-one should use directly.
+ *
+ * The way the scan currently works is:
+ * - The Java MediaScannerService creates a MediaScanner (this class), and calls
+ * MediaScanner.scanDirectories on it.
+ * - scanDirectories() calls the native processDirectory() for each of the specified directories.
+ * - the processDirectory() JNI method wraps the provided mediascanner client in a native
+ * 'MyMediaScannerClient' class, then calls processDirectory() on the native MediaScanner
+ * object (which got created when the Java MediaScanner was created).
+ * - native MediaScanner.processDirectory() (currently part of opencore) calls
+ * doProcessDirectory(), which recurses over the folder, and calls
+ * native MyMediaScannerClient.scanFile() for every file whose extension matches.
+ * - native MyMediaScannerClient.scanFile() calls back on Java MediaScannerClient.scanFile,
+ * which calls doScanFile, which after some setup calls back down to native code, calling
+ * MediaScanner.processFile().
+ * - MediaScanner.processFile() calls one of several methods, depending on the type of the
+ * file: parseMP3, parseMP4, parseMidi, parseOgg or parseWMA.
+ * - each of these methods gets metadata key/value pairs from the file, and repeatedly
+ * calls native MyMediaScannerClient.handleStringTag, which calls back up to its Java
+ * counterparts in this file.
+ * - Java handleStringTag() gathers the key/value pairs that it's interested in.
+ * - once processFile returns and we're back in Java code in doScanFile(), it calls
+ * Java MyMediaScannerClient.endFile(), which takes all the data that's been
+ * gathered and inserts an entry in to the database.
+ *
+ * In summary:
+ * Java MediaScannerService calls
+ * Java MediaScanner scanDirectories, which calls
+ * Java MediaScanner processDirectory (native method), which calls
+ * native MediaScanner processDirectory, which calls
+ * native MyMediaScannerClient scanFile, which calls
+ * Java MyMediaScannerClient scanFile, which calls
+ * Java MediaScannerClient doScanFile, which calls
+ * Java MediaScanner processFile (native method), which calls
+ * native MediaScanner processFile, which calls
+ * native parseMP3, parseMP4, parseMidi, parseOgg or parseWMA, which calls
+ * native MyMediaScanner handleStringTag, which calls
+ * Java MyMediaScanner handleStringTag.
+ * Once MediaScanner processFile returns, an entry is inserted in to the database.
*
* {@hide}
*/
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 8ee0cbd..9552aa6 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -18,6 +18,7 @@
libnativehelper \
libcutils \
libutils \
+ libbinder \
libmedia \
libsgl \
libui
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 374ddeb..9ff2e24 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -9,6 +9,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ libbinder \
libandroid_runtime \
libnativehelper \
libmedia
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 8020da2..806ef52 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -21,7 +21,7 @@
JetPlayer.cpp
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libsonivox
+ libui libcutils libutils libbinder libsonivox
LOCAL_MODULE:= libmedia
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 1720af0..793bbf4 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -29,11 +29,11 @@
#include <media/AudioSystem.h>
#include <media/AudioRecord.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
+#include <binder/MemoryDealer.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
#include <cutils/atomic.h>
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index a21a7a4..86d0542 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <media/AudioSystem.h>
#include <math.h>
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 289bd75..4a1b69e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -32,9 +32,9 @@
#include <media/AudioTrack.h>
#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
+#include <binder/MemoryDealer.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
#include <cutils/atomic.h>
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 52bd7d4..7395885 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -21,7 +21,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <media/IAudioFlinger.h>
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 9d00aefb..dbc2bba 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <media/IAudioFlingerClient.h>
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index 6e42dac..000a304 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -18,7 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <media/IAudioRecord.h>
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index abc202d..3d25a3e 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -18,7 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <media/IAudioTrack.h>
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 85b5944..dd4df99 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -17,7 +17,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <SkBitmap.h>
#include <media/IMediaMetadataRetriever.h>
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index f37519f..997251b 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -18,7 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <media/IMediaPlayer.h>
#include <ui/ISurface.h>
diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp
index 65022cd..d1f08bd 100644
--- a/media/libmedia/IMediaPlayerClient.cpp
+++ b/media/libmedia/IMediaPlayerClient.cpp
@@ -16,8 +16,8 @@
*/
#include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
#include <media/IMediaPlayerClient.h>
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 370e3fb..8fd13ae 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -17,9 +17,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <media/IMediaPlayerService.h>
#include <media/IMediaRecorder.h>
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 84d08c4..dadb38a 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "IMediaRecorder"
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <ui/ISurface.h>
#include <ui/ICamera.h>
#include <media/IMediaPlayerClient.h>
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 09afc6c..d34a8ed 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -18,8 +18,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetriever"
-#include <utils/IServiceManager.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
#include <media/mediametadataretriever.h>
#include <media/IMediaPlayerService.h>
#include <utils/Log.h>
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 809316a..0f3eb70 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -24,13 +24,13 @@
#include <unistd.h>
#include <fcntl.h>
-#include <utils/IServiceManager.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
#include <media/mediaplayer.h>
#include <media/AudioTrack.h>
-#include <utils/MemoryBase.h>
+#include <binder/MemoryBase.h>
namespace android {
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 6b26faf..0a5df0d 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -20,7 +20,7 @@
#include <utils/Log.h>
#include <ui/Surface.h>
#include <media/mediarecorder.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/String8.h>
#include <media/IMediaPlayerService.h>
#include <media/IMediaRecorder.h>
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f7f2490..0877142 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -20,6 +20,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ libbinder \
libvorbisidec \
libsonivox \
libopencore_player \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8ef0dc6..a17e651 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -30,10 +30,10 @@
#include <cutils/atomic.h>
#include <android_runtime/ActivityManager.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/MemoryBase.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
#include <cutils/properties.h>
#include <media/MediaPlayerInterface.h>
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index e0d2947..e54f20d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -25,10 +25,10 @@
#include <string.h>
#include <cutils/atomic.h>
#include <android_runtime/ActivityManager.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/MemoryBase.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
#include <media/PVMediaRecorder.h>
#include <utils/String16.h>
@@ -37,6 +37,7 @@
namespace android {
const char* cameraPermission = "android.permission.CAMERA";
+const char* recordAudioPermission = "android.permission.RECORD_AUDIO";
static bool checkPermission(const char* permissionString) {
#ifndef HAVE_ANDROID_OS
@@ -86,6 +87,9 @@
status_t MediaRecorderClient::setAudioSource(int as)
{
LOGV("setAudioSource(%d)", as);
+ if (!checkPermission(recordAudioPermission)) {
+ return PERMISSION_DENIED;
+ }
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
LOGE("recorder is not initialized");
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 6cb4a34..ba8d9a8 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -26,10 +26,10 @@
#include <string.h>
#include <cutils/atomic.h>
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
#include <android_runtime/ActivityManager.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <media/MediaMetadataRetrieverInterface.h>
#include <media/MediaPlayerInterface.h>
#include <media/PVMetadataRetriever.h>
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index ce29c98..f31f6c0 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -20,7 +20,7 @@
#include <utils.h>
#include <utils/KeyedVector.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
#include <media/MediaMetadataRetrieverInterface.h>
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index c681698..a92cea8 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -8,7 +8,8 @@
libaudioflinger \
libcameraservice \
libmediaplayerservice \
- libutils
+ libutils \
+ libbinder
base := $(LOCAL_PATH)/../..
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 6954b63..fbea0d4 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -20,9 +20,9 @@
#include <unistd.h>
#include <grp.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <AudioFlinger.h>
diff --git a/media/sdutils/sdutil.cpp b/media/sdutils/sdutil.cpp
index a9aabf0..6f0cdfb2c 100644
--- a/media/sdutils/sdutil.cpp
+++ b/media/sdutils/sdutil.cpp
@@ -15,8 +15,8 @@
*/
#include <hardware_legacy/IMountService.h>
-#include <utils/BpBinder.h>
-#include <utils/IServiceManager.h>
+#include <binder/BpBinder.h>
+#include <binder/IServiceManager.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index d0ff9ce..ac59799 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.WRITE_SDCARD" />
<application>
<uses-library android:name="android.test.runner" />
<activity android:label="@string/app_name"
diff --git a/media/tests/MediaFrameworkTest/res/raw/testmidi.mid b/media/tests/MediaFrameworkTest/res/raw/testmidi.mid
index df84e20..d4ead53 100644
--- a/media/tests/MediaFrameworkTest/res/raw/testmidi.mid
+++ b/media/tests/MediaFrameworkTest/res/raw/testmidi.mid
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3 b/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3
index 89c44b0..b7d69f8 100644
--- a/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3
+++ b/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 760b6b5..fd3a4ba 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -23,27 +23,27 @@
*
*/
public class MediaNames {
-
+ //A directory to hold all kinds of media files
+ public static final String MEDIA_SAMPLE_POOL = "/sdcard/media_api/samples/";
//Audio files
- public static final String MP3CBR = "/sdcard/media_api/music/MP3CBR.mp3";
- public static final String MP3VBR = "/sdcard/media_api/music/MP3VBR.mp3";
+ public static final String MP3CBR = "/sdcard/media_api/music/MP3_256kbps_2ch.mp3";
+ public static final String MP3VBR = "/sdcard/media_api/music/MP3_256kbps_2ch_VBR.mp3";
public static final String SHORTMP3 = "/sdcard/media_api/music/SHORTMP3.mp3";
- public static final String MIDI = "/sdcard/media_api/music/MIDI.mid";
+ public static final String MIDI = "/sdcard/media_api/music/ants.mid";
public static final String WMA9 = "/sdcard/media_api/music/WMA9.wma";
public static final String WMA10 = "/sdcard/media_api/music/WMA10.wma";
- public static final String WAV = "/sdcard/media_api/music/complicated_wav.wav";
- public static final String AMR = "/sdcard/media_api/music/AMRNB.amr";
- public static final String OGG = "/sdcard/media_api/music/Mists_of_Time-4T.ogg";
- public static final String OGGSHORT = "/sdcard/media_api/music/Skippy.ogg";
+ public static final String WAV = "/sdcard/media_api/music/rings_2ch.wav";
+ public static final String AMR = "/sdcard/media_api/music/test_amr_ietf.amr";
+ public static final String OGG = "/sdcard/media_api/music/Revelation.ogg";
- public static final int MP3CBR_LENGTH = 231116;
- public static final int MP3VBR_LENGTH = 126407;
+ public static final int MP3CBR_LENGTH = 71000;
+ public static final int MP3VBR_LENGTH = 71000;
public static final int SHORTMP3_LENGTH = 286;
- public static final int MIDI_LENGTH = 210528;
+ public static final int MIDI_LENGTH = 17000;
public static final int WMA9_LENGTH = 126559;
public static final int WMA10_LENGTH = 126559;
- public static final int AMR_LENGTH = 126540;
- public static final int OGG_LENGTH = 40000;
+ public static final int AMR_LENGTH = 37000;
+ public static final int OGG_LENGTH = 4000;
public static final int SEEK_TIME = 10000;
public static final long PAUSE_WAIT_TIME = 3000;
@@ -60,29 +60,21 @@
//public static final String VIDEO_RTSP3GP = "rtsp://193.159.241.21/sp/alizee05.3gp";
//local video
- public static final String VIDEO_MP4 = "/sdcard/media_api/video/gingerkids.MP4";
+ public static final String VIDEO_MP4 = "/sdcard/media_api/video/MPEG4_320_AAC_64.mp4";
public static final String VIDEO_LONG_3GP = "/sdcard/media_api/video/radiohead.3gp";
public static final String VIDEO_SHORT_3GP = "/sdcard/media_api/video/short.3gp";
public static final String VIDEO_LARGE_SIZE_3GP = "/sdcard/media_api/video/border_large.3gp";
- public static final String VIDEO_H263_AAC = "/sdcard/media_api/video/H263_AAC.3gp";
- public static final String VIDEO_H263_AMR = "/sdcard/media_api/video/H263_AMR.3gp";
- public static final String VIDEO_H264_AAC = "/sdcard/media_api/video/H264_AAC.3gp";
- public static final String VIDEO_H264_AMR = "/sdcard/media_api/video/H264_AMR.3gp";
+ public static final String VIDEO_H263_AAC = "/sdcard/media_api/video/H263_56_AAC_24.3gp";
+ public static final String VIDEO_H263_AMR = "/sdcard/media_api/video/H263_56_AMRNB_6.3gp";
+ public static final String VIDEO_H264_AAC = "/sdcard/media_api/video/H264_320_AAC_64.3gp";
+ public static final String VIDEO_H264_AMR = "/sdcard/media_api/video/H264_320_AMRNB_6.3gp";
public static final String VIDEO_WMV = "/sdcard/media_api/video/bugs.wmv";
- public static final String VIDEO_HIGHRES_H263 = "/sdcard/media_api/video/h263_qcif_30fps.3gp";
- public static final String VIDEO_HIGHRES_MP4 = "/sdcard/media_api/video/mpeg4_qvga_24fps.3gp";
+ public static final String VIDEO_HIGHRES_H263 = "/sdcard/media_api/video/H263_500_AMRNB_12.3gp";
+ public static final String VIDEO_HIGHRES_MP4 = "/sdcard/media_api/video/H264_500_AAC_128.3gp";
//ringtone
public static final String ringtone = "/sdcard/media_api/ringtones/F1_NewVoicemail.mp3";
-
- //streaming mp3
- public static final String STREAM_LARGE_MP3 =
- "http://wms.pv.com:7070/MediaDownloadContent/mp3/BuenaVista_04_Pueblo_Nuevo.mp3";
- public static final String STREAM_SMALL_MP3 =
- "http://wms.pv.com:7070/MediaDownloadContent/mp3/ID3V2_TestFile.mp3";
- public static final String STREAM_REGULAR_MP3 =
- "http://wms.pv.com:7070/MediaDownloadContent/mp3/ElectricCosmo.mp3";
-
+
//streaming mp3
public static final String STREAM_MP3_1 =
"http://wms.pv.com:7070/MediaDownloadContent/mp3/chadthi_jawani_128kbps.mp3";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index d9e17ea..0c0974c 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -32,8 +32,14 @@
import android.os.SystemClock;
import android.util.Log;
+import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.io.FileOutputStream;
+import java.util.Random;
/**
* Junit / Instrumentation test case for the media player api
@@ -50,8 +56,9 @@
private static final Object lock = new Object();
private static final Object prepareDone = new Object();
private static final Object videoSizeChanged = new Object();
+ private static final Object onCompletion = new Object();
private static boolean onPrepareSuccess = false;
-
+ private static boolean onCompleteSuccess = false;
public static String printCpuInfo(){
String cm = "dumpsys cpuinfo";
@@ -78,7 +85,9 @@
try{
mp.setDataSource(filePath);
mp.prepare();
- }catch (Exception e){}
+ }catch (Exception e){
+ Log.v(TAG, e.toString());
+ }
int duration = mp.getDuration();
Log.v(TAG, "Duration " + duration);
mp.release();
@@ -527,7 +536,6 @@
//Verify the thumbnail
Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
-
outputWidth = outThumbnail.getWidth();
outputHeight = outThumbnail.getHeight();
goldenHeight = goldenBitmap.getHeight();
@@ -537,15 +545,18 @@
if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight))
return false;
- //Check one line of pixel
- int x = goldenHeight/2;
- for (int j=0; j<goldenWidth; j++){
- if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)){
+ // Check half line of pixel
+ int x = goldenHeight / 2;
+ for (int j = 1; j < goldenWidth / 2; j++) {
+ if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)) {
Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j));
- return false;
+ return false;
}
- }
- }catch (Exception e){}
+ }
+ }catch (Exception e){
+ Log.v(TAG, e.toString());
+ return false;
+ }
return true;
}
@@ -725,8 +736,75 @@
}
return onPrepareSuccess;
}
-
-
-
-}
+ static MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
+ public void onCompletion(MediaPlayer mp) {
+ synchronized (onCompletion) {
+ Log.v(TAG, "notify the completion callback");
+ onCompletion.notify();
+ onCompleteSuccess = true;
+ }
+ }
+ };
+
+ // For each media file, forward twice and backward once, then play to the end
+ public static boolean playMediaSamples(String filePath) throws Exception {
+ int duration = 0;
+ int curPosition = 0;
+ int nextPosition = 0;
+ int waittime = 0;
+ Random r = new Random();
+ initializeMessageLooper();
+ synchronized (lock) {
+ try {
+ lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "looper was interrupted.");
+ return false;
+ }
+ }
+ try {
+ mMediaPlayer.setOnCompletionListener(mCompletionListener);
+ Log.v(TAG, "playMediaSamples: sample file name " + filePath);
+ mMediaPlayer.setDataSource(filePath);
+ mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+ mMediaPlayer.prepare();
+ duration = mMediaPlayer.getDuration();
+ Log.v(TAG, "playMediaSamples: duration = " + duration);
+ // start to play
+ mMediaPlayer.start();
+ // randomly play for time within (0, duration/3)
+ Thread.sleep(r.nextInt(duration/3));
+ mMediaPlayer.pause();
+ Log.v(TAG, "playMediaSamples: current position after pause: "
+ + mMediaPlayer.getCurrentPosition());
+ // seek to position (0, 2/3*duration)
+ nextPosition = mMediaPlayer.getCurrentPosition() + r.nextInt(duration/3);
+ mMediaPlayer.seekTo(nextPosition);
+ Log.v(TAG, "playMediaSamples: current position after the first seek:"
+ + mMediaPlayer.getCurrentPosition());
+ // play for another short time
+ mMediaPlayer.start();
+ Thread.sleep(r.nextInt(duration/6));
+ Log.v(TAG, "playMediaSamples: position after the second play:"
+ + mMediaPlayer.getCurrentPosition());
+ // seek to a random position (0, duration)
+ mMediaPlayer.seekTo(r.nextInt(duration));
+ Log.v(TAG, "playMediaSamples: current position after the second seek:"
+ + mMediaPlayer.getCurrentPosition());
+ waittime = duration - mMediaPlayer.getCurrentPosition();
+ synchronized(onCompletion){
+ try {
+ onCompletion.wait(waittime + 30000);
+ }catch (Exception e) {
+ Log.v(TAG, "playMediaSamples are interrupted");
+ return false;
+ }
+ }
+ terminateMessageLooper();
+ }catch (Exception e) {
+ Log.v(TAG, "playMediaSamples:" + e.getMessage());
+ }
+ return onCompleteSuccess;
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
index 8be7058..e01bd53 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -26,6 +26,8 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.Suppress;
+import java.io.File;
+
/**
* Junit / Instrumentation test case for the media player api
@@ -408,7 +410,7 @@
//Play a mid file which the duration is around 210 seconds
@LargeTest
public void testMidiResources() throws Exception {
- boolean midiResources = CodecTest.resourcesPlayback(MediaFrameworkTest.midiafd,180000);
+ boolean midiResources = CodecTest.resourcesPlayback(MediaFrameworkTest.midiafd,16000);
assertTrue("Play midi from resources", midiResources);
}
@@ -420,7 +422,7 @@
@MediumTest
public void testPrepareAsyncReset() throws Exception {
- boolean isReset = CodecTest.prepareAsyncReset(MediaNames.STREAM_LARGE_MP3);
+ boolean isReset = CodecTest.prepareAsyncReset(MediaNames.STREAM_MP3);
assertTrue("PrepareAsync Reset", isReset);
}
@@ -456,4 +458,29 @@
CodecTest.prepareAsyncCallback(MediaNames.STREAM_H264_480_360_1411k, true);
assertTrue("StreamH264PrepareAsyncCallback", onPrepareSuccess);
}
+
+ //Provide a tool to play all kinds of media files in a directory
+ @Suppress
+ @LargeTest
+ public void testMediaSamples() throws Exception {
+ // load directory files
+ boolean onCompleteSuccess = false;
+ File dir = new File(MediaNames.MEDIA_SAMPLE_POOL);
+ String[] children = dir.list();
+ if (children == null) {
+ Log.v("MediaPlayerApiTest:testMediaSamples", "dir is empty");
+ return;
+ } else {
+ for (int i = 0; i < children.length; i++) {
+ //Get filename of directory
+ String filename = children[i];
+ Log.v("MediaPlayerApiTest",
+ "testMediaSamples: file to be played: "
+ + dir + "/" + filename);
+ onCompleteSuccess =
+ CodecTest.playMediaSamples(dir + "/" + filename);
+ assertTrue("testMediaSamples", onCompleteSuccess);
+ }
+ }
+ }
}
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index b0997b1..7340357 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -890,16 +890,10 @@
cname +
" = (" +
cfunc.getArgType(cIndex).getDeclaration() +
- ") _env->GetDirectBufferAddress(" +
- (mUseCPlusPlus ? "" : "_env, ") +
+ ") getDirectBufferPointer(_env, " +
cname + "_buf);");
String iii = " ";
- out.println(iii + indent + "if ( ! " + cname + " ) {");
- out.println(iii + iii + indent +
- (mUseCPlusPlus ? "_env" : "(*_env)") +
- "->ThrowNew(" +
- (mUseCPlusPlus ? "" : "_env, ") +
- "IAEClass, \"Must use a native order direct Buffer\");");
+ out.println(iii + indent + "if ( ! " + cname + " ) {");
out.println(iii + iii + indent + "return;");
out.println(iii + indent + "}");
} else {
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index 3948fd3..e1c09f4 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -132,6 +132,19 @@
commit ? 0 : JNI_ABORT);
}
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf += position << elementSizeShift;
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ return (void*) buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 11c6087..4896acb 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -132,6 +132,19 @@
commit ? 0 : JNI_ABORT);
}
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+ char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (buf) {
+ jint position = _env->GetIntField(buffer, positionID);
+ jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+ buf += position << elementSizeShift;
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
+ return (void*) buf;
+}
+
static int
getNumCompressedTextureFormats() {
int numCompressedTextureFormats = 0;
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 275ff3a..c283418 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -31,8 +31,11 @@
<bool name="def_bluetooth_on">false</bool>
<bool name="def_install_non_market_apps">false</bool>
- <!-- Comma-separated list of providers. -->
- <string name="def_location_providers_allowed">network</string>
+ <!-- Comma-separated list of location providers.
+ Network location is off by default because it requires
+ user opt-in via Setup Wizard or Settings.
+ -->
+ <string name="def_location_providers_allowed">gps</string>
<!-- 0 == mobile, 1 == wifi. -->
<integer name="def_network_preference">1</integer>
<bool name="def_usb_mass_storage_enabled">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 28e5f9c..57f8147 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -65,7 +65,7 @@
private static final String TAG = "SettingsProvider";
private static final String DATABASE_NAME = "settings.db";
private static final int DATABASE_VERSION = 34;
-
+
private Context mContext;
public DatabaseHelper(Context context) {
@@ -81,7 +81,7 @@
");");
db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
}
-
+
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE system (" +
@@ -134,7 +134,7 @@
public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
+ currentVersion);
-
+
int upgradeVersion = oldVersion;
// Pattern for upgrade blocks:
@@ -143,7 +143,7 @@
// .. your upgrade logic..
// upgradeVersion = [the DATABASE_VERSION you set]
// }
-
+
if (upgradeVersion == 20) {
/*
* Version 21 is part of the volume control refresh. There is no
@@ -156,7 +156,7 @@
upgradeVersion = 21;
}
-
+
if (upgradeVersion < 22) {
upgradeVersion = 22;
// Upgrade the lock gesture storage location and format
@@ -186,7 +186,7 @@
}
upgradeVersion = 24;
}
-
+
if (upgradeVersion == 24) {
db.beginTransaction();
try {
@@ -213,7 +213,7 @@
}
upgradeVersion = 26;
}
-
+
if (upgradeVersion == 26) {
// This introduces the new secure settings table.
db.beginTransaction();
@@ -225,12 +225,12 @@
}
upgradeVersion = 27;
}
-
+
if (upgradeVersion == 27) {
// Copy settings values from 'system' to 'secure' and delete them from 'system'
SQLiteStatement insertStmt = null;
SQLiteStatement deleteStmt = null;
-
+
db.beginTransaction();
try {
insertStmt =
@@ -271,11 +271,11 @@
Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
};
-
+
for (String setting : settingsToMove) {
insertStmt.bindString(1, setting);
insertStmt.execute();
-
+
deleteStmt.bindString(1, setting);
deleteStmt.execute();
}
@@ -291,7 +291,7 @@
}
upgradeVersion = 28;
}
-
+
if (upgradeVersion == 28 || upgradeVersion == 29) {
// Note: The upgrade to 28 was flawed since it didn't delete the old
// setting first before inserting. Combining 28 and 29 with the
@@ -313,10 +313,10 @@
} finally {
db.endTransaction();
}
-
+
upgradeVersion = 30;
}
-
+
if (upgradeVersion == 30) {
/*
* Upgrade 31 clears the title for all quick launch shortcuts so the
@@ -373,7 +373,7 @@
}
upgradeVersion = 33;
}
-
+
if (upgradeVersion == 33) {
// Set the default zoom controls to: tap-twice to bring up +/-
db.beginTransaction();
@@ -405,7 +405,7 @@
}
private void upgradeLockPatternLocation(SQLiteDatabase db) {
- Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
+ Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
null, null, null, null);
if (c.getCount() > 0) {
c.moveToFirst();
@@ -414,7 +414,7 @@
// Convert lock pattern
try {
LockPatternUtils lpu = new LockPatternUtils(mContext.getContentResolver());
- List<LockPatternView.Cell> cellPattern =
+ List<LockPatternView.Cell> cellPattern =
LockPatternUtils.stringToPattern(lockPattern);
lpu.saveLockPattern(cellPattern);
} catch (IllegalArgumentException e) {
@@ -542,12 +542,12 @@
AudioManager.RINGER_MODE_NORMAL);
loadVibrateSetting(db, false);
-
+
// By default, only the ring/notification and system streams are affected
loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
(1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) |
(1 << AudioManager.STREAM_SYSTEM));
-
+
loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
((1 << AudioManager.STREAM_MUSIC) |
(1 << AudioManager.STREAM_RING) |
@@ -561,7 +561,7 @@
if (deleteOld) {
db.execSQL("DELETE FROM system WHERE name='" + Settings.System.VIBRATE_ON + "'");
}
-
+
SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
@@ -576,79 +576,78 @@
private void loadSettings(SQLiteDatabase db) {
loadSystemSettings(db);
- loadSecureSettings(db);
+ loadSecureSettings(db);
}
-
+
private void loadSystemSettings(SQLiteDatabase db) {
SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ " VALUES(?,?);");
-
+
Resources r = mContext.getResources();
- loadSetting(stmt, Settings.Secure.CURRENT_ACTIVE_PHONE,
- RILConstants.CDMA_PHONE);
+
loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
R.bool.def_dim_screen);
- loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
"1".equals(SystemProperties.get("ro.kernel.qemu")) ? 1 : 0);
loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
R.integer.def_screen_off_timeout);
-
+
loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
R.bool.def_airplane_mode_on);
-
+
loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
R.string.def_airplane_mode_radios);
-
+
loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
R.bool.def_auto_time); // Sync time to NITZ
-
+
loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
R.integer.def_screen_brightness);
-
+
loadDefaultAnimationSettings(stmt);
loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
R.bool.def_accelerometer_rotation);
-
+
// Default date format based on build
loadSetting(stmt, Settings.System.DATE_FORMAT,
- SystemProperties.get("ro.com.android.dateformat",
+ SystemProperties.get("ro.com.android.dateformat",
"MM-dd-yyyy"));
stmt.close();
}
-
+
private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
loadFractionSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE,
R.fraction.def_window_animation_scale, 1);
loadFractionSetting(stmt, Settings.System.TRANSITION_ANIMATION_SCALE,
R.fraction.def_window_transition_scale, 1);
}
-
+
private void loadSecureSettings(SQLiteDatabase db) {
SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+ " VALUES(?,?);");
-
+
loadBooleanSetting(stmt, Settings.Secure.BLUETOOTH_ON,
R.bool.def_bluetooth_on);
-
+
// Data roaming default, based on build
- loadSetting(stmt, Settings.Secure.DATA_ROAMING,
+ loadSetting(stmt, Settings.Secure.DATA_ROAMING,
"true".equalsIgnoreCase(
- SystemProperties.get("ro.com.android.dataroaming",
- "false")) ? 1 : 0);
-
+ SystemProperties.get("ro.com.android.dataroaming",
+ "false")) ? 1 : 0);
+
loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
R.bool.def_install_non_market_apps);
-
+
loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
R.string.def_location_providers_allowed);
-
+
loadIntegerSetting(stmt, Settings.Secure.NETWORK_PREFERENCE,
R.integer.def_network_preference);
-
+
loadBooleanSetting(stmt, Settings.Secure.USB_MASS_STORAGE_ENABLED,
R.bool.def_usb_mass_storage_enabled);
-
+
loadBooleanSetting(stmt, Settings.Secure.WIFI_ON,
R.bool.def_wifi_on);
loadBooleanSetting(stmt, Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
@@ -660,25 +659,26 @@
}
// Set the preferred network mode to 0 = Global, CDMA default
- loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE,
+ int type = SystemProperties.getInt("ro.telephony.default_network",
RILConstants.PREFERRED_NETWORK_MODE);
+ loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
// Enable or disable Cell Broadcast SMS
loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
// Set the preferred cdma subscription to 0 = Subscription from RUIM, when available
- loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
+ loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
// Don't do this. The SystemServer will initialize ADB_ENABLED from a
// persistent system property instead.
//loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
-
+
// Allow mock locations default, based on build
- loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
+ loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
"1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
-
+
stmt.close();
}
@@ -687,24 +687,23 @@
stmt.bindString(2, value.toString());
stmt.execute();
}
-
+
private void loadStringSetting(SQLiteStatement stmt, String key, int resid) {
loadSetting(stmt, key, mContext.getResources().getString(resid));
}
-
+
private void loadBooleanSetting(SQLiteStatement stmt, String key, int resid) {
loadSetting(stmt, key,
mContext.getResources().getBoolean(resid) ? "1" : "0");
}
-
+
private void loadIntegerSetting(SQLiteStatement stmt, String key, int resid) {
loadSetting(stmt, key,
Integer.toString(mContext.getResources().getInteger(resid)));
}
-
+
private void loadFractionSetting(SQLiteStatement stmt, String key, int resid, int base) {
loadSetting(stmt, key,
Float.toString(mContext.getResources().getFraction(resid, base, base)));
}
}
-
diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
index 2326b46..9992420 100644
--- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
+++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
@@ -60,7 +60,7 @@
"android.intent.extra.from_trusted_server", false);
if (fromTrustedServer) {
String accountName = intent.getStringExtra("account");
- String token = intent.getStringExtra("message_token");
+ String token = intent.getStringExtra(Intent.EXTRA_REMOTE_INTENT_TOKEN);
if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(token)) {
if (Config.LOGD) {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 983329b..e3fff81 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -158,11 +158,13 @@
case MSG_RUN_BACKUP:
// snapshot the pending-backup set and work on that
synchronized (mQueueLock) {
- mBackupQueue = new ArrayList();
- for (BackupRequest b: mPendingBackups.values()) {
- mBackupQueue.add(b);
+ if (mBackupQueue == null) {
+ mBackupQueue = new ArrayList();
+ for (BackupRequest b: mPendingBackups.values()) {
+ mBackupQueue.add(b);
+ }
+ mPendingBackups = new HashMap<ComponentName,BackupRequest>();
}
- mPendingBackups = new HashMap<ComponentName,BackupRequest>();
// !!! TODO: start a new backup-queue journal file too
// WARNING: If we crash after this line, anything in mPendingBackups will
// be lost. FIX THIS.
@@ -190,9 +192,13 @@
BackupRequest request;
synchronized (mQueueLock) {
int queueSize = mBackupQueue.size();
+ Log.d(TAG, "mBackupQueue.size=" + queueSize);
if (queueSize == 0) {
mBackupQueue = null;
- // TODO: Anything else to do here?
+ // if there are pending backups, start those after a short delay
+ if (mPendingBackups.size() > 0) {
+ mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
+ }
return;
}
request = mBackupQueue.get(0);
@@ -267,7 +273,7 @@
// !!! TODO: After successful transport, delete the now-stale data
// and juggle the files so that next time the new state is passed
- backupDataName.delete();
+ //backupDataName.delete();
newStateName.renameTo(savedStateName);
} catch (FileNotFoundException fnf) {
@@ -284,6 +290,9 @@
mBackupQueue.remove(0);
}
mContext.unbindService(mBackupHandler);
+
+ // start the next one
+ startOneService();
}
// Add the backup services in the given package to our set of known backup participants.
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index caad7d0..596053d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -271,6 +271,7 @@
* - is not plugged and battery level crosses the WARNING boundary (becomes < 15).
*/
final boolean sendBatteryLow = !plugged
+ && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mBatteryLevel < BATTERY_LEVEL_WARNING
&& (oldPlugged || mLastBatteryLevel >= BATTERY_LEVEL_WARNING);
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 7b8a2a4..9c1f942 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -63,7 +63,7 @@
yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
}
- MotionEvent generateMotion(InputDevice device, long curTime,
+ MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano,
boolean isAbs, Display display, int orientation,
int metaState) {
if (!changed) {
@@ -167,7 +167,7 @@
if (!isAbs) {
x = y = 0;
}
- return MotionEvent.obtain(downTime, curTime, action,
+ return MotionEvent.obtainNano(downTime, curTime, curTimeNano, action,
scaledX, scaledY, scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
} else {
@@ -181,7 +181,7 @@
}
return null;
}
- MotionEvent me = MotionEvent.obtain(downTime, curTime,
+ MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano,
MotionEvent.ACTION_MOVE, scaledX, scaledY,
scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index 53e63c2..d8c8c90 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -180,8 +180,7 @@
return resultList;
}
- public List<R> queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 411cd6b..78cdf8b 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -18,8 +18,9 @@
import android.content.Context;
import android.content.res.Configuration;
-import android.os.SystemClock;
+import android.os.LatencyTimer;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -73,14 +74,17 @@
public static final int FILTER_REMOVE = 0;
public static final int FILTER_KEEP = 1;
public static final int FILTER_ABORT = -1;
-
+
+ private static final boolean MEASURE_LATENCY = false;
+ private LatencyTimer lt;
+
public interface FilterCallback {
int filterEvent(QueuedEvent ev);
}
static class QueuedEvent {
InputDevice inputDevice;
- long when;
+ long whenNano;
int flags; // From the raw event
int classType; // One of the class constants in InputEvent
Object event;
@@ -88,7 +92,7 @@
void copyFrom(QueuedEvent that) {
this.inputDevice = that.inputDevice;
- this.when = that.when;
+ this.whenNano = that.whenNano;
this.flags = that.flags;
this.classType = that.classType;
this.event = that.event;
@@ -107,6 +111,10 @@
}
KeyInputQueue(Context context) {
+ if (MEASURE_LATENCY) {
+ lt = new LatencyTimer(100, 1000);
+ }
+
PowerManager pm = (PowerManager)context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -241,7 +249,7 @@
if (configChanged) {
synchronized (mFirst) {
- addLocked(di, SystemClock.uptimeMillis(), 0,
+ addLocked(di, System.nanoTime(), 0,
RawInputEvent.CLASS_CONFIGURATION_CHANGED,
null);
}
@@ -256,6 +264,7 @@
// timebase as SystemClock.uptimeMillis().
//curTime = gotOne ? ev.when : SystemClock.uptimeMillis();
final long curTime = SystemClock.uptimeMillis();
+ final long curTimeNano = System.nanoTime();
//Log.i(TAG, "curTime=" + curTime + ", systemClock=" + SystemClock.uptimeMillis());
final int classes = di.classes;
@@ -276,7 +285,7 @@
down = false;
}
int keycode = rotateKeyCodeLocked(ev.keycode);
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_KEYBOARD,
newKeyEvent(di, di.mDownTime, curTime, down,
keycode, 0, scancode,
@@ -330,7 +339,7 @@
}
MotionEvent me;
- me = di.mAbs.generateMotion(di, curTime, true,
+ me = di.mAbs.generateMotion(di, curTime, curTimeNano, true,
mDisplay, mOrientation, mGlobalMetaState);
if (false) Log.v(TAG, "Absolute: x=" + di.mAbs.x
+ " y=" + di.mAbs.y + " ev=" + me);
@@ -338,15 +347,15 @@
if (WindowManagerPolicy.WATCH_POINTER) {
Log.i(TAG, "Enqueueing: " + me);
}
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_TOUCHSCREEN, me);
}
- me = di.mRel.generateMotion(di, curTime, false,
+ me = di.mRel.generateMotion(di, curTime, curTimeNano, false,
mDisplay, mOrientation, mGlobalMetaState);
if (false) Log.v(TAG, "Relative: x=" + di.mRel.x
+ " y=" + di.mRel.y + " ev=" + me);
if (me != null) {
- addLocked(di, curTime, ev.flags,
+ addLocked(di, curTimeNano, ev.flags,
RawInputEvent.CLASS_TRACKBALL, me);
}
}
@@ -530,7 +539,7 @@
}
}
- private QueuedEvent obtainLocked(InputDevice device, long when,
+ private QueuedEvent obtainLocked(InputDevice device, long whenNano,
int flags, int classType, Object event) {
QueuedEvent ev;
if (mCacheCount == 0) {
@@ -542,7 +551,7 @@
mCacheCount--;
}
ev.inputDevice = device;
- ev.when = when;
+ ev.whenNano = whenNano;
ev.flags = flags;
ev.classType = classType;
ev.event = event;
@@ -561,13 +570,13 @@
}
}
- private void addLocked(InputDevice device, long when, int flags,
+ private void addLocked(InputDevice device, long whenNano, int flags,
int classType, Object event) {
boolean poke = mFirst.next == mLast;
- QueuedEvent ev = obtainLocked(device, when, flags, classType, event);
+ QueuedEvent ev = obtainLocked(device, whenNano, flags, classType, event);
QueuedEvent p = mLast.prev;
- while (p != mFirst && ev.when < p.when) {
+ while (p != mFirst && ev.whenNano < p.whenNano) {
p = p.prev;
}
@@ -578,8 +587,15 @@
ev.inQueue = true;
if (poke) {
+ long time;
+ if (MEASURE_LATENCY) {
+ time = System.nanoTime();
+ }
mFirst.notify();
mWakeLock.acquire();
+ if (MEASURE_LATENCY) {
+ lt.sample("1 addLocked-queued event ", System.nanoTime() - time);
+ }
}
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 05888e0..147a085 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -46,7 +46,6 @@
import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
-import android.location.ILocationCollector;
import android.location.ILocationListener;
import android.location.ILocationManager;
import android.location.ILocationProvider;
@@ -107,8 +106,6 @@
android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
private static final String INSTALL_LOCATION_PROVIDER =
android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
- private static final String INSTALL_LOCATION_COLLECTOR =
- android.Manifest.permission.INSTALL_LOCATION_COLLECTOR;
// Set of providers that are explicitly enabled
private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -171,9 +168,6 @@
private HashMap<String,Location> mLastKnownLocation =
new HashMap<String,Location>();
- // Location collector
- private ILocationCollector mCollector;
-
private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
// for Settings change notification
@@ -630,16 +624,6 @@
}
}
- public void installLocationCollector(ILocationCollector collector) {
- if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_COLLECTOR)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires INSTALL_LOCATION_COLLECTOR permission");
- }
-
- // FIXME - only support one collector
- mCollector = collector;
- }
-
public void installGeocodeProvider(IGeocodeProvider provider) {
if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
!= PackageManager.PERMISSION_GRANTED) {
@@ -1619,23 +1603,19 @@
synchronized (mLock) {
Location location = (Location) msg.obj;
+ String provider = location.getProvider();
- if (mCollector != null &&
- LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
- try {
- mCollector.updateLocation(location);
- } catch (RemoteException e) {
- Log.w(TAG, "mCollector.updateLocation failed");
- mCollector = null;
+ // notify other providers of the new location
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderProxy proxy = mProviders.get(i);
+ if (!provider.equals(proxy.getName())) {
+ proxy.updateLocation(location);
}
}
- String provider = location.getProvider();
- if (!isAllowedBySettingsLocked(provider)) {
- return;
+ if (isAllowedBySettingsLocked(provider)) {
+ handleLocationChangedLocked(location);
}
-
- handleLocationChangedLocked(location);
}
}
} catch (Exception e) {
@@ -1935,7 +1915,6 @@
synchronized (mLock) {
pw.println("Current Location Manager state:");
pw.println(" sProvidersLoaded=" + sProvidersLoaded);
- pw.println(" mCollector=" + mCollector);
pw.println(" Listeners:");
int N = mReceivers.size();
for (int i=0; i<N; i++) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5194aea..1cfe002 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -1270,8 +1270,7 @@
synchronized (mPackages) {
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
List<PreferredActivity> prefs =
- mSettings.mPreferredActivities.queryIntent(null,
- intent, resolvedType,
+ mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
if (prefs != null && prefs.size() > 0) {
// First figure out how good the original match set is.
@@ -1348,7 +1347,7 @@
synchronized (mPackages) {
return (List<ResolveInfo>)mActivities.
- queryIntent(null, intent, resolvedType, flags);
+ queryIntent(intent, resolvedType, flags);
}
}
@@ -1517,7 +1516,7 @@
String resolvedType, int flags) {
synchronized (mPackages) {
return (List<ResolveInfo>)mReceivers.
- queryIntent(null, intent, resolvedType, flags);
+ queryIntent(intent, resolvedType, flags);
}
}
@@ -1550,8 +1549,7 @@
}
synchronized (mPackages) {
- return (List<ResolveInfo>)mServices.
- queryIntent(null, intent, resolvedType, flags);
+ return (List<ResolveInfo>)mServices.queryIntent(intent, resolvedType, flags);
}
}
@@ -2831,6 +2829,21 @@
// we can't add any new permissions to it.
if (!gp.loadedPermissions.contains(perm)) {
allowed = false;
+ // Except... if this is a permission that was added
+ // to the platform (note: need to only do this when
+ // updating the platform).
+ final int NP = PackageParser.NEW_PERMISSIONS.length;
+ for (int ip=0; ip<NP; ip++) {
+ final PackageParser.NewPermissionInfo npi
+ = PackageParser.NEW_PERMISSIONS[ip];
+ if (npi.name.equals(perm)
+ && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
+ allowed = true;
+ Log.i(TAG, "Auto-granting WRITE_SDCARD to old pkg "
+ + pkg.packageName);
+ break;
+ }
+ }
}
}
if (allowed) {
@@ -2869,17 +2882,14 @@
private final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly);
}
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, int flags) {
+ public List queryIntent(Intent intent, String resolvedType, int flags) {
mFlags = flags;
- return super.queryIntent(
- resolver, intent, resolvedType,
+ return super.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
}
@@ -2893,8 +2903,13 @@
int N = packageActivities.size();
ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
+
+ ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
for (int i = 0; i < N; ++i) {
- listCut.add(packageActivities.get(i).intents);
+ intentFilters = packageActivities.get(i).intents;
+ if (intentFilters != null && intentFilters.size() > 0) {
+ listCut.add(intentFilters);
+ }
}
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
}
@@ -3013,17 +3028,14 @@
private final class ServiceIntentResolver
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, boolean defaultOnly) {
+ public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(resolver, intent, resolvedType, defaultOnly);
+ return super.queryIntent(intent, resolvedType, defaultOnly);
}
- public List queryIntent(ContentResolver resolver, Intent intent,
- String resolvedType, int flags) {
+ public List queryIntent(Intent intent, String resolvedType, int flags) {
mFlags = flags;
- return super.queryIntent(
- resolver, intent, resolvedType,
+ return super.queryIntent(intent, resolvedType,
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
}
@@ -3589,7 +3601,9 @@
} else {
// Re installation failed. Restore old information
// Remove new pkg information
- removePackageLI(newPackage, true);
+ if (newPackage != null) {
+ removePackageLI(newPackage, true);
+ }
// Add back the old system package
scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
oldPkgSetting.resourcePath,
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index fa54421..88f47fd 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -26,6 +26,7 @@
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -39,48 +40,64 @@
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.DefaultPhoneNotifier;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneStateIntentReceiver;
import com.android.internal.telephony.TelephonyIntents;
import com.android.server.am.BatteryStatsService;
-
/**
- * Since phone process can be restarted, this class provides a centralized
- * place that applications can register and be called back from.
+ * Since phone process can be restarted, this class provides a centralized place
+ * that applications can register and be called back from.
*/
class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static final String TAG = "TelephonyRegistry";
private static class Record {
String pkgForDebug;
+
IBinder binder;
+
IPhoneStateListener callback;
+
int events;
}
private final Context mContext;
+
private final ArrayList<Record> mRecords = new ArrayList();
+
private final IBatteryStats mBatteryStats;
private int mCallState = TelephonyManager.CALL_STATE_IDLE;
+
private String mCallIncomingNumber = "";
+
private ServiceState mServiceState = new ServiceState();
- private int mSignalStrength = -1;
+
+ private SignalStrength mSignalStrength = new SignalStrength();
+
private boolean mMessageWaiting = false;
+
private boolean mCallForwarding = false;
+
private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
+
private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
+
private boolean mDataConnectionPossible = false;
+
private String mDataConnectionReason = "";
+
private String mDataConnectionApn = "";
+
private String mDataConnectionInterfaceName = "";
+
private Bundle mCellLocation = new Bundle();
- // we keep a copy of all of the sate so we can send it out when folks register for it
+ // we keep a copy of all of the state so we can send it out when folks
+ // register for it
//
- // In these calls we call with the lock held. This is safe becasuse remote
- // calls go through a oneway interface and local calls going through a handler before
- // they get to app code.
+ // In these calls we call with the lock held. This is safe becasuse remote
+ // calls go through a oneway interface and local calls going through a
+ // handler before they get to app code.
TelephonyRegistry(Context context) {
CellLocation.getEmpty().fillInNotifierBundle(mCellLocation);
@@ -90,13 +107,18 @@
public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) {
- //Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events));
+ // Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
+ // Integer.toHexString(events));
if (events != 0) {
// check permissions
if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
+ // ACCESS_FINE_LOCATION implies ACCESS_COARSE_LOCATION
+ if (mContext.checkCallingPermission(
+ android.Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
+ }
}
synchronized (mRecords) {
@@ -105,7 +127,7 @@
find_and_add: {
IBinder b = callback.asBinder();
final int N = mRecords.size();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
r = mRecords.get(i);
if (b == r.binder) {
break find_and_add;
@@ -125,7 +147,9 @@
}
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- r.callback.onSignalStrengthChanged(mSignalStrength);
+ int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -168,6 +192,13 @@
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+ try {
+ r.callback.onSignalStrengthsChanged(mSignalStrength);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -177,8 +208,8 @@
private void remove(IBinder binder) {
synchronized (mRecords) {
- final int N = mRecords.size();
- for (int i=0; i<N; i++) {
+ final int recordCount = mRecords.size();
+ for (int i = 0; i < recordCount; i++) {
if (mRecords.get(i).binder == binder) {
mRecords.remove(i);
return;
@@ -194,8 +225,7 @@
synchronized (mRecords) {
mCallState = state;
mCallIncomingNumber = incomingNumber;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
try {
@@ -212,11 +242,10 @@
public void notifyServiceState(ServiceState state) {
if (!checkPhoneStatePermission("notifyServiceState()")) {
return;
- }
+ }
synchronized (mRecords) {
mServiceState = state;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
sendServiceState(r, state);
@@ -226,35 +255,38 @@
broadcastServiceStateChanged(state);
}
- public void notifySignalStrength(int signalStrengthASU) {
+ public void notifySignalStrength(SignalStrength signalStrength) {
if (!checkPhoneStatePermission("notifySignalStrength()")) {
return;
- }
+ }
synchronized (mRecords) {
- mSignalStrength = signalStrengthASU;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ mSignalStrength = signalStrength;
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
+ if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+ sendSignalStrength(r, signalStrength);
+ }
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- r.callback.onSignalStrengthChanged(signalStrengthASU);
+ int gsmSignalStrength = signalStrength.getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
}
- broadcastSignalStrengthChanged(signalStrengthASU);
+ broadcastSignalStrengthChanged(signalStrength);
}
public void notifyMessageWaitingChanged(boolean mwi) {
if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
return;
- }
+ }
synchronized (mRecords) {
mMessageWaiting = mwi;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
try {
@@ -270,11 +302,10 @@
public void notifyCallForwardingChanged(boolean cfi) {
if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
return;
- }
+ }
synchronized (mRecords) {
mCallForwarding = cfi;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
try {
@@ -290,11 +321,10 @@
public void notifyDataActivity(int state) {
if (!checkPhoneStatePermission("notifyDataActivity()")) {
return;
- }
+ }
synchronized (mRecords) {
mDataActivity = state;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
try {
@@ -307,19 +337,18 @@
}
}
- public void notifyDataConnection(int state, boolean isDataConnectivityPissible,
- String reason, String apn, String interfaceName) {
+ public void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason,
+ String apn, String interfaceName) {
if (!checkPhoneStatePermission("notifyDataConnection()")) {
return;
- }
+ }
synchronized (mRecords) {
mDataConnectionState = state;
- mDataConnectionPossible = isDataConnectivityPissible;
+ mDataConnectionPossible = isDataConnectivityPossible;
mDataConnectionReason = reason;
mDataConnectionApn = apn;
mDataConnectionInterfaceName = interfaceName;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
try {
@@ -330,17 +359,17 @@
}
}
}
- broadcastDataConnectionStateChanged(state, isDataConnectivityPissible,
- reason, apn, interfaceName);
+ broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
+ interfaceName);
}
public void notifyDataConnectionFailed(String reason) {
if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
return;
- }
+ }
/*
* This is commented out because there is on onDataConnectionFailed callback
- * on PhoneStateListener. There should be.
+ * on PhoneStateListener. There should be
synchronized (mRecords) {
mDataConnectionFailedReason = reason;
final int N = mRecords.size();
@@ -358,11 +387,10 @@
public void notifyCellLocation(Bundle cellLocation) {
if (!checkPhoneStatePermission("notifyCellLocation()")) {
return;
- }
+ }
synchronized (mRecords) {
mCellLocation = cellLocation;
- final int N = mRecords.size();
- for (int i=N-1; i>=0; i--) {
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
sendCellLocation(r, cellLocation);
@@ -371,12 +399,10 @@
}
}
- //
- // the new callback broadcasting
- //
- // copy the service state object so they can't mess it up in the local calls
- //
- public void sendServiceState(Record r, ServiceState state) {
+ /**
+ * Copy the service state object so they can't mess it up in the local calls
+ */
+ private void sendServiceState(Record r, ServiceState state) {
try {
r.callback.onServiceStateChanged(new ServiceState(state));
} catch (RemoteException ex) {
@@ -384,7 +410,7 @@
}
}
- public void sendCellLocation(Record r, Bundle cellLocation) {
+ private void sendCellLocation(Record r, Bundle cellLocation) {
try {
r.callback.onCellLocationChanged(new Bundle(cellLocation));
} catch (RemoteException ex) {
@@ -392,18 +418,24 @@
}
}
+ private void sendSignalStrength(Record r, SignalStrength signalStrength) {
+ try {
+ r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump telephony.registry from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
return;
}
synchronized (mRecords) {
- final int N = mRecords.size();
+ final int recordCount = mRecords.size();
pw.println("last known state:");
pw.println(" mCallState=" + mCallState);
pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
@@ -418,15 +450,14 @@
pw.println(" mDataConnectionApn=" + mDataConnectionApn);
pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
pw.println(" mCellLocation=" + mCellLocation);
- pw.println("registrations: count=" + N);
- for (int i=0; i<N; i++) {
+ pw.println("registrations: count=" + recordCount);
+ for (int i = 0; i < recordCount; i++) {
Record r = mRecords.get(i);
pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
}
}
}
-
//
// the legacy intent broadcasting
//
@@ -439,17 +470,20 @@
mContext.sendStickyBroadcast(intent);
}
- private void broadcastSignalStrengthChanged(int asu) {
+ private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
long ident = Binder.clearCallingIdentity();
try {
- mBatteryStats.notePhoneSignalStrength(asu);
+ mBatteryStats.notePhoneSignalStrength(signalStrength);
} catch (RemoteException e) {
+ /* The remote entity disappeared, we can safely ignore the exception. */
} finally {
Binder.restoreCallingIdentity(ident);
}
-
+
Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
- intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu);
+ Bundle data = new Bundle();
+ signalStrength.fillInNotifierBundle(data);
+ intent.putExtras(data);
mContext.sendStickyBroadcast(intent);
}
@@ -462,13 +496,13 @@
mBatteryStats.notePhoneOn();
}
} catch (RemoteException e) {
+ /* The remote entity disappeared, we can safely ignore the exception. */
} finally {
Binder.restoreCallingIdentity(ident);
}
-
+
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- intent.putExtra(Phone.STATE_KEY,
- DefaultPhoneNotifier.convertCallState(state).toString());
+ intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
}
@@ -498,15 +532,14 @@
intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
mContext.sendStickyBroadcast(intent);
}
-
+
private boolean checkPhoneStatePermission(String method) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
String msg = "Modify Phone State Permission Denial: " + method + " from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid();
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Log.w(TAG, msg);
return false;
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 348f0a1..5fa8701 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,8 +96,8 @@
private int mScanLocksAcquired;
private int mScanLocksReleased;
- private final List<WifiMulticaster> mMulticasters =
- new ArrayList<WifiMulticaster>();
+ private final List<Multicaster> mMulticasters =
+ new ArrayList<Multicaster>();
private int mMulticastEnabled;
private int mMulticastDisabled;
@@ -1449,10 +1449,12 @@
Settings.System.getInt(mContext.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ Log.d(TAG, "ACTION_SCREEN_ON");
mAlarmManager.cancel(mIdleIntent);
mDeviceIdle = false;
mScreenOff = false;
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ Log.d(TAG, "ACTION_SCREEN_OFF");
mScreenOff = true;
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1461,12 +1463,20 @@
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
- long triggerTime = System.currentTimeMillis() + idleMillis;
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ if (!mWifiStateTracker.hasIpAddress()) {
+ // do not keep Wifi awake when screen is off if Wifi is not fully active
+ mDeviceIdle = true;
+ updateWifiState();
+ } else {
+ long triggerTime = System.currentTimeMillis() + idleMillis;
+ Log.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ }
}
/* we can return now -- there's nothing to do until we get the idle intent back */
return;
} else if (action.equals(ACTION_DEVICE_IDLE)) {
+ Log.d(TAG, "got ACTION_DEVICE_IDLE");
mDeviceIdle = true;
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
/*
@@ -1477,9 +1487,11 @@
* the already-set timer.
*/
int pluggedType = intent.getIntExtra("plugged", 0);
+ Log.d(TAG, "ACTION_BATTERY_CHANGED pluggedType: " + pluggedType);
if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
!shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
long triggerTime = System.currentTimeMillis() + idleMillis;
+ Log.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
mPluggedType = pluggedType;
return;
@@ -1732,7 +1744,7 @@
}
}
- private class WifiLock extends WifiDeathRecipient {
+ private class WifiLock extends DeathRecipient {
WifiLock(int lockMode, String tag, IBinder binder) {
super(lockMode, tag, binder);
}
@@ -1875,13 +1887,13 @@
return hadLock;
}
- private abstract class WifiDeathRecipient
+ private abstract class DeathRecipient
implements IBinder.DeathRecipient {
String mTag;
int mMode;
IBinder mBinder;
- WifiDeathRecipient(int mode, String tag, IBinder binder) {
+ DeathRecipient(int mode, String tag, IBinder binder) {
super();
mTag = tag;
mMode = mode;
@@ -1894,13 +1906,13 @@
}
}
- private class WifiMulticaster extends WifiDeathRecipient {
- WifiMulticaster(String tag, IBinder binder) {
+ private class Multicaster extends DeathRecipient {
+ Multicaster(String tag, IBinder binder) {
super(Binder.getCallingUid(), tag, binder);
}
public void binderDied() {
- Log.e(TAG, "WifiMulticaster binderDied");
+ Log.e(TAG, "Multicaster binderDied");
synchronized (mMulticasters) {
int i = mMulticasters.indexOf(this);
if (i != -1) {
@@ -1910,7 +1922,7 @@
}
public String toString() {
- return "WifiMulticaster{" + mTag + " binder=" + mBinder + "}";
+ return "Multicaster{" + mTag + " binder=" + mBinder + "}";
}
public int getUid() {
@@ -1918,12 +1930,12 @@
}
}
- public void enableWifiMulticast(IBinder binder, String tag) {
+ public void enableMulticast(IBinder binder, String tag) {
enforceChangePermission();
synchronized (mMulticasters) {
mMulticastEnabled++;
- mMulticasters.add(new WifiMulticaster(tag, binder));
+ mMulticasters.add(new Multicaster(tag, binder));
// Note that we could call stopPacketFiltering only when
// our new size == 1 (first call), but this function won't
// be called often and by making the stopPacket call each
@@ -1941,7 +1953,7 @@
}
}
- public void disableWifiMulticast() {
+ public void disableMulticast() {
enforceChangePermission();
int uid = Binder.getCallingUid();
@@ -1949,7 +1961,7 @@
mMulticastDisabled++;
int size = mMulticasters.size();
for (int i = size - 1; i >= 0; i--) {
- WifiMulticaster m = mMulticasters.get(i);
+ Multicaster m = mMulticasters.get(i);
if ((m != null) && (m.getUid() == uid)) {
removeMulticasterLocked(i, uid);
}
@@ -1973,7 +1985,7 @@
}
}
- public boolean isWifiMulticastEnabled() {
+ public boolean isMulticastEnabled() {
enforceAccessPermission();
synchronized (mMulticasters) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3fa5baf..4561e1a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -63,6 +63,7 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.LatencyTimer;
import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
@@ -133,7 +134,9 @@
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_REORDER = false;
static final boolean SHOW_TRANSACTIONS = false;
-
+ static final boolean MEASURE_LATENCY = false;
+ static private LatencyTimer lt;
+
static final boolean PROFILE_ORIENTATION = false;
static final boolean BLUR = true;
static final boolean localLOGV = DEBUG;
@@ -495,6 +498,10 @@
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
+ if (MEASURE_LATENCY) {
+ lt = new LatencyTimer(100, 1000);
+ }
+
mContext = context;
mHaveInputMethods = haveInputMethods;
mLimitedAlphaCompositing = context.getResources().getBoolean(
@@ -1300,7 +1307,6 @@
mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
}
}
-
if (localLOGV) Log.v(
TAG, "New client " + client.asBinder()
+ ": window=" + win);
@@ -3715,7 +3721,7 @@
private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
long curTime = SystemClock.uptimeMillis();
- if (eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
+ if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
if (mLastTouchEventType == eventType &&
(curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
return;
@@ -3775,9 +3781,17 @@
if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
"dispatchPointer " + ev);
+ if (MEASURE_LATENCY) {
+ lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
+ }
+
Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
ev, true, false);
+ if (MEASURE_LATENCY) {
+ lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
+ }
+
int action = ev.getAction();
if (action == MotionEvent.ACTION_UP) {
@@ -3814,6 +3828,7 @@
WindowState target = (WindowState)targetObj;
final long eventTime = ev.getEventTime();
+ final long eventTimeNano = ev.getEventTimeNano();
//Log.i(TAG, "Sending " + ev + " to " + target);
@@ -3832,6 +3847,10 @@
}
}
+ if (MEASURE_LATENCY) {
+ lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
+ }
+
if ((target.mAttrs.flags &
WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
//target wants to ignore fat touch events
@@ -3914,6 +3933,10 @@
}
}
+ if (MEASURE_LATENCY) {
+ lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
+ }
+
synchronized(mWindowMap) {
if (qev != null && action == MotionEvent.ACTION_MOVE) {
mKeyWaiter.bindTargetWindowLocked(target,
@@ -3951,7 +3974,16 @@
if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Log.v(TAG, "Delivering pointer " + qev + " to " + target);
}
+
+ if (MEASURE_LATENCY) {
+ lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
+ }
+
target.mClient.dispatchPointer(ev, eventTime);
+
+ if (MEASURE_LATENCY) {
+ lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
+ }
return true;
} catch (android.os.RemoteException e) {
Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
@@ -5072,7 +5104,7 @@
}
}
}
- };
+ }
public boolean detectSafeMode() {
mSafeMode = mPolicy.detectSafeMode();
@@ -5137,9 +5169,13 @@
if (DEBUG_INPUT && ev != null) Log.v(
TAG, "Event: type=" + ev.classType + " data=" + ev.event);
+ if (MEASURE_LATENCY) {
+ lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
+ }
+
try {
if (ev != null) {
- curTime = ev.when;
+ curTime = SystemClock.uptimeMillis();
int eventType;
if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
eventType = eventType((MotionEvent)ev.event);
@@ -5150,17 +5186,29 @@
eventType = LocalPowerManager.OTHER_EVENT;
}
try {
- long now = SystemClock.uptimeMillis();
-
- if ((now - mLastBatteryStatsCallTime)
+ if ((curTime - mLastBatteryStatsCallTime)
>= MIN_TIME_BETWEEN_USERACTIVITIES) {
- mLastBatteryStatsCallTime = now;
+ mLastBatteryStatsCallTime = curTime;
mBatteryStats.noteInputEvent();
}
} catch (RemoteException e) {
// Ignore
}
- mPowerManager.userActivity(curTime, false, eventType, false);
+
+ if (eventType != TOUCH_EVENT
+ && eventType != LONG_TOUCH_EVENT
+ && eventType != CHEEK_EVENT) {
+ mPowerManager.userActivity(curTime, false,
+ eventType, false);
+ } else if (mLastTouchEventType != eventType
+ || (curTime - mLastUserActivityCallTime)
+ >= MIN_TIME_BETWEEN_USERACTIVITIES) {
+ mLastUserActivityCallTime = curTime;
+ mLastTouchEventType = eventType;
+ mPowerManager.userActivity(curTime, false,
+ eventType, false);
+ }
+
switch (ev.classType) {
case RawInputEvent.CLASS_KEYBOARD:
KeyEvent ke = (KeyEvent)ev.event;
@@ -7732,7 +7780,6 @@
int i;
// FIRST LOOP: Perform a layout, if needed.
-
performLayoutLockedInner();
if (mFxSession == null) {
@@ -7752,7 +7799,6 @@
}
// SECOND LOOP: Execute animations and update visibility of windows.
-
boolean orientationChangeComplete = true;
Session holdScreen = null;
float screenBrightness = -1;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9471eff..f2959e3 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -30,6 +30,7 @@
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.AlertDialog;
+import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IActivityWatcher;
import android.app.IApplicationThread;
@@ -41,6 +42,7 @@
import android.app.Instrumentation;
import android.app.PendingIntent;
import android.app.ResultInfo;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -78,10 +80,14 @@
import android.os.SystemProperties;
import android.provider.Checkin;
import android.provider.Settings;
+import android.server.data.CrashData;
+import android.server.data.StackTraceElementData;
+import android.server.data.ThrowableData;
import android.text.TextUtils;
import android.util.Config;
import android.util.EventLog;
import android.util.Log;
+import android.util.LogPrinter;
import android.util.PrintWriterPrinter;
import android.util.SparseArray;
import android.view.Gravity;
@@ -92,10 +98,13 @@
import dalvik.system.Zygote;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
@@ -191,6 +200,10 @@
// Maximum number of recent tasks that we can remember.
static final int MAX_RECENT_TASKS = 20;
+ // Amount of time after a call to stopAppSwitches() during which we will
+ // prevent further untrusted switches from happening.
+ static final long APP_SWITCH_DELAY_TIME = 5*1000;
+
// How long until we reset a task when the user returns to it. Currently
// 30 minutes.
static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
@@ -328,6 +341,21 @@
final ArrayList mHistory = new ArrayList();
/**
+ * Description of a request to start a new activity, which has been held
+ * due to app switches being disabled.
+ */
+ class PendingActivityLaunch {
+ HistoryRecord r;
+ HistoryRecord sourceRecord;
+ Uri[] grantedUriPermissions;
+ int grantedMode;
+ boolean onlyIfNeeded;
+ }
+
+ final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
+ = new ArrayList<PendingActivityLaunch>();
+
+ /**
* List of all active broadcasts that are to be executed immediately
* (without waiting for another broadcast to finish). Currently this only
* contains broadcasts to registered receivers, to avoid spinning up
@@ -705,6 +733,18 @@
int mFactoryTest;
/**
+ * The time at which we will allow normal application switches again,
+ * after a call to {@link #stopAppSwitches()}.
+ */
+ long mAppSwitchesAllowedTime;
+
+ /**
+ * This is set to true after the first switch after mAppSwitchesAllowedTime
+ * is set; any switches after that will clear the time.
+ */
+ boolean mDidAppSwitch;
+
+ /**
* Set while we are wanting to sleep, to prevent any
* activities from being started/resumed.
*/
@@ -852,6 +892,7 @@
static final int SERVICE_ERROR_MSG = 18;
static final int RESUME_TOP_ACTIVITY_MSG = 19;
static final int PROC_START_TIMEOUT_MSG = 20;
+ static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
AlertDialog mUidAlert;
@@ -910,6 +951,8 @@
d.show();
proc.anrDialog = d;
}
+
+ ensureScreenEnabled();
} break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
@@ -1041,6 +1084,11 @@
processStartTimedOutLocked(app);
}
}
+ case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
+ synchronized (ActivityManagerService.this) {
+ doPendingActivityLaunchesLocked(true);
+ }
+ }
}
}
};
@@ -1495,6 +1543,18 @@
return null;
}
+ private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
+ int i = mHistory.size()-1;
+ while (i >= 0) {
+ HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ if (!r.finishing && !r.delayedResume && r != notTop) {
+ return r;
+ }
+ i--;
+ }
+ return null;
+ }
+
/**
* This is a simplified version of topRunningActivityLocked that provides a number of
* optional skip-over modes. It is intended for use with the ActivityWatcher hook only.
@@ -2245,6 +2305,8 @@
return true;
}
+ next.delayedResume = false;
+
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
// Make sure we have executed any pending transitions, since there
@@ -2471,7 +2533,8 @@
return true;
}
- private final void startActivityLocked(HistoryRecord r, boolean newTask) {
+ private final void startActivityLocked(HistoryRecord r, boolean newTask,
+ boolean doResume) {
final int NH = mHistory.size();
int addPos = -1;
@@ -2558,7 +2621,7 @@
if ((r.intent.getFlags()
&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
- doShow = topRunningActivityLocked(null) == r;
+ doShow = topRunningNonDelayedActivityLocked(null) == r;
}
}
if (SHOW_APP_STARTING_ICON && doShow) {
@@ -2588,13 +2651,15 @@
mWindowManager.validateAppTokens(mHistory);
}
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
}
/**
* Perform clear operation as requested by
- * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: assuming the top task on the
- * stack is the one that the new activity is being launched in, look for
+ * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
+ * stack to the given task, then look for
* an instance of that activity in the stack and, if found, finish all
* activities on top of it and return the instance.
*
@@ -2602,9 +2667,21 @@
* @return Returns the old activity that should be continue to be used,
* or null if none was found.
*/
- private final HistoryRecord performClearTopTaskLocked(int taskId,
+ private final HistoryRecord performClearTaskLocked(int taskId,
HistoryRecord newR, boolean doClear) {
int i = mHistory.size();
+
+ // First find the requested task.
+ while (i > 0) {
+ i--;
+ HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ if (r.task.taskId == taskId) {
+ i++;
+ break;
+ }
+ }
+
+ // Now clear it.
while (i > 0) {
i--;
HistoryRecord r = (HistoryRecord)mHistory.get(i);
@@ -2840,15 +2917,75 @@
intent, resolvedType, aInfo, mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
- HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
- != 0 ? r : null;
-
+ if (mResumedActivity == null
+ || mResumedActivity.info.applicationInfo.uid != callingUid) {
+ if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
+ PendingActivityLaunch pal = new PendingActivityLaunch();
+ pal.r = r;
+ pal.sourceRecord = sourceRecord;
+ pal.grantedUriPermissions = grantedUriPermissions;
+ pal.grantedMode = grantedMode;
+ pal.onlyIfNeeded = onlyIfNeeded;
+ mPendingActivityLaunches.add(pal);
+ return START_SWITCHES_CANCELED;
+ }
+ }
+
+ if (mDidAppSwitch) {
+ // This is the second allowed switch since we stopped switches,
+ // so now just generally allow switches. Use case: user presses
+ // home (switches disabled, switch to home, mDidAppSwitch now true);
+ // user taps a home icon (coming from home so allowed, we hit here
+ // and now allow anyone to switch again).
+ mAppSwitchesAllowedTime = 0;
+ } else {
+ mDidAppSwitch = true;
+ }
+
+ doPendingActivityLaunchesLocked(false);
+
+ return startActivityUncheckedLocked(r, sourceRecord,
+ grantedUriPermissions, grantedMode, onlyIfNeeded, true);
+ }
+
+ private final void doPendingActivityLaunchesLocked(boolean doResume) {
+ final int N = mPendingActivityLaunches.size();
+ if (N <= 0) {
+ return;
+ }
+ for (int i=0; i<N; i++) {
+ PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
+ startActivityUncheckedLocked(pal.r, pal.sourceRecord,
+ pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
+ doResume && i == (N-1));
+ }
+ mPendingActivityLaunches.clear();
+ }
+
+ private final int startActivityUncheckedLocked(HistoryRecord r,
+ HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
+ int grantedMode, boolean onlyIfNeeded, boolean doResume) {
+ final Intent intent = r.intent;
+ final int callingUid = r.launchedFromUid;
+
+ int launchFlags = intent.getFlags();
+
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
if (DEBUG_USER_LEAVING) Log.v(TAG,
"startActivity() => mUserLeaving=" + mUserLeaving);
+ // If the caller has asked not to resume at this point, we make note
+ // of this in the record so that we can skip it when trying to find
+ // the top running activity.
+ if (!doResume) {
+ r.delayedResume = true;
+ }
+
+ HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
+ != 0 ? r : null;
+
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
@@ -2856,7 +2993,7 @@
if (onlyIfNeeded) {
HistoryRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = topRunningActivityLocked(notTop);
+ checkedCaller = topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
@@ -2894,7 +3031,7 @@
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
- if (resultRecord != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
// is pretty messed up, so instead immediately send back a cancel
@@ -2902,10 +3039,9 @@
// dependency on its originator.
Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
+ r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
- resultRecord = null;
}
boolean addingToTask = false;
@@ -2916,7 +3052,7 @@
// If bring to front is requested, and no result is requested, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
- if (resultRecord == null) {
+ if (r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
@@ -2938,7 +3074,7 @@
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
- HistoryRecord curTop = topRunningActivityLocked(notTop);
+ HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
boolean callerAtFront = sourceRecord == null
@@ -2959,7 +3095,9 @@
// the client said not to do anything if that
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
@@ -2969,7 +3107,7 @@
// from the task up to the one being started. In most
// cases this means we are resetting the task to its
// initial state.
- HistoryRecord top = performClearTopTaskLocked(
+ HistoryRecord top = performClearTaskLocked(
taskTop.task.taskId, r, true);
if (top != null) {
if (top.frontOfTask) {
@@ -3035,7 +3173,9 @@
// We didn't do anything... but it was needed (a.k.a., client
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_TASK_TO_FRONT;
}
}
@@ -3052,8 +3192,8 @@
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- HistoryRecord top = topRunningActivityLocked(notTop);
- if (top != null && resultRecord == null) {
+ HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
+ if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity)) {
if (top.app != null && top.app.thread != null) {
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
@@ -3062,7 +3202,9 @@
logStartActivity(LOG_AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
if (onlyIfNeeded) {
// We don't need to start a new activity, and
// the client said not to do anything if that
@@ -3077,9 +3219,9 @@
}
} else {
- if (resultRecord != null) {
+ if (r.resultTo != null) {
sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
+ r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
}
return START_CLASS_NOT_FOUND;
@@ -3088,7 +3230,7 @@
boolean newTask = false;
// Should this be considered a new task?
- if (resultRecord == null && !addingToTask
+ if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// todo: should do better management of integers.
mCurTask++;
@@ -3108,14 +3250,16 @@
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
- HistoryRecord top = performClearTopTaskLocked(
+ HistoryRecord top = performClearTaskLocked(
sourceRecord.task.taskId, r, true);
if (top != null) {
logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
deliverNewIntentLocked(top, r.intent);
// For paranoia, make sure we have correctly
// resumed the top activity.
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
@@ -3128,7 +3272,9 @@
HistoryRecord top = moveActivityToFrontLocked(where);
logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
deliverNewIntentLocked(top, r.intent);
- resumeTopActivityLocked(null);
+ if (doResume) {
+ resumeTopActivityLocked(null);
+ }
return START_DELIVERED_TO_TOP;
}
}
@@ -3157,7 +3303,7 @@
EventLog.writeEvent(LOG_AM_CREATE_TASK, r.task.taskId);
}
logStartActivity(LOG_AM_CREATE_ACTIVITY, r, r.task);
- startActivityLocked(r, newTask);
+ startActivityLocked(r, newTask, doResume);
return START_SUCCESS;
}
@@ -4911,6 +5057,20 @@
}
}
+ final void ensureScreenEnabled() {
+ boolean enableScreen;
+ synchronized (this) {
+ enableScreen = !mBooted;
+ mBooted = true;
+ }
+
+ if (enableScreen) {
+ EventLog.writeEvent(LOG_BOOT_PROGRESS_ENABLE_SCREEN,
+ SystemClock.uptimeMillis());
+ enableScreenAfterBoot();
+ }
+ }
+
public final void activityPaused(IBinder token, Bundle icicle) {
// Refuse possible leaked file descriptors
if (icicle != null && icicle.hasFileDescriptors()) {
@@ -6251,6 +6411,10 @@
"moveTaskToFront()");
synchronized(this) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task to front")) {
+ return;
+ }
final long origId = Binder.clearCallingIdentity();
try {
int N = mRecentTasks.size();
@@ -6335,6 +6499,12 @@
"moveTaskToBack()");
synchronized(this) {
+ if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task to back")) {
+ return;
+ }
+ }
final long origId = Binder.clearCallingIdentity();
moveTaskToBackLocked(task);
Binder.restoreCallingIdentity(origId);
@@ -6438,6 +6608,10 @@
"moveTaskBackwards()");
synchronized(this) {
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), "Task backwards")) {
+ return;
+ }
final long origId = Binder.clearCallingIdentity();
moveTaskBackwardsLocked(task);
Binder.restoreCallingIdentity(origId);
@@ -7179,6 +7353,55 @@
}
}
+ public void stopAppSwitches() {
+ if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.STOP_APP_SWITCHES);
+ }
+
+ synchronized(this) {
+ mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
+ + APP_SWITCH_DELAY_TIME;
+ mDidAppSwitch = false;
+ mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
+ Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
+ mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
+ }
+ }
+
+ public void resumeAppSwitches() {
+ if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.STOP_APP_SWITCHES);
+ }
+
+ synchronized(this) {
+ // Note that we don't execute any pending app switches... we will
+ // let those wait until either the timeout, or the next start
+ // activity request.
+ mAppSwitchesAllowedTime = 0;
+ }
+ }
+
+ boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
+ String name) {
+ if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
+ return true;
+ }
+
+ final int perm = checkComponentPermission(
+ android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
+ callingUid, -1);
+ if (perm == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
+ Log.w(TAG, name + " request from " + callingUid + " stopped");
+ return false;
+ }
+
public void setDebugApp(String packageName, boolean waitForDebugger,
boolean persistent) {
enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
@@ -7595,6 +7818,30 @@
return handleAppCrashLocked(app);
}
+ private ComponentName getErrorReportReceiver(ProcessRecord app) {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ try {
+ // was an installer package name specified when this app was
+ // installed?
+ String installerPackageName = pm.getInstallerPackageName(app.info.packageName);
+ if (installerPackageName == null) {
+ return null;
+ }
+
+ // is there an Activity in this package that handles ACTION_APP_ERROR?
+ Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+ ResolveInfo info = pm.resolveIntentForPackage(intent, null, 0, installerPackageName);
+ if (info == null || info.activityInfo == null) {
+ return null;
+ }
+
+ return new ComponentName(installerPackageName, info.activityInfo.name);
+ } catch (RemoteException e) {
+ // will return null and no error report will be delivered
+ }
+ return null;
+ }
+
void makeAppNotRespondingLocked(ProcessRecord app,
String tag, String shortMsg, String longMsg, byte[] crashData) {
app.notResponding = true;
@@ -7713,6 +7960,7 @@
}
void startAppProblemLocked(ProcessRecord app) {
+ app.errorReportReceiver = getErrorReportReceiver(app);
skipCurrentReceiverLocked(app);
}
@@ -7745,7 +7993,6 @@
public int handleApplicationError(IBinder app, int flags,
String tag, String shortMsg, String longMsg, byte[] crashData) {
AppErrorResult result = new AppErrorResult();
-
ProcessRecord r = null;
synchronized (this) {
if (app != null) {
@@ -7834,16 +8081,96 @@
int res = result.get();
+ Intent appErrorIntent = null;
synchronized (this) {
if (r != null) {
mProcessCrashTimes.put(r.info.processName, r.info.uid,
SystemClock.uptimeMillis());
}
+ if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
+ appErrorIntent = createAppErrorIntentLocked(r);
+ res = AppErrorDialog.FORCE_QUIT;
+ }
+ }
+
+ if (appErrorIntent != null) {
+ try {
+ mContext.startActivity(appErrorIntent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "bug report receiver dissappeared", e);
+ }
}
return res;
}
+ Intent createAppErrorIntentLocked(ProcessRecord r) {
+ ApplicationErrorReport report = createAppErrorReportLocked(r);
+ if (report == null) {
+ return null;
+ }
+ Intent result = new Intent(Intent.ACTION_APP_ERROR);
+ result.setComponent(r.errorReportReceiver);
+ result.putExtra(Intent.EXTRA_BUG_REPORT, report);
+ result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return result;
+ }
+
+ ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r) {
+ if (r.errorReportReceiver == null) {
+ return null;
+ }
+
+ if (!r.crashing && !r.notResponding) {
+ return null;
+ }
+
+ try {
+ ApplicationErrorReport report = new ApplicationErrorReport();
+ report.packageName = r.info.packageName;
+ report.installerPackageName = r.errorReportReceiver.getPackageName();
+ report.processName = r.processName;
+
+ if (r.crashing) {
+ report.type = ApplicationErrorReport.TYPE_CRASH;
+ report.crashInfo = new ApplicationErrorReport.CrashInfo();
+
+ ByteArrayInputStream byteStream = new ByteArrayInputStream(
+ r.crashingReport.crashData);
+ DataInputStream dataStream = new DataInputStream(byteStream);
+ CrashData crashData = new CrashData(dataStream);
+ ThrowableData throwData = crashData.getThrowableData();
+
+ report.time = crashData.getTime();
+ report.crashInfo.stackTrace = throwData.toString();
+
+ // extract the source of the exception, useful for report
+ // clustering
+ while (throwData.getCause() != null) {
+ throwData = throwData.getCause();
+ }
+ StackTraceElementData trace = throwData.getStackTrace()[0];
+ report.crashInfo.exceptionClassName = throwData.getType();
+ report.crashInfo.throwFileName = trace.getFileName();
+ report.crashInfo.throwClassName = trace.getClassName();
+ report.crashInfo.throwMethodName = trace.getMethodName();
+ } else if (r.notResponding) {
+ report.type = ApplicationErrorReport.TYPE_ANR;
+ report.anrInfo = new ApplicationErrorReport.AnrInfo();
+
+ report.anrInfo.activity = r.notRespondingReport.tag;
+ report.anrInfo.cause = r.notRespondingReport.shortMsg;
+ report.anrInfo.info = r.notRespondingReport.longMsg;
+ }
+
+ return report;
+ } catch (IOException e) {
+ // we don't send it
+ }
+
+ return null;
+ }
+
public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
// assume our apps are happy - lazy create the list
List<ActivityManager.ProcessErrorStateInfo> errList = null;
@@ -10176,8 +10503,6 @@
}
}
- final ContentResolver resolver = mContext.getContentResolver();
-
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
@@ -10200,8 +10525,7 @@
ActivityThread.getPackageManager().queryIntentReceivers(
intent, resolvedType, STOCK_PM_FLAGS);
}
- registeredReceivers = mReceiverResolver.queryIntent(resolver,
- intent, resolvedType, false);
+ registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index 3fcfad0..33894d6 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -19,17 +19,22 @@
import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
class AppErrorDialog extends BaseErrorDialog {
+ private final static String TAG = "AppErrorDialog";
+
private final AppErrorResult mResult;
private final ProcessRecord mProc;
// Event 'what' codes
static final int FORCE_QUIT = 0;
static final int DEBUG = 1;
+ static final int FORCE_QUIT_AND_REPORT = 2;
// 5-minute timeout, then we automatically dismiss the crash dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
@@ -58,12 +63,22 @@
setCancelable(false);
- setButton(res.getText(com.android.internal.R.string.force_close),
- mHandler.obtainMessage(FORCE_QUIT));
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getText(com.android.internal.R.string.force_close),
+ mHandler.obtainMessage(FORCE_QUIT));
+
if ((flags&1) != 0) {
- setButton(res.getText(com.android.internal.R.string.debug),
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ res.getText(com.android.internal.R.string.debug),
mHandler.obtainMessage(DEBUG));
}
+
+ if (app.errorReportReceiver != null) {
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getText(com.android.internal.R.string.report),
+ mHandler.obtainMessage(FORCE_QUIT_AND_REPORT));
+ }
+
setTitle(res.getText(com.android.internal.R.string.aerr_title));
getWindow().addFlags(FLAG_SYSTEM_ERROR);
getWindow().setTitle("Application Error: " + app.info.processName);
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index 7390ed0..03c2a04 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -18,7 +18,10 @@
import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
@@ -26,6 +29,13 @@
import android.util.Log;
class AppNotRespondingDialog extends BaseErrorDialog {
+ private static final String TAG = "AppNotRespondingDialog";
+
+ // Event 'what' codes
+ static final int FORCE_CLOSE = 1;
+ static final int WAIT = 2;
+ static final int WAIT_AND_REPORT = 3;
+
private final ActivityManagerService mService;
private final ProcessRecord mProc;
@@ -67,10 +77,19 @@
? res.getString(resid, name1.toString(), name2.toString())
: res.getString(resid, name1.toString()));
- setButton(res.getText(com.android.internal.R.string.force_close),
- mHandler.obtainMessage(1));
- setButton2(res.getText(com.android.internal.R.string.wait),
- mHandler.obtainMessage(2));
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ res.getText(com.android.internal.R.string.force_close),
+ mHandler.obtainMessage(FORCE_CLOSE));
+ setButton(DialogInterface.BUTTON_NEUTRAL,
+ res.getText(com.android.internal.R.string.wait),
+ mHandler.obtainMessage(WAIT));
+
+ if (app.errorReportReceiver != null) {
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ res.getText(com.android.internal.R.string.report),
+ mHandler.obtainMessage(WAIT_AND_REPORT));
+ }
+
setTitle(res.getText(com.android.internal.R.string.anr_title));
getWindow().addFlags(FLAG_SYSTEM_ERROR);
getWindow().setTitle("Application Not Responding: " + app.info.processName);
@@ -81,16 +100,23 @@
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
+ Intent appErrorIntent = null;
switch (msg.what) {
- case 1:
+ case FORCE_CLOSE:
// Kill the application.
mService.killAppAtUsersRequest(mProc,
AppNotRespondingDialog.this, true);
break;
- case 2:
+ case WAIT_AND_REPORT:
+ case WAIT:
// Continue waiting for the application.
synchronized (mService) {
ProcessRecord app = mProc;
+
+ if (msg.what == WAIT_AND_REPORT) {
+ appErrorIntent = mService.createAppErrorIntentLocked(app);
+ }
+
app.notResponding = false;
app.notRespondingReport = null;
if (app.anrDialog == AppNotRespondingDialog.this) {
@@ -99,6 +125,14 @@
}
break;
}
+
+ if (appErrorIntent != null) {
+ try {
+ getContext().startActivity(appErrorIntent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "bug report receiver dissappeared", e);
+ }
+ }
}
};
}
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 0387be5..a695eba 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -25,6 +25,7 @@
import android.os.Parcel;
import android.os.Process;
import android.os.ServiceManager;
+import android.telephony.SignalStrength;
import android.util.Log;
import java.io.FileDescriptor;
@@ -177,10 +178,10 @@
}
}
- public void notePhoneSignalStrength(int asu) {
+ public void notePhoneSignalStrength(SignalStrength signalStrength) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.notePhoneSignalStrengthLocked(asu);
+ mStats.notePhoneSignalStrengthLocked(signalStrength);
}
}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 1488791..1789687 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -85,6 +85,7 @@
boolean launchFailed; // set if a launched failed, to abort on 2nd try
boolean haveState; // have we gotten the last activity state?
boolean stopped; // is activity pause finished?
+ boolean delayedResume; // not yet resumed because of stopped app switches?
boolean finishing; // activity in pending finish list?
boolean configDestroy; // need to destroy due to config change?
int configChangeFlags; // which config values have changed
@@ -146,6 +147,7 @@
pw.print(" icicle="); pw.println(icicle);
pw.print(prefix); pw.print("state="); pw.print(state);
pw.print(" stopped="); pw.print(stopped);
+ pw.print(" delayedResume="); pw.print(delayedResume);
pw.print(" finishing="); pw.println(finishing);
pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
pw.print(" inHistory="); pw.print(inHistory);
@@ -191,6 +193,7 @@
launchFailed = false;
haveState = false;
stopped = false;
+ delayedResume = false;
finishing = false;
configDestroy = false;
keysPaused = false;
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 68aebc3..419dadf 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -107,6 +107,10 @@
ActivityManager.ProcessErrorStateInfo crashingReport;
ActivityManager.ProcessErrorStateInfo notRespondingReport;
+ // Who will be notified of the error. This is usually an activity in the
+ // app that installed the package.
+ ComponentName errorReportReceiver;
+
void dump(PrintWriter pw, String prefix) {
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
@@ -157,7 +161,14 @@
pw.print(" "); pw.print(crashDialog);
pw.print(" notResponding="); pw.print(notResponding);
pw.print(" " ); pw.print(anrDialog);
- pw.print(" bad="); pw.println(bad);
+ pw.print(" bad="); pw.print(bad);
+
+ // crashing or notResponding is always set before errorReportReceiver
+ if (errorReportReceiver != null) {
+ pw.print(" errorReportReceiver=");
+ pw.print(errorReportReceiver.flattenToShortString());
+ }
+ pw.println();
}
if (activities.size() > 0) {
pw.print(prefix); pw.print("activities="); pw.println(activities);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index b17ba82..76c05d9 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -41,6 +41,7 @@
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import android.util.Log;
@@ -57,6 +58,7 @@
import com.android.internal.location.GpsLocationProvider;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.EriInfo;
import com.android.internal.telephony.cdma.TtyIntent;
import com.android.server.am.BatteryStatsService;
@@ -106,45 +108,140 @@
// phone
private TelephonyManager mPhone;
private IBinder mPhoneIcon;
+ private IBinder mPhoneEvdoIcon;
//***** Signal strength icons
private IconData mPhoneData;
+ private IconData mPhoneEvdoData;
//GSM/UMTS
private static final int[] sSignalImages = new int[] {
- com.android.internal.R.drawable.stat_sys_signal_0,
- com.android.internal.R.drawable.stat_sys_signal_1,
- com.android.internal.R.drawable.stat_sys_signal_2,
- com.android.internal.R.drawable.stat_sys_signal_3,
- com.android.internal.R.drawable.stat_sys_signal_4
- };
+ com.android.internal.R.drawable.stat_sys_signal_0,
+ com.android.internal.R.drawable.stat_sys_signal_1,
+ com.android.internal.R.drawable.stat_sys_signal_2,
+ com.android.internal.R.drawable.stat_sys_signal_3,
+ com.android.internal.R.drawable.stat_sys_signal_4
+ };
private static final int[] sSignalImages_r = new int[] {
- com.android.internal.R.drawable.stat_sys_r_signal_0,
- com.android.internal.R.drawable.stat_sys_r_signal_1,
- com.android.internal.R.drawable.stat_sys_r_signal_2,
- com.android.internal.R.drawable.stat_sys_r_signal_3,
- com.android.internal.R.drawable.stat_sys_r_signal_4
- };
+ com.android.internal.R.drawable.stat_sys_r_signal_0,
+ com.android.internal.R.drawable.stat_sys_r_signal_1,
+ com.android.internal.R.drawable.stat_sys_r_signal_2,
+ com.android.internal.R.drawable.stat_sys_r_signal_3,
+ com.android.internal.R.drawable.stat_sys_r_signal_4
+ };
//CDMA
private static final int[] sSignalImages_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_signal_4_cdma
+ com.android.internal.R.drawable.stat_sys_signal_cdma_0,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_1,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_2,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_3,
+ com.android.internal.R.drawable.stat_sys_signal_cdma_4
};
- private static final int[] sSignalImages_r_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_r_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_r_signal_4_cdma
+ private static final int[] sRoamingIndicatorImages_cdma = new int[] {
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
+ // 1 is Standard Roaming Indicator OFF
+ // TODO T: image never used, remove and put 0 instead?
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 2 is Standard Roaming Indicator FLASHING
+ // TODO T: image never used, remove and put 0 instead?
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 3-12 Standard ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 13-63 Reserved for Standard ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+ // 64-127 Reserved for Non Standard (Operator Specific) ERI
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+ com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
+
+ // 128-255 Reserved
};
- private static final int[] sSignalImages_ra_cdma = new int[] {
- com.android.internal.R.drawable.stat_sys_ra_signal_0_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_1_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_2_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_3_cdma,
- com.android.internal.R.drawable.stat_sys_ra_signal_4_cdma
+ // EVDO
+ private static final int[] sSignalImages_evdo = new int[] {
+ com.android.internal.R.drawable.stat_sys_signal_evdo_0,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_1,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_2,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_3,
+ com.android.internal.R.drawable.stat_sys_signal_evdo_4
};
//***** Data connection icons
@@ -174,12 +271,14 @@
com.android.internal.R.drawable.stat_sys_data_in_evdo,
com.android.internal.R.drawable.stat_sys_data_out_evdo,
com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
+ com.android.internal.R.drawable.stat_sys_data_dormant_evdo,
};
private static final int[] sDataNetType_1xrtt = new int[] {
com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
+ com.android.internal.R.drawable.stat_sys_data_dormant_1xrtt,
};
// Assume it's all good unless we hear otherwise. We don't always seem
@@ -189,7 +288,7 @@
int mDataState = TelephonyManager.DATA_DISCONNECTED;
int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
ServiceState mServiceState;
- int mSignalAsu = -1;
+ SignalStrength mSignalStrength;
// data connection
private IBinder mDataIcon;
@@ -244,6 +343,10 @@
private IBinder mTTYModeIcon;
private IconData mTTYModeEnableIconData;
+ // Cdma Roaming Indicator, ERI
+ private IBinder mCdmaRoamingIndicatorIcon;
+ private IconData mCdmaRoamingIndicatorIconData;
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -304,6 +407,7 @@
private StatusBarPolicy(Context context, StatusBarService service) {
mContext = context;
mService = service;
+ mSignalStrength = new SignalStrength();
mBatteryStats = BatteryStatsService.getService();
// clock
@@ -319,14 +423,21 @@
// phone_signal
mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- mPhoneData = IconData.makeIcon("phone_signal",
+ mPhoneData = IconData.makeIcon("phone_signal",
null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
mPhoneIcon = service.addIcon(mPhoneData, null);
+
+ // phone_evdo_signal
+ mPhoneEvdoData = IconData.makeIcon("phone_evdo_signal",
+ null, com.android.internal.R.drawable.stat_sys_signal_evdo_0, 0, 0);
+ mPhoneEvdoIcon = service.addIcon(mPhoneEvdoData, null);
+ service.setIconVisibility(mPhoneEvdoIcon, false);
+
// register for phone state notifications.
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_CALL_STATE
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_DATA_ACTIVITY);
@@ -349,6 +460,12 @@
mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
service.setIconVisibility(mTTYModeIcon, false);
+ // Cdma Roaming Indicator, ERI
+ mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
+ null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
+ mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
+ service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+
// bluetooth status
mBluetoothData = IconData.makeIcon("bluetooth",
null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -645,8 +762,8 @@
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
- public void onSignalStrengthChanged(int asu) {
- mSignalAsu = asu;
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrength = signalStrength;
updateSignalStrength();
}
@@ -654,6 +771,7 @@
public void onServiceStateChanged(ServiceState state) {
mServiceState = state;
updateSignalStrength();
+ updateCdmaRoamingIcon();
updateDataIcon();
}
@@ -675,7 +793,6 @@
updateDataIcon();
}
};
-
private final void updateSimState(Intent intent) {
String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
@@ -702,25 +819,51 @@
updateDataIcon();
}
- private final void updateSignalStrength() {
- int asu = mSignalAsu;
- ServiceState ss = mServiceState;
+ // TODO(Teleca): I've add isCdma() to reduce some code duplication and simplify.
+ // Please validate the correctness of these changes
+ private boolean isCdma() {
+ // Is this equivalent, if so it seems simpler?
+// return ((mPhone != null) && (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA));
- boolean hasService = true;
-
- if (ss != null) {
- int state = ss.getState();
- switch (state) {
- case ServiceState.STATE_OUT_OF_SERVICE:
- case ServiceState.STATE_POWER_OFF:
- hasService = false;
- break;
+ if (mServiceState != null) {
+ switch(mServiceState.getRadioTechnology()) {
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
+ return true;
+ default:
+ return false;
}
} else {
- hasService = false;
+ return false;
}
+ }
- if (!hasService) {
+ // TODO(Teleca): I've add hasService() to reduce some code duplication and simplify.
+ // Please validate the correctness of these changes.
+ private boolean hasService() {
+ if (mServiceState != null) {
+ switch (mServiceState.getState()) {
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_POWER_OFF:
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private final void updateSignalStrength() {
+ int iconLevel = -1;
+ int evdoIconLevel = -1;
+ int[] iconList;
+ int[] evdoIconList;
+
+ if (!hasService()) {
//Log.d(TAG, "updateSignalStrength: no service");
if (Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
@@ -729,48 +872,92 @@
mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
}
mService.updateIcon(mPhoneIcon, mPhoneData, null);
+ mService.setIconVisibility(mPhoneEvdoIcon,false);
return;
}
- // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
- // asu = 0 (-113dB or less) is very weak
- // signal, its better to show 0 bars to the user in such cases.
- // asu = 99 is a special case, where the signal strength is unknown.
- if (asu <= 0 || asu == 99) asu = 0;
- else if (asu >= 16) asu = 4;
- else if (asu >= 8) asu = 3;
- else if (asu >= 4) asu = 2;
- else asu = 1;
+ if (!isCdma()) {
+ int asu = mSignalStrength.getGsmSignalStrength();
- int[] iconList;
- if (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
- switch(ss.getExtendedCdmaRoaming()) {
- case ServiceState.REGISTRATION_STATE_ROAMING:
- iconList = this.sSignalImages_r_cdma;
- break;
- case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
- iconList = this.sSignalImages_ra_cdma;
- break;
- default:
- iconList = this.sSignalImages_cdma;
- break;
+ // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+ // asu = 0 (-113dB or less) is very weak
+ // signal, its better to show 0 bars to the user in such cases.
+ // asu = 99 is a special case, where the signal strength is unknown.
+ if (asu <= 0 || asu == 99) iconLevel = 0;
+ else if (asu >= 16) iconLevel = 4;
+ else if (asu >= 8) iconLevel = 3;
+ else if (asu >= 4) iconLevel = 2;
+ else iconLevel = 1;
+
+ if (mPhone.isNetworkRoaming()) {
+ iconList = sSignalImages_r;
+ } else {
+ iconList = sSignalImages;
}
- } else if (mPhone.isNetworkRoaming()) {
- iconList = sSignalImages_r;
} else {
- iconList = sSignalImages;
+ iconList = this.sSignalImages_cdma;
+
+ int cdmaDbm = mSignalStrength.getCdmaDbm();
+ int cdmaEcio = mSignalStrength.getCdmaEcio();
+ int levelDbm = 0;
+ int levelEcio = 0;
+
+ if (cdmaDbm >= -75) levelDbm = 4;
+ else if (cdmaDbm >= -85) levelDbm = 3;
+ else if (cdmaDbm >= -95) levelDbm = 2;
+ else if (cdmaDbm >= -100) levelDbm = 1;
+ else levelDbm = 0;
+
+ // Ec/Io are in dB*10
+ if (cdmaEcio >= -90) levelEcio = 4;
+ else if (cdmaEcio >= -110) levelEcio = 3;
+ else if (cdmaEcio >= -130) levelEcio = 2;
+ else if (cdmaEcio >= -150) levelEcio = 1;
+ else levelEcio = 0;
+
+ iconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio;
}
- mPhoneData.iconId = iconList[asu];
+ if ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+ || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
+ // Use Evdo icon
+ evdoIconList = this.sSignalImages_evdo;
+
+ int evdoEcio = mSignalStrength.getEvdoEcio();
+ int evdoSnr = mSignalStrength.getEvdoSnr();
+ int levelEvdoEcio = 0;
+ int levelEvdoSnr = 0;
+
+ // Ec/Io are in dB*10
+ if (evdoEcio >= -650) levelEvdoEcio = 4;
+ else if (evdoEcio >= -750) levelEvdoEcio = 3;
+ else if (evdoEcio >= -900) levelEvdoEcio = 2;
+ else if (evdoEcio >= -1050) levelEvdoEcio = 1;
+ else levelEvdoEcio = 0;
+
+ if (evdoSnr > 7) levelEvdoSnr = 4;
+ else if (evdoSnr > 5) levelEvdoSnr = 3;
+ else if (evdoSnr > 3) levelEvdoSnr = 2;
+ else if (evdoSnr > 1) levelEvdoSnr = 1;
+ else levelEvdoSnr = 0;
+
+ evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
+
+ mPhoneEvdoData.iconId = evdoIconList[evdoIconLevel];
+ mService.updateIcon(mPhoneEvdoIcon, mPhoneEvdoData, null);
+ mService.setIconVisibility(mPhoneEvdoIcon,true);
+ } else {
+ mService.setIconVisibility(mPhoneEvdoIcon,false);
+ }
+
+ mPhoneData.iconId = iconList[iconLevel];
mService.updateIcon(mPhoneIcon, mPhoneData, null);
}
private final void updateDataNetType() {
int net = mPhone.getNetworkType();
- ServiceState ss = this.mServiceState;
switch (net) {
-
case TelephonyManager.NETWORK_TYPE_EDGE:
mDataIconList = sDataNetType_e;
break;
@@ -798,32 +985,51 @@
int iconId;
boolean visible = true;
- if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
- int data = mDataState;
-
- int[] list = mDataIconList;
-
- ServiceState ss = mServiceState;
-
- boolean hasService = false;
-
- if (ss != null) {
- hasService = (ss.getState() == ServiceState.STATE_IN_SERVICE);
+ if (!isCdma()) {
+ // GSM case, we have to check also the sim state
+ if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
+ if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
+ switch (mDataActivity) {
+ case TelephonyManager.DATA_ACTIVITY_IN:
+ iconId = mDataIconList[1];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_OUT:
+ iconId = mDataIconList[2];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_INOUT:
+ iconId = mDataIconList[3];
+ break;
+ default:
+ iconId = mDataIconList[0];
+ break;
+ }
+ mDataData.iconId = iconId;
+ mService.updateIcon(mDataIcon, mDataData, null);
+ } else {
+ visible = false;
+ }
+ } else {
+ mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
+ mService.updateIcon(mDataIcon, mDataData, null);
}
-
- if (hasService && data == TelephonyManager.DATA_CONNECTED) {
+ } else {
+ // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
+ if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
switch (mDataActivity) {
case TelephonyManager.DATA_ACTIVITY_IN:
- iconId = list[1];
+ iconId = mDataIconList[1];
break;
case TelephonyManager.DATA_ACTIVITY_OUT:
- iconId = list[2];
+ iconId = mDataIconList[2];
break;
case TelephonyManager.DATA_ACTIVITY_INOUT:
- iconId = list[3];
+ iconId = mDataIconList[3];
+ break;
+ case TelephonyManager.DATA_ACTIVITY_DORMANT:
+ iconId = mDataIconList[4];
break;
default:
- iconId = list[0];
+ iconId = mDataIconList[0];
break;
}
mDataData.iconId = iconId;
@@ -831,10 +1037,8 @@
} else {
visible = false;
}
- } else {
- mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
- mService.updateIcon(mDataIcon, mDataData, null);
}
+
long ident = Binder.clearCallingIdentity();
try {
mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
@@ -842,6 +1046,7 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
+
if (mDataIconVisible != visible) {
mService.setIconVisibility(mDataIcon, visible);
mDataIconVisible = visible;
@@ -852,7 +1057,7 @@
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
final int ringerMode = audioManager.getRingerMode();
final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
- ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ ringerMode == AudioManager.RINGER_MODE_VIBRATE;
final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
? com.android.internal.R.drawable.stat_sys_ringer_vibrate
: com.android.internal.R.drawable.stat_sys_ringer_silent;
@@ -884,7 +1089,7 @@
} else {
return;
}
-
+
if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
@@ -899,15 +1104,15 @@
private final void updateWifi(Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-
+
final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
+
if (!enabled) {
// If disabled, hide the icon. (We show icon when connected.)
mService.setIconVisibility(mWifiIcon, false);
}
-
+
} else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
false);
@@ -916,9 +1121,9 @@
}
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final NetworkInfo networkInfo = (NetworkInfo)
+ final NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-
+
int iconId;
if (networkInfo != null && networkInfo.isConnected()) {
mIsWifiConnected = true;
@@ -965,18 +1170,18 @@
if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
// GPS is getting fixes
mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
- mService.setIconVisibility(mGpsIcon, true);
+ mService.setIconVisibility(mGpsIcon, true);
} else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
// GPS is off
- mService.setIconVisibility(mGpsIcon, false);
+ mService.setIconVisibility(mGpsIcon, false);
} else {
// GPS is on, but not receiving fixes
mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
- mService.setIconVisibility(mGpsIcon, true);
+ mService.setIconVisibility(mGpsIcon, true);
}
}
- private final void updateTTY(Intent intent) {
+ private final void updateTTY(Intent intent) {
final String action = intent.getAction();
final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
@@ -986,14 +1191,59 @@
// TTY is on
Log.i(TAG, "updateTTY: set TTY on");
mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
- mService.setIconVisibility(mTTYModeIcon, true);
+ mService.setIconVisibility(mTTYModeIcon, true);
} else {
// TTY is off
Log.i(TAG, "updateTTY: set TTY off");
- mService.setIconVisibility(mTTYModeIcon, false);
+ mService.setIconVisibility(mTTYModeIcon, false);
}
}
+ private final void updateCdmaRoamingIcon() {
+ if (!hasService()) {
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ }
+
+ if (!isCdma()) {
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ }
+
+ int[] iconList = sRoamingIndicatorImages_cdma;
+ int iconIndex = mPhone.getCdmaEriIconIndex();
+ int iconMode = mPhone.getCdmaEriIconMode();
+
+ if (iconIndex == -1) {
+ Log.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
+ return;
+ }
+
+ if (iconMode == -1) {
+ Log.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
+ return;
+ }
+
+ if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
+ Log.d(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+ return;
+ }
+
+ switch (iconMode) {
+ case EriInfo.ROAMING_ICON_MODE_NORMAL:
+ mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
+ mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+ mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
+ break;
+ case EriInfo.ROAMING_ICON_MODE_FLASH:
+ mCdmaRoamingIndicatorIconData.iconId = com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
+ mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+ break;
+
+ }
+ mService.updateIcon(mPhoneIcon, mPhoneData, null);
+ }
+
+
private class StatusBarHandler extends Handler {
@Override
public void handleMessage(Message msg) {
@@ -1007,6 +1257,3 @@
}
}
}
-
-
-
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 5336e27..48cbace 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -19,6 +19,7 @@
import com.android.internal.R;
import com.android.internal.util.CharSequences;
+import android.app.ActivityManagerNative;
import android.app.Dialog;
import android.app.IStatusBar;
import android.app.PendingIntent;
@@ -1254,6 +1255,14 @@
public void onClick(View v) {
try {
+ // The intent we are sending is for the application, which
+ // won't have permission to immediately start an activity after
+ // the user switches to home. We know it is safe to do at this
+ // point, so make sure new activity switches are now allowed.
+ ActivityManagerNative.getDefault().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+ try {
mIntent.send();
mNotificationCallbacks.onNotificationClick(mPkg, mId);
} catch (PendingIntent.CanceledException e) {
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index 1d66fb1..85d63c9 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -19,8 +19,8 @@
#include "JNIHelp.h"
#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
+#include <utils/Log.h>
+#include <utils/misc.h>
#include <fcntl.h>
#include <stdio.h>
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index 2524966..e4f001f 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -18,8 +18,8 @@
#include "JNIHelp.h"
#include "jni.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
+#include <utils/Log.h>
+#include <utils/misc.h>
#include <fcntl.h>
#include <stdio.h>
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index bb5f126..7d600f0 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -62,13 +62,10 @@
* @hide
*/
public static CellLocation newFromBundle(Bundle bundle) {
- // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
- // instead of SystemProperties???
-
- // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
- // ITelephony have not been created
- if (RILConstants.CDMA_PHONE ==
- SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE)) {
+ // TelephonyManager.getDefault().getPhoneType() handles the case when
+ // ITelephony interface is not up yet.
+ int type = TelephonyManager.getDefault().getPhoneType();
+ if (type == RILConstants.CDMA_PHONE) {
return new CdmaCellLocation(bundle);
} else {
return new GsmCellLocation(bundle);
@@ -85,17 +82,13 @@
*
*/
public static CellLocation getEmpty() {
- // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
- // instead of SystemProperties???
-
- // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
- // ITelephony have not been created
- if (RILConstants.CDMA_PHONE ==
- SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE)) {
+ // TelephonyManager.getDefault().getPhoneType() handles the case when
+ // ITelephony interface is not up yet.
+ int type = TelephonyManager.getDefault().getPhoneType();
+ if (type == RILConstants.CDMA_PHONE) {
return new CdmaCellLocation();
} else {
return new GsmCellLocation();
}
}
-
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index df6860b..8abafae 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -4,6 +4,7 @@
import android.os.Handler;
import android.os.Message;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.CellLocation;
import android.util.Log;
@@ -42,10 +43,10 @@
/**
* Listen for changes to the network signal strength (cellular).
* <p>
- * Example: The status bar uses this to control the signal-strength
- * icon.
*
* @see #onSignalStrengthChanged
+ *
+ * TODO: @deprecated to be deprecated by LISTEN_SIGNAL_STRENGTHS, @see #onSignalStrengthsChanged
*/
public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002;
@@ -107,6 +108,18 @@
*/
public static final int LISTEN_DATA_ACTIVITY = 0x00000080;
+ /**
+ * Listen for changes to the network signal strengths (cellular).
+ * <p>
+ * Example: The status bar uses this to control the signal-strength
+ * icon.
+ *
+ * @see #onSignalStrengthsChanged
+ *
+ * @hide
+ */
+ public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100;
+
public PhoneStateListener() {
}
@@ -129,6 +142,7 @@
* @see ServiceState#STATE_IN_SERVICE
* @see ServiceState#STATE_OUT_OF_SERVICE
* @see ServiceState#STATE_POWER_OFF
+ * @deprecated, @see #onSignalStrengthsChanged
*/
public void onSignalStrengthChanged(int asu) {
// default implementation empty
@@ -185,12 +199,27 @@
* @see TelephonyManager#DATA_ACTIVITY_IN
* @see TelephonyManager#DATA_ACTIVITY_OUT
* @see TelephonyManager#DATA_ACTIVITY_INOUT
+ * @see TelephonyManager#DATA_ACTIVITY_DORMANT
*/
public void onDataActivity(int direction) {
// default implementation empty
}
/**
+ * Callback invoked when network signal strengths changes.
+ *
+ * @see ServiceState#STATE_EMERGENCY_ONLY
+ * @see ServiceState#STATE_IN_SERVICE
+ * @see ServiceState#STATE_OUT_OF_SERVICE
+ * @see ServiceState#STATE_POWER_OFF
+ *
+ * @hide
+ */
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*/
@@ -229,6 +258,9 @@
public void onDataActivity(int direction) {
Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget();
}
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget();
+ }
};
Handler mHandler = new Handler() {
@@ -259,6 +291,9 @@
case LISTEN_DATA_ACTIVITY:
PhoneStateListener.this.onDataActivity(msg.arg1);
break;
+ case LISTEN_SIGNAL_STRENGTHS:
+ PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
+ break;
}
}
};
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 4de0954..50c4d41 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -99,12 +99,9 @@
public static final int REGISTRATION_STATE_UNKNOWN = 4;
/** @hide */
public static final int REGISTRATION_STATE_ROAMING = 5;
- /** @hide */
- public static final int REGISTRATION_STATE_ROAMING_AFFILIATE = 6;
private int mState = STATE_OUT_OF_SERVICE;
private boolean mRoaming;
- private int mExtendedCdmaRoaming;
private String mOperatorAlphaLong;
private String mOperatorAlphaShort;
private String mOperatorNumeric;
@@ -115,6 +112,8 @@
private boolean mCssIndicator;
private int mNetworkId;
private int mSystemId;
+ private int mCdmaRoamingIndicator;
+ private int mCdmaDefaultRoamingIndicator;
/**
* Create a new ServiceState from a intent notifier Bundle
@@ -159,7 +158,8 @@
mCssIndicator = s.mCssIndicator;
mNetworkId = s.mNetworkId;
mSystemId = s.mSystemId;
- mExtendedCdmaRoaming = s.mExtendedCdmaRoaming;
+ mCdmaRoamingIndicator = s.mCdmaRoamingIndicator;
+ mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
}
/**
@@ -176,7 +176,8 @@
mCssIndicator = (in.readInt() != 0);
mNetworkId = in.readInt();
mSystemId = in.readInt();
- mExtendedCdmaRoaming = in.readInt();
+ mCdmaRoamingIndicator = in.readInt();
+ mCdmaDefaultRoamingIndicator = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
@@ -190,7 +191,8 @@
out.writeInt(mCssIndicator ? 1 : 0);
out.writeInt(mNetworkId);
out.writeInt(mSystemId);
- out.writeInt(mExtendedCdmaRoaming);
+ out.writeInt(mCdmaRoamingIndicator);
+ out.writeInt(mCdmaDefaultRoamingIndicator);
}
public int describeContents() {
@@ -231,15 +233,25 @@
return mRoaming;
}
- /** @hide */
- public int getExtendedCdmaRoaming(){
- return this.mExtendedCdmaRoaming;
+ /**
+ * @hide
+ */
+ public int getCdmaRoamingIndicator(){
+ return this.mCdmaRoamingIndicator;
+ }
+
+ /**
+ * @hide
+ */
+ public int getCdmaDefaultRoamingIndicator(){
+ return this.mCdmaDefaultRoamingIndicator;
}
/**
* Get current registered operator name in long alphanumeric format
*
* In GSM/UMTS, long format can be upto 16 characters long
+ * In CDMA, returns the ERI text, if set, otherwise the ONS
*
* @return long name of operator, null if unregistered or unknown
*/
@@ -289,7 +301,8 @@
+ ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
+ ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
+ ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
- + (mExtendedCdmaRoaming));
+ + mCdmaRoamingIndicator
+ + mCdmaDefaultRoamingIndicator);
}
@Override
@@ -316,7 +329,9 @@
&& equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
&& equalsHandlesNulls(mNetworkId, s.mNetworkId)
&& equalsHandlesNulls(mSystemId, s.mSystemId)
- && equalsHandlesNulls(mExtendedCdmaRoaming, s.mExtendedCdmaRoaming));
+ && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
+ && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
+ s.mCdmaDefaultRoamingIndicator));
}
@Override
@@ -363,9 +378,10 @@
+ " " + (mIsManualNetworkSelection ? "(manual)" : "")
+ " " + radioTechnology
+ " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
- + "NetworkId: " + mNetworkId
- + "SystemId: " + mSystemId
- + "ExtendedCdmaRoaming: " + mExtendedCdmaRoaming);
+ + " " + mNetworkId
+ + " " + mSystemId
+ + "RoamInd: " + mCdmaRoamingIndicator
+ + "DefRoamInd: " + mCdmaDefaultRoamingIndicator);
}
public void setStateOutOfService() {
@@ -379,7 +395,8 @@
mCssIndicator = false;
mNetworkId = -1;
mSystemId = -1;
- mExtendedCdmaRoaming = -1;
+ mCdmaRoamingIndicator = -1;
+ mCdmaDefaultRoamingIndicator = -1;
}
public void setStateOff() {
@@ -393,7 +410,8 @@
mCssIndicator = false;
mNetworkId = -1;
mSystemId = -1;
- mExtendedCdmaRoaming = -1;
+ mCdmaRoamingIndicator = -1;
+ mCdmaDefaultRoamingIndicator = -1;
}
public void setState(int state) {
@@ -404,9 +422,18 @@
mRoaming = roaming;
}
- /** @hide */
- public void setExtendedCdmaRoaming (int roaming) {
- this.mExtendedCdmaRoaming = roaming;
+ /**
+ * @hide
+ */
+ public void setCdmaRoamingIndicator(int roaming) {
+ this.mCdmaRoamingIndicator = roaming;
+ }
+
+ /**
+ * @hide
+ */
+ public void setCdmaDefaultRoamingIndicator (int roaming) {
+ this.mCdmaDefaultRoamingIndicator = roaming;
}
public void setOperatorName(String longName, String shortName, String numeric) {
@@ -415,6 +442,16 @@
mOperatorNumeric = numeric;
}
+ /**
+ * In CDMA mOperatorAlphaLong can be set from the ERI
+ * text, this is done from the CDMAPhone and not from the CdmaServiceStateTracker
+ *
+ * @hide
+ */
+ public void setCdmaEriText(String longName) {
+ mOperatorAlphaLong = longName;
+ }
+
public void setIsManualSelection(boolean isManual) {
mIsManualNetworkSelection = isManual;
}
@@ -447,7 +484,8 @@
mCssIndicator = m.getBoolean("cssIndicator");
mNetworkId = m.getInt("networkId");
mSystemId = m.getInt("systemId");
- mExtendedCdmaRoaming = m.getInt("extendedCdmaRoaming");
+ mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
+ mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
}
/**
@@ -467,7 +505,8 @@
m.putBoolean("cssIndicator", mCssIndicator);
m.putInt("networkId", mNetworkId);
m.putInt("systemId", mSystemId);
- m.putInt("extendedCdmaRoaming", mExtendedCdmaRoaming);
+ m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
+ m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
}
//***** CDMA
diff --git a/telephony/java/android/telephony/SignalStrength.aidl b/telephony/java/android/telephony/SignalStrength.aidl
new file mode 100644
index 0000000..c25411e
--- /dev/null
+++ b/telephony/java/android/telephony/SignalStrength.aidl
@@ -0,0 +1,22 @@
+/* //device/java/android/android/content/Intent.aidl
+**
+** Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
+** 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 android.telephony;
+
+parcelable SignalStrength;
+
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
new file mode 100644
index 0000000..8ed0065
--- /dev/null
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * 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 android.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Contains phone signal strength related information.
+ *
+ * @hide
+ */
+public class SignalStrength implements Parcelable {
+
+ static final String LOG_TAG = "PHONE";
+
+ private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+ private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ private int mCdmaDbm; // This value is the RSSI value
+ private int mCdmaEcio; // This value is the Ec/Io
+ private int mEvdoDbm; // This value is the EVDO RSSI value
+ private int mEvdoEcio; // This value is the EVDO Ec/Io
+ private int mEvdoSnr; // Valid values are 0-8. 8 is the highest signal to noise ratio
+
+ private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
+
+ /**
+ * Create a new SignalStrength from a intent notifier Bundle
+ *
+ * This method is used by PhoneStateIntentReceiver and maybe by
+ * external applications.
+ *
+ * @param m Bundle from intent notifier
+ * @return newly created SignalStrength
+ *
+ */
+ public static SignalStrength newFromBundle(Bundle m) {
+ SignalStrength ret;
+ ret = new SignalStrength();
+ ret.setFromNotifierBundle(m);
+ return ret;
+ }
+
+ /**
+ * Empty constructor
+ *
+ */
+ public SignalStrength() {
+ mGsmSignalStrength = 99;
+ mGsmBitErrorRate = -1;
+ mCdmaDbm = -1;
+ mCdmaEcio = -1;
+ mEvdoDbm = -1;
+ mEvdoEcio = -1;
+ mEvdoSnr = -1;
+ isGsm = true;
+ }
+
+ /**
+ * Constructor
+ *
+ */
+ public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+ int cdmaDbm, int cdmaEcio,
+ int evdoDbm, int evdoEcio, int evdoSnr, boolean gsm) {
+ mGsmSignalStrength = gsmSignalStrength;
+ mGsmBitErrorRate = gsmBitErrorRate;
+ mCdmaDbm = cdmaDbm;
+ mCdmaEcio = cdmaEcio;
+ mEvdoDbm = evdoDbm;
+ mEvdoEcio = evdoEcio;
+ mEvdoSnr = evdoSnr;
+ isGsm = gsm;
+ }
+
+ /**
+ * Copy constructors
+ *
+ * @param s Source SignalStrength
+ */
+ public SignalStrength(SignalStrength s) {
+ copyFrom(s);
+ }
+
+ /**
+ * @hide
+ */
+ protected void copyFrom(SignalStrength s) {
+ mGsmSignalStrength = s.mGsmSignalStrength;
+ mGsmBitErrorRate = s.mGsmBitErrorRate;
+ mCdmaDbm = s.mCdmaDbm;
+ mCdmaEcio = s.mCdmaEcio;
+ mEvdoDbm = s.mEvdoDbm;
+ mEvdoEcio = s.mEvdoEcio;
+ mEvdoSnr = s.mEvdoSnr;
+ isGsm = s.isGsm;
+ }
+
+ /**
+ * Construct a SignalStrength object from the given parcel.
+ */
+ public SignalStrength(Parcel in) {
+ mGsmSignalStrength = in.readInt();
+ mGsmBitErrorRate = in.readInt();
+ mCdmaDbm = in.readInt();
+ mCdmaEcio = in.readInt();
+ mEvdoDbm = in.readInt();
+ mEvdoEcio = in.readInt();
+ mEvdoSnr = in.readInt();
+ isGsm = (in.readInt() != 0);
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mGsmSignalStrength);
+ out.writeInt(mGsmBitErrorRate);
+ out.writeInt(mCdmaDbm);
+ out.writeInt(mCdmaEcio);
+ out.writeInt(mEvdoDbm);
+ out.writeInt(mEvdoEcio);
+ out.writeInt(mEvdoSnr);
+ out.writeInt(isGsm ? 1 : 0);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
+ public SignalStrength createFromParcel(Parcel in) {
+ return new SignalStrength(in);
+ }
+
+ public SignalStrength[] newArray(int size) {
+ return new SignalStrength[size];
+ }
+ };
+
+ /**
+ * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS 27.007 8.5
+ */
+ public int getGsmSignalStrength() {
+ return this.mGsmSignalStrength;
+ }
+
+ /**
+ * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ */
+ public int getGsmBitErrorRate() {
+ return this.mGsmBitErrorRate;
+ }
+
+ /**
+ * Get the CDMA RSSI value in dBm
+ */
+ public int getCdmaDbm() {
+ return this.mCdmaDbm;
+ }
+
+ /**
+ * Get the CDMA Ec/Io value in dB*10
+ */
+ public int getCdmaEcio() {
+ return this.mCdmaEcio;
+ }
+
+ /**
+ * Get the EVDO RSSI value in dBm
+ */
+ public int getEvdoDbm() {
+ return this.mEvdoDbm;
+ }
+
+ /**
+ * Get the EVDO Ec/Io value in dB*10
+ */
+ public int getEvdoEcio() {
+ return this.mEvdoEcio;
+ }
+
+ /**
+ * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
+ */
+ public int getEvdoSnr() {
+ return this.mEvdoSnr;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isGsm() {
+ return this.isGsm;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int hashCode() {
+ return ((mGsmSignalStrength * 0x1234)
+ + mGsmBitErrorRate
+ + mCdmaDbm + mCdmaEcio
+ + mEvdoDbm + mEvdoEcio + mEvdoSnr
+ + (isGsm ? 1 : 0));
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals (Object o) {
+ SignalStrength s;
+
+ try {
+ s = (SignalStrength) o;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ return (mGsmSignalStrength == s.mGsmSignalStrength
+ && mGsmBitErrorRate == s.mGsmBitErrorRate
+ && mCdmaDbm == s.mCdmaDbm
+ && mCdmaEcio == s.mCdmaEcio
+ && mEvdoDbm == s.mEvdoDbm
+ && mEvdoEcio == s.mEvdoEcio
+ && mEvdoSnr == s.mEvdoSnr
+ && isGsm == s.isGsm);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public String toString() {
+ return ("SignalStrength:"
+ + " " + mGsmSignalStrength
+ + " " + mGsmBitErrorRate
+ + " " + mCdmaDbm
+ + " " + mCdmaEcio
+ + " " + mEvdoDbm
+ + " " + mEvdoEcio
+ + " " + mEvdoSnr
+ + " " + (isGsm ? "gsm" : "cdma"));
+ }
+
+ /**
+ * Test whether two objects hold the same data values or both are null
+ *
+ * @param a first obj
+ * @param b second obj
+ * @return true if two objects equal or both are null
+ * @hide
+ */
+ private static boolean equalsHandlesNulls (Object a, Object b) {
+ return (a == null) ? (b == null) : a.equals (b);
+ }
+
+ /**
+ * Set SignalStrength based on intent notifier map
+ *
+ * @param m intent notifier map
+ * @hide
+ */
+ private void setFromNotifierBundle(Bundle m) {
+ mGsmSignalStrength = m.getInt("GsmSignalStrength");
+ mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
+ mCdmaDbm = m.getInt("CdmaDbm");
+ mCdmaEcio = m.getInt("CdmaEcio");
+ mEvdoDbm = m.getInt("EvdoDbm");
+ mEvdoEcio = m.getInt("EvdoEcio");
+ mEvdoSnr = m.getInt("EvdoSnr");
+ isGsm = m.getBoolean("isGsm");
+ }
+
+ /**
+ * Set intent notifier Bundle based on SignalStrength
+ *
+ * @param m intent notifier Bundle
+ * @hide
+ */
+ public void fillInNotifierBundle(Bundle m) {
+ m.putInt("GsmSignalStrength", mGsmSignalStrength);
+ m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
+ m.putInt("CdmaDbm", mCdmaDbm);
+ m.putInt("CdmaEcio", mCdmaEcio);
+ m.putInt("EvdoDbm", mEvdoDbm);
+ m.putInt("EvdoEcio", mEvdoEcio);
+ m.putInt("EvdoSnr", mEvdoSnr);
+ m.putBoolean("isGsm", Boolean.valueOf(isGsm));
+ }
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 3b7f4b5..e73de3c 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -20,6 +20,7 @@
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
@@ -307,7 +308,8 @@
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
- destinationAddress, message, statusReportRequested, header);
+ destinationAddress, message, statusReportRequested,
+ SmsHeader.fromByteArray(header));
} else {
spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
destinationAddress, message, statusReportRequested, header);
@@ -331,7 +333,7 @@
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
- destinationAddress, message, statusReportRequested);
+ destinationAddress, message, statusReportRequested, null);
} else {
spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
destinationAddress, message, statusReportRequested);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 559542a..a79eb3a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,26 +16,24 @@
package android.telephony;
-import com.android.internal.telephony.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.telephony.CellLocation;
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
+import java.util.List;
+
/**
* Provides access to information about the telephony services on
* the device. Applications can use the methods in this class to
@@ -192,8 +190,9 @@
/**
* Returns the current location of the device.
*
- * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
- * ACCESS_COARSE_LOCATION}.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
*/
public CellLocation getCellLocation() {
try {
@@ -238,10 +237,10 @@
/**
* Returns the neighboring cell information of the device.
- *
+ *
* @return List of NeighboringCellInfo or null if info unavailable.
- *
- * <p>Requires Permission:
+ *
+ * <p>Requires Permission:
* (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
*/
public List<NeighboringCellInfo> getNeighboringCellInfo() {
@@ -250,24 +249,25 @@
} catch (RemoteException ex) {
}
return null;
-
+
}
-
+
/**
* No phone module
+ *
*/
public static final int PHONE_TYPE_NONE = 0;
/**
* GSM phone
*/
- public static final int PHONE_TYPE_GSM = 1;
+ public static final int PHONE_TYPE_GSM = RILConstants.GSM_PHONE;
/**
* CDMA phone
* @hide
*/
- public static final int PHONE_TYPE_CDMA = 2;
+ public static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE;
/**
* Returns a constant indicating the device phone type.
@@ -278,16 +278,41 @@
*/
public int getPhoneType() {
try{
- if(getITelephony().getActivePhoneType() == RILConstants.CDMA_PHONE) {
- return PHONE_TYPE_CDMA;
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ if(telephony.getActivePhoneType() == RILConstants.CDMA_PHONE) {
+ return PHONE_TYPE_CDMA;
+ } else {
+ return PHONE_TYPE_GSM;
+ }
} else {
- return PHONE_TYPE_GSM;
+ // This can happen when the ITelephony interface is not up yet.
+ return getPhoneTypeFromProperty();
}
- }catch(RemoteException ex){
- return PHONE_TYPE_NONE;
+ } catch(RemoteException ex){
+ // This shouldn't happen in the normal case, as a backup we
+ // read from the system property.
+ return getPhoneTypeFromProperty();
}
}
+
+ private int getPhoneTypeFromProperty() {
+ int type =
+ SystemProperties.getInt(TelephonyProperties.CURRENT_ACTIVE_PHONE,
+ getPhoneTypeFromNetworkType());
+ return type;
+ }
+
+ private int getPhoneTypeFromNetworkType() {
+ // When the system property CURRENT_ACTIVE_PHONE, has not been set,
+ // use the system property for default network type.
+ // This is a fail safe, and can only happen at first boot.
+ int mode = SystemProperties.getInt("ro.telephony.default_network", -1);
+ if (mode == -1)
+ return PHONE_TYPE_NONE;
+ return PhoneFactory.getPhoneType(mode);
+ }
//
//
// Current Network
@@ -639,6 +664,11 @@
/** Data connection activity: Currently both sending and receiving
* IP PPP traffic. */
public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT;
+ /**
+ * Data connection is active, but physical link is down
+ * @hide
+ */
+ public static final int DATA_ACTIVITY_DORMANT = 0x00000004;
/**
* Returns a constant indicating the type of activity on a data connection
@@ -648,6 +678,7 @@
* @see #DATA_ACTIVITY_IN
* @see #DATA_ACTIVITY_OUT
* @see #DATA_ACTIVITY_INOUT
+ * @see #DATA_ACTIVITY_DORMANT
*/
public int getDataActivity() {
try {
@@ -729,4 +760,48 @@
// system process dead
}
}
+
+ /**
+ * Returns the CDMA ERI icon index to display
+ *
+ * @hide
+ */
+ public int getCdmaEriIconIndex() {
+ try {
+ return getITelephony().getCdmaEriIconIndex();
+ } catch (RemoteException ex) {
+ // the phone process is restarting.
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the CDMA ERI icon mode,
+ * 0 - ON
+ * 1 - FLASHING
+ *
+ * @hide
+ */
+ public int getCdmaEriIconMode() {
+ try {
+ return getITelephony().getCdmaEriIconMode();
+ } catch (RemoteException ex) {
+ // the phone process is restarting.
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the CDMA ERI text,
+ *
+ * @hide
+ */
+ public String getCdmaEriText() {
+ try {
+ return getITelephony().getCdmaEriText();
+ } catch (RemoteException ex) {
+ // the phone process is restarting.
+ return null;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java
index 0928ddf..84dfca0 100644
--- a/telephony/java/android/telephony/gsm/SmsMessage.java
+++ b/telephony/java/android/telephony/gsm/SmsMessage.java
@@ -21,6 +21,7 @@
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
@@ -369,7 +370,8 @@
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
- destinationAddress, message, statusReportRequested, header);
+ destinationAddress, message, statusReportRequested,
+ SmsHeader.fromByteArray(header));
} else {
spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
destinationAddress, message, statusReportRequested, header);
@@ -395,7 +397,7 @@
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
- destinationAddress, message, statusReportRequested);
+ destinationAddress, message, statusReportRequested, null);
} else {
spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
destinationAddress, message, statusReportRequested);
@@ -744,4 +746,3 @@
}
}
}
-
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index fbc596c..e78422e 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -54,34 +54,32 @@
protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList();
protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList();
+ protected RegistrantList mOtaSessionRegistrants = new RegistrantList();
+ protected RegistrantList mCallWaitingRegistrants = new RegistrantList();
+ protected RegistrantList mInformationRecordsRegistrants = new RegistrantList();
protected Registrant mUnsolOemHookRawRegistrant;
protected Registrant mSMSRegistrant;
protected Registrant mNITZTimeRegistrant;
protected Registrant mSignalStrengthRegistrant;
protected Registrant mUSSDRegistrant;
protected Registrant mSmsOnSimRegistrant;
- /** Registrant for handling SMS Status Reports */
protected Registrant mSmsStatusRegistrant;
- /** Registrant for handling Supplementary Service Notifications */
protected Registrant mSsnRegistrant;
protected Registrant mStkSessionEndRegistrant;
protected Registrant mStkProCmdRegistrant;
protected Registrant mStkEventRegistrant;
protected Registrant mStkCallSetUpRegistrant;
- /** Registrant for handling SIM/RUIM SMS storage full messages */
protected Registrant mIccSmsFullRegistrant;
- /** Registrant for handling Icc Refresh notifications */
+ protected Registrant mEmergencyCallbackModeRegistrant;
protected Registrant mIccRefreshRegistrant;
- /** Registrant for handling RING notifications */
protected Registrant mRingRegistrant;
- /** Registrant for handling RESTRICTED STATE changed notification */
protected Registrant mRestrictedStateRegistrant;
- //Network Mode received from PhoneFactory
+ // Network Mode received from PhoneFactory
protected int mNetworkMode;
- //CDMA subscription received from PhoneFactory
+ // CDMA subscription received from PhoneFactory
protected int mCdmaSubscription;
- //Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
+ // Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
protected int mPhoneType;
@@ -424,6 +422,10 @@
mIccRefreshRegistrant = new Registrant (h, what, obj);
}
+ public void setEmergencyCallbackMode(Handler h, int what, Object obj) {
+ mEmergencyCallbackModeRegistrant = new Registrant (h, what, obj);
+ }
+
public void unSetOnIccRefresh(Handler h) {
mIccRefreshRegistrant.clear();
}
@@ -470,6 +472,33 @@
mUnsolOemHookRawRegistrant.clear();
}
+ public void registerForOtaSessionStatus(Handler h, int what, Object obj){
+ Registrant r = new Registrant (h, what, obj);
+ mOtaSessionRegistrants.add(r);
+ }
+
+ public void unregisterForOtaSessionStatus(Handler h){
+ mOtaSessionRegistrants.remove(h);
+ }
+
+ public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+ Registrant r = new Registrant (h, what, obj);
+ mCallWaitingRegistrants.add(r);
+ }
+
+ public void unregisterForCdmaCallWaiting(Handler h){
+ mCallWaitingRegistrants.remove(h);
+ }
+
+ public void registerCdmaInformationRecord(Handler h, int what, Object obj) {
+ Registrant r = new Registrant (h, what, obj);
+ mInformationRecordsRegistrants.add(r);
+ }
+
+ public void unregisterCdmaInformationRecord(Handler h) {
+ mInformationRecordsRegistrants.remove(h);
+ }
+
//***** Protected Methods
/**
* Store new RadioState and send notification based on the changes
diff --git a/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java b/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java
new file mode 100644
index 0000000..690df05
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java
@@ -0,0 +1,201 @@
+/*
+ * 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.telephony;
+
+/**
+ * TODO(Teleca): This class was poorly implemented and didn't
+ * follow the Android coding conventions. It is now more or less
+ * follows the conventions but there is still some work, see the
+ * TODO's.
+ */
+
+
+public class CdmaInformationRecord {
+ public int messageName;
+
+ public CdmaDisplayInfoRec displayInfoRec;
+ public CdmaNumberInfoRec numberInfoRec;
+ public CdmaSignalInfoRec signalInfoRec;
+ public CdmaRedirectingNumberInfoRec redirectingNumberInfoRec;
+ public CdmaLineControlInfoRec lineControlInfoRec;
+ public CdmaT53ClirInfoRec cdmaT53ClirInfoRec;
+ public CdmaT53AudioControlInfoRec cdmaT53AudioControlInfoRec;
+
+ public static final int RIL_CDMA_DISPLAY_INFO_REC = 0;
+ public static final int RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC = 1;
+ public static final int RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC = 2;
+ public static final int RIL_CDMA_CONNECTED_NUMBER_INFO_REC = 3;
+ public static final int RIL_CDMA_SIGNAL_INFO_REC = 4;
+ public static final int RIL_CDMA_REDIRECTING_NUMBER_INFO_REC = 5;
+ public static final int RIL_CDMA_LINE_CONTROL_INFO_REC = 6;
+ public static final int RIL_CDMA_EXTENDED_DISPLAY_INFO_REC = 7;
+ public static final int RIL_CDMA_T53_CLIR_INFO_REC = 8;
+ public static final int RIL_CDMA_T53_RELEASE_INFO_REC = 9;
+ public static final int RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC = 10;
+
+ public CdmaInformationRecord(int messageName) {
+ this.messageName = messageName;
+ }
+
+ void createDisplayInfo(int length, char buffer[]) {
+ displayInfoRec = new CdmaDisplayInfoRec(length, buffer);
+ }
+
+ void createNumberInfo(int length, char buffer[]) {
+ numberInfoRec = new CdmaNumberInfoRec(length, buffer);
+ }
+
+ void createSignalInfo(char buffer[]) {
+ signalInfoRec = new CdmaSignalInfoRec(buffer);
+ }
+
+ void createRedirectingNumberInfo(int length, char buffer[], int reason) {
+ redirectingNumberInfoRec = new CdmaRedirectingNumberInfoRec(length, buffer, reason);
+ }
+
+ void createLineControlInfo(char buffer[]) {
+ lineControlInfoRec = new CdmaLineControlInfoRec(buffer);
+ }
+
+ void createT53ClirInfo(char buffer) {
+ cdmaT53ClirInfoRec = new CdmaT53ClirInfoRec(buffer);
+ }
+
+ void createT53AudioControlInfo(char ul, char dl) {
+ cdmaT53AudioControlInfoRec = new CdmaT53AudioControlInfoRec(ul, dl);
+ }
+
+ /**
+ * TODO(Teleca): Add comments for each class giving the
+ * document and section where the information is defined
+ * as shown CdmaSignalInfoRec. Also add a toString to
+ * each of these to ease debugging.
+ */
+
+ /**
+ * Signal Information record from 3GPP2 C.S005 3.7.5.5
+ */
+ public static class CdmaSignalInfoRec {
+ public boolean isPresent; /* non-zero if signal information record is present */
+ public int signalType;
+ public int alertPitch;
+ public int signalCode;
+
+ public CdmaSignalInfoRec() {}
+
+ public CdmaSignalInfoRec(char buffer[]) {
+ isPresent = buffer[0] == 1;
+ signalType = buffer[1];
+ alertPitch = buffer[2];
+ signalCode = buffer[3];
+ }
+
+ @Override
+ public String toString() {
+ return "CdmaSignalInfo: {" +
+ " isPresent: " + isPresent +
+ ", signalType: " + signalType +
+ ", alertPitch: " + alertPitch +
+ ", signalCode: " + signalCode +
+ " }";
+ }
+ }
+
+ public static class CdmaDisplayInfoRec {
+ public char alphaLen;
+ public char alphaBuf[];
+
+ public CdmaDisplayInfoRec(int length, char buffer[]) {
+ alphaLen = (char)length;
+ alphaBuf = new char[length];
+ for(int i = 0; i < length; i++)
+ alphaBuf[i] = buffer[i];
+ }
+ }
+
+ public static class CdmaNumberInfoRec {
+ public int len;
+ public char buf[];
+ public char numberType;
+ public char numberPlan;
+ public char pi; // TODO(Teleca): poor name, no meaning
+ public char si; // TODO(Teleca): poor name
+
+ public CdmaNumberInfoRec(int length, char buffer[]) {
+ int i;
+
+ len = length;
+ buf = new char[length];
+ for (i = 0; i < len; i++) {
+ buf[i] = buffer[i];
+ }
+
+ numberType = buffer[i++];
+ numberPlan = buffer[i++];
+ pi = buffer[i++];
+ si = buffer[i++];
+ }
+ }
+
+ public static class CdmaRedirectingNumberInfoRec {
+ public static final int REASON_UNKNOWN = 0;
+ public static final int REASON_CALL_FORWARDING_BUSY = 1;
+ public static final int REASON_CALL_FORWARDING_NO_REPLY = 2;
+ public static final int REASON_CALLED_DTE_OUT_OF_ORDER = 9;
+ public static final int REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10;
+ public static final int REASON_CALL_FORWARDING_UNCONDITIONAL = 15;
+
+ public CdmaNumberInfoRec numberInfoRec;
+ public int redirectingReason;
+
+ public CdmaRedirectingNumberInfoRec(int length, char buffer[], int reason) {
+ numberInfoRec = new CdmaNumberInfoRec(length, buffer);
+ redirectingReason = reason;
+ }
+ }
+
+ public static class CdmaLineControlInfoRec {
+ public char lineCtrlPolarityIncluded;
+ public char lineCtrlToggle;
+ public char lineCtrlReverse;
+ public char lineCtrlPowerDenial;
+
+ CdmaLineControlInfoRec(char buffer[]) {
+ lineCtrlPolarityIncluded = buffer[0];
+ lineCtrlToggle = buffer[1];
+ lineCtrlReverse = buffer[2];
+ lineCtrlPowerDenial = buffer[3];
+ }
+ }
+
+ // TODO(Teleca): A class for a single character, is this needed?
+ public static class CdmaT53ClirInfoRec {
+ public char cause;
+
+ public CdmaT53ClirInfoRec(char buffer) {
+ cause = buffer;
+ }
+ }
+
+ public static class CdmaT53AudioControlInfoRec {
+ public char uplink;
+ public char downlink;
+
+ public CdmaT53AudioControlInfoRec(char ul, char dl) {
+ uplink = ul;
+ downlink = dl;
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index 5a1bb7e..ddf6b50 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -241,6 +241,24 @@
void unregisterForRUIMReady(Handler h);
/**
+ * Registers for the status of an OTASP/OTAPA session
+ */
+ void registerForOtaSessionStatus(Handler h, int what, Object obj);
+ void unregisterForOtaSessionStatus(Handler h);
+
+ /**
+ * register for Call waiting for CDMA
+ */
+ void registerForCdmaCallWaiting(Handler h, int what, Object obj);
+ void unregisterForCdmaCallWaiting(Handler h);
+
+ /**
+ * Registers for CDMA information records
+ */
+ void registerCdmaInformationRecord(Handler h, int what, Object obj);
+ void unregisterCdmaInformationRecord(Handler h);
+
+ /**
* unlike the register* methods, there's only one new SMS handler
* if you need to unregister, you should also tell the radio to stop
* sending SMS's to you (via AT+CNMI)
@@ -326,6 +344,16 @@
void unSetOnIccSmsFull(Handler h);
/**
+ * Sets the handler for Emergency call-back Mode enter mesage.
+ * Unlike the register* methods, there's only one notification handler
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void setEmergencyCallbackMode(Handler h, int what, Object obj);
+
+ /**
* Sets the handler for SIM Refresh notifications.
* Unlike the register* methods, there's only one notification handler
*
@@ -348,12 +376,12 @@
void unSetOnCallRing(Handler h);
/**
- * Sets the handler for RESTRICTED_STATE changed notification,
+ * Sets the handler for RESTRICTED_STATE changed notification,
* eg, for Domain Specific Access Control
* unlike the register* methods, there's only one signal strength handler
- *
- * AsyncResult.result is an int[1]
- * response.obj.result[0] is a bitmask of RIL_RESTRICTED_STATE_* values
+ *
+ * AsyncResult.result is an int[1]
+ * response.obj.result[0] is a bitmask of RIL_RESTRICTED_STATE_* values
*/
void setOnRestrictedStateChanged(Handler h, int what, Object obj);
@@ -516,7 +544,7 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
- * ar.result contains a List of PDPContextState
+ * ar.result contains a List of DataCallState
* @deprecated
*/
void getPDPContextList(Message result);
@@ -526,7 +554,7 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
- * ar.result contains a List of PDPContextState
+ * ar.result contains a List of DataCallState
*/
void getDataCallList(Message result);
@@ -767,6 +795,12 @@
*/
void stopDtmf(Message result);
+ /**
+ * ar.exception carries exception on failure
+ * ar.userObject contains the orignal value of result.obj
+ * ar.result is null on success and failure
+ */
+ void sendBurstDtmf(String dtmfString, Message result);
/**
* smscPDU is smsc address in PDU form GSM BCD format prefixed
@@ -1087,13 +1121,12 @@
public void getDeviceIdentity(Message response);
/**
- * Request the device IMSI_M / MDN / AH_SID / H_SID / H_NID.
+ * Request the device MDN / H_SID / H_NID / MIN.
* "response" is const char **
- * [0] is IMSI_M if CDMA subscription is available
- * [1] is MDN if CDMA subscription is available
- * [2] is AH_SID (Analog Home SID) if CDMA subscription
- * [3] is H_SID (Home SID) if CDMA subscription is available
- * [4] is H_NID (Home SID) if CDMA subscription is available
+ * [0] is MDN if CDMA subscription is available
+ * [1] is H_SID (Home SID) if CDMA subscription is available
+ * [2] is H_NID (Home NID) if CDMA subscription is available
+ * [3] is MIN (10 digits, MIN2+MIN1) if CDMA subscription is available
*/
public void getCDMASubscription(Message response);
@@ -1133,7 +1166,7 @@
* @param enable is true to enable, false to disable
* @param response is callback message
*/
- void setTTYModeEnabled(boolean enable, Message response);
+ void setTTYMode(int ttyMode, Message response);
/**
* Query the TTY mode for the CDMA phone
@@ -1142,7 +1175,7 @@
*
* @param response is callback message
*/
- void queryTTYModeEnabled(Message response);
+ void queryTTYMode(Message response);
/**
* Setup a packet data connection On successful completion, the result
@@ -1196,6 +1229,10 @@
* @param result
* Callback message is empty on completion
*/
+ /**
+ * TODO(Teleca): configValuesArray is represented as a RIL_BroadcastSMSConfig
+ * so we think this should be a class with the appropriate parameters not an array?
+ */
public void setCdmaBroadcastConfig(int[] configValuesArray, Message result);
/**
@@ -1205,4 +1242,10 @@
* Callback message contains the configuration from the modem on completion
*/
public void getCdmaBroadcastConfig(Message result);
+
+ /**
+ * Requests the radio's system selection module to exit emergency callback mode.
+ * @param response callback message
+ */
+ public void exitEmergencyCallbackMode(Message response);
}
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index 86ceb89..c6bbf82 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -29,25 +29,34 @@
public enum DisconnectCause {
- NOT_DISCONNECTED, /* has not yet disconnected */
- INCOMING_MISSED, /* an incoming call that was missed and never answered */
- NORMAL, /* normal; remote */
- LOCAL, /* normal; local hangup */
- BUSY, /* outgoing call to busy line */
- CONGESTION, /* outgoing call to congested network */
- MMI, /* not presently used; dial() returns null */
- INVALID_NUMBER, /* invalid dial string */
+ NOT_DISCONNECTED, /* has not yet disconnected */
+ INCOMING_MISSED, /* an incoming call that was missed and never answered */
+ NORMAL, /* normal; remote */
+ LOCAL, /* normal; local hangup */
+ BUSY, /* outgoing call to busy line */
+ CONGESTION, /* outgoing call to congested network */
+ MMI, /* not presently used; dial() returns null */
+ INVALID_NUMBER, /* invalid dial string */
LOST_SIGNAL,
- LIMIT_EXCEEDED, /* eg GSM ACM limit exceeded */
- INCOMING_REJECTED, /* an incoming call that was rejected */
- POWER_OFF, /* radio is turned off explicitly */
- OUT_OF_SERVICE, /* out of service */
- ICC_ERROR, /* No ICC, ICC locked, or other ICC error */
- CALL_BARRED, /* call was blocked by call barrring */
- FDN_BLOCKED, /* call was blocked by fixed dial number */
- CS_RESTRICTED, /* call was blocked by restricted all voice access */
- CS_RESTRICTED_NORMAL,/* call was blocked by restricted normal voice access */
- CS_RESTRICTED_EMERGENCY/* call was blocked by restricted emergency voice access */
+ LIMIT_EXCEEDED, /* eg GSM ACM limit exceeded */
+ INCOMING_REJECTED, /* an incoming call that was rejected */
+ POWER_OFF, /* radio is turned off explicitly */
+ OUT_OF_SERVICE, /* out of service */
+ ICC_ERROR, /* No ICC, ICC locked, or other ICC error */
+ CALL_BARRED, /* call was blocked by call barrring */
+ FDN_BLOCKED, /* call was blocked by fixed dial number */
+ CS_RESTRICTED, /* call was blocked by restricted all voice access */
+ CS_RESTRICTED_NORMAL, /* call was blocked by restricted normal voice access */
+ CS_RESTRICTED_EMERGENCY, /* call was blocked by restricted emergency voice access */
+ CDMA_LOCKED_UNTIL_POWER_CYCLE, /* MS is locked until next power cycle */
+ CDMA_DROP,
+ CDMA_INTERCEPT, /* INTERCEPT order received, MS state idle entered */
+ CDMA_REORDER, /* MS has been redirected, call is cancelled */
+ CDMA_SO_REJECT, /* service option rejection */
+ CDMA_RETRY_ORDER, /* requeseted service is rejected, retry delay is set */
+ CDMA_ACCESS_FAILURE,
+ CDMA_PREEMPTED,
+ CDMA_NOT_EMERGENCY /* not an emergency call */
}
Object userData;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
similarity index 63%
rename from telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
rename to telephony/java/com/android/internal/telephony/DataCallState.java
index 31cdacf..d0f3d24 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * 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.
@@ -14,25 +15,18 @@
* limitations under the License.
*/
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
-/**
- * {@hide}
- */
-public class PDPContextState {
+public class DataCallState {
public int cid;
public int active;
public String type;
public String apn;
public String address;
+ @Override
public String toString() {
- return "com.android.internal.telephony.gsm.PDPContextState: {" +
- " cid: " + cid +
- ", active: " + active +
- ", type: " + type +
- ", apn: " + apn +
- ", address: " + address +
- " }";
+ return "DataCallState: {" + " cid: " + cid + ", active: " + active + ", type: " + type
+ + ", apn: " + apn + ", address: " + address + " }";
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 5b826b2..d23af1f 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -63,7 +63,8 @@
NONE,
DATAIN,
DATAOUT,
- DATAINANDOUT
+ DATAINANDOUT,
+ DORMANT
}
//***** Event Codes
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 79b4afe..d6151c6 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -62,7 +62,7 @@
public void notifySignalStrength(Phone sender) {
try {
- mRegistry.notifySignalStrength(sender.getSignalStrengthASU());
+ mRegistry.notifySignalStrength(sender.getSignalStrength());
} catch (RemoteException ex) {
// system process is dead
}
@@ -200,6 +200,8 @@
return TelephonyManager.DATA_ACTIVITY_OUT;
case DATAINANDOUT:
return TelephonyManager.DATA_ACTIVITY_INOUT;
+ case DORMANT:
+ return TelephonyManager.DATA_ACTIVITY_DORMANT;
default:
return TelephonyManager.DATA_ACTIVITY_NONE;
}
@@ -217,6 +219,8 @@
return Phone.DataActivityState.DATAOUT;
case TelephonyManager.DATA_ACTIVITY_INOUT:
return Phone.DataActivityState.DATAINANDOUT;
+ case TelephonyManager.DATA_ACTIVITY_DORMANT:
+ return Phone.DataActivityState.DORMANT;
default:
return Phone.DataActivityState.NONE;
}
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 8f4c69c..8e2941b 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -182,7 +182,7 @@
return stringToGsm7BitPacked(data);
}
- int headerBits = header.length * 8;
+ int headerBits = (header.length + 1) * 8;
int headerSeptets = headerBits / 7;
headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
@@ -194,7 +194,8 @@
(headerSeptets*7), true);
// Paste in the header
- System.arraycopy(header, 0, ret, 1, header.length);
+ ret[1] = (byte)header.length;
+ System.arraycopy(header, 0, ret, 2, header.length);
return ret;
}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index e0884b3..0202ec8 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -18,6 +18,7 @@
import android.os.Bundle;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
oneway interface IPhoneStateListener {
void onServiceStateChanged(in ServiceState serviceState);
@@ -30,5 +31,6 @@
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state);
void onDataActivity(int direction);
+ void onSignalStrengthsChanged(in SignalStrength signalStrength);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bab0603..cc6b452 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -221,5 +221,22 @@
*/
int getActivePhoneType();
+ /**
+ * Returns the CDMA ERI icon index to display
+ */
+ int getCdmaEriIconIndex();
+
+ /**
+ * Returns the CDMA ERI icon mode,
+ * 0 - ON
+ * 1 - FLASHING
+ */
+ int getCdmaEriIconMode();
+
+ /**
+ * Returns the CDMA ERI text,
+ */
+ String getCdmaEriText();
+
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 1b011fe..865c6ca 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,6 +19,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import com.android.internal.telephony.IPhoneStateListener;
interface ITelephonyRegistry {
@@ -26,7 +27,7 @@
void notifyCallState(int state, String incomingNumber);
void notifyServiceState(in ServiceState state);
- void notifySignalStrength(int signalStrengthASU);
+ void notifySignalStrength(in SignalStrength signalStrength);
void notifyMessageWaitingChanged(boolean mwi);
void notifyCallForwardingChanged(boolean cfi);
void notifyDataActivity(int state);
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index 014fbb6..7eafafd 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -61,4 +61,5 @@
static final String DF_TELECOM = "7F10";
static final String DF_GRAPHICS = "5F50";
static final String DF_GSM = "7F20";
+ static final String DF_CDMA = "7F25";
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 03c1c56..4d0cf41 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -23,6 +23,7 @@
import android.preference.PreferenceManager;
import android.telephony.CellLocation;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.gsm.NetworkInfo;
@@ -82,9 +83,11 @@
* <li>DATAIN = Receiving IP ppp traffic</li>
* <li>DATAOUT = Sending IP ppp traffic</li>
* <li>DATAINANDOUT = Both receiving and sending IP ppp traffic</li>
+ * <li>DORMANT = The data connection is still active,
+ but physical link is down</li>
* </ul>
*/
- NONE, DATAIN, DATAOUT, DATAINANDOUT;
+ NONE, DATAIN, DATAOUT, DATAINANDOUT, DORMANT;
};
enum SuppService {
@@ -150,7 +153,7 @@
static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
static final String REASON_SIM_LOADED = "simLoaded";
-
+
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
static final int BM_EURO_BAND = 1; // GSM-900 / DCS-1800 / WCDMA-IMT-2000
@@ -162,28 +165,35 @@
// Used for preferred network type
// Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
- int NT_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
- int NT_MODE_GSM_ONLY = 1; /* GSM only */
- int NT_MODE_WCDMA_ONLY = 2; /* WCDMA only */
- int NT_MODE_GSM_UMTS = 3; /* GSM/WCDMA (auto mode, according to PRL)
- AVAILABLE Application Settings menu*/
- int NT_MODE_CDMA = 4; /* CDMA and EvDo (auto mode, according to PRL)
- AVAILABLE Application Settings menu*/
- int NT_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
- int NT_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
- int NT_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
- AVAILABLE Application Settings menu*/
- int PREFERRED_NT_MODE = NT_MODE_GSM_ONLY;
+ int NT_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
+ int NT_MODE_GSM_ONLY = RILConstants.NETWORK_MODE_GSM_ONLY;
+ int NT_MODE_WCDMA_ONLY = RILConstants.NETWORK_MODE_WCDMA_ONLY;
+ int NT_MODE_GSM_UMTS = RILConstants.NETWORK_MODE_GSM_UMTS;
+
+ int NT_MODE_CDMA = RILConstants.NETWORK_MODE_CDMA;
+
+ int NT_MODE_CDMA_NO_EVDO = RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
+ int NT_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
+ int NT_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
+
+ int PREFERRED_NT_MODE = RILConstants.PREFERRED_NETWORK_MODE;
// Used for CDMA roaming mode
- static final int CDMA_RM_HOME = 0; //Home Networks only, as defined in PRL
- static final int CDMA_RM_AFFILIATED = 1; //Roaming an Affiliated networks, as defined in PRL
- static final int CDMA_RM_ANY = 2; //Roaming on Any Network, as defined in PRL
+ static final int CDMA_RM_HOME = 0; // Home Networks only, as defined in PRL
+ static final int CDMA_RM_AFFILIATED = 1; // Roaming an Affiliated networks, as defined in PRL
+ static final int CDMA_RM_ANY = 2; // Roaming on Any Network, as defined in PRL
// Used for CDMA subscription mode
- static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; //RUIM/SIM (default)
- static final int CDMA_SUBSCRIPTION_NV = 1; //NV -> non-volatile memory
+ static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; // RUIM/SIM (default)
+ static final int CDMA_SUBSCRIPTION_NV = 1; // NV -> non-volatile memory
+
+ static final int PREFERRED_CDMA_SUBSCRIPTION = CDMA_SUBSCRIPTION_NV;
+
+ static final int TTY_MODE_OFF = 0;
+ static final int TTY_MODE_FULL = 1;
+ static final int TTY_MODE_HCO = 2;
+ static final int TTY_MODE_VCO = 3;
/**
* Get the current ServiceState. Use
@@ -263,16 +273,11 @@
String getActiveApn();
/**
- * Get current signal strength. No change notification available on this
- * interface. Use <code>PhoneStateNotifier</code> or an equivalent.
- * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu).
- * The following special values are defined:</p>
- * <ul><li>0 means "-113 dBm or less".</li>
- * <li>31 means "-51 dBm or greater".</li></ul>
+ * Get current signal strength.
*
- * @return Current signal strength in ASU's.
+ * @return Current signal strength as SignalStrength
*/
- int getSignalStrengthASU();
+ SignalStrength getSignalStrength();
/**
* Notifies when a previously untracked non-ringing/waiting connection has appeared.
@@ -494,6 +499,53 @@
void unregisterForInCallVoicePrivacyOff(Handler h);
/**
+ * Register for notifications about information record available
+ *
+ * @param h Handler that receives the notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void registerCdmaInformationRecord(Handler h, int what, Object obj);
+
+ /**
+ * Unregister for notifications about information record available
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ void unregisterCdmaInformationRecord(Handler h);
+
+ /**
+ * Register for the indication of OTA status change
+ *
+ * @param h Handler that receives the notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void registerForOtaStatusChange(Handler h, int what, Object obj);
+
+ /**
+ * Unregister for the indication of OTA status change
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ void unregisterForOtaStatusChange(Handler h);
+
+ /**
+ * Register for the indication of Cdma Call Waiting
+ *
+ * @param h Handler that receives the notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void registerForCdmaCallWaiting(Handler h, int what, Object obj);
+
+ /**
+ * Unregister for the indication of Cdma Call Waiting
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ void unregisterForCdmaCallWaiting(Handler h);
+ /**
* Returns SIM record load state. Use
* <code>getSimCard().registerForReady()</code> for change notification.
*
@@ -707,6 +759,10 @@
*/
void stopDtmf();
+ /**
+ * Play a Burst of DTMF tone on the active call. Ignored if there is no active call.
+ */
+ void sendBurstDtmf(String dtmfString);
/**
* Sets the radio power on/off state (off is sometimes
@@ -1279,6 +1335,10 @@
//***** CDMA support methods
+ /**
+ * Retrieves the MIN for CDMA phones.
+ */
+ String getMin();
/**
* Retrieves the ESN for CDMA phones.
@@ -1306,22 +1366,30 @@
public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager();
/**
- * setTTYModeEnabled
+ * setTTYMode
* sets a TTY mode option.
*
* @param enable is a boolean representing the state that you are
* requesting, true for enabled, false for disabled.
* @param onComplete a callback message when the action is completed
*/
- void setTTYModeEnabled(boolean enable, Message onComplete);
+ void setTTYMode(int ttyMode, Message onComplete);
/**
- * queryTTYModeEnabled
+ * queryTTYMode
* query the status of the TTY mode
*
* @param onComplete a callback message when the action is completed.
*/
- void queryTTYModeEnabled(Message onComplete);
+ void queryTTYMode(Message onComplete);
+
+ /**
+ * exitEmergencyCallbackMode
+ * exits the emergency callback mode
+ *
+ * @param onComplete a callback message when the action is completed.
+ */
+ void exitEmergencyCallbackMode(Message onComplete);
/**
* Activate or deactivate cell broadcast SMS.
@@ -1344,10 +1412,30 @@
/**
* Configure cell broadcast SMS.
*
+ * TODO: Change the configValuesArray to a RIL_BroadcastSMSConfig
+ *
* @param response
* Callback message is empty on completion
*/
public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response);
public void notifyDataActivity();
+
+ /**
+ * Returns the CDMA ERI icon index to display
+ */
+ public int getCdmaEriIconIndex();
+
+ /**
+ * Returns the CDMA ERI icon mode,
+ * 0 - ON
+ * 1 - FLASHING
+ */
+ public int getCdmaEriIconMode();
+
+ /**
+ * Returns the CDMA ERI text,
+ */
+ public String getCdmaEriText();
+
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 0314034..7234aa3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -29,6 +29,7 @@
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.text.TextUtils;
import android.util.Log;
@@ -52,6 +53,15 @@
*
*/
+/**
+ * TODO(Teleca): This has a multitude of methods that are CDMA specific
+ * , (registerForVoicePrivacy, registerCdmaInformationRecord, registerCdmaCallWaiting,
+ * setCdmaRoamingPreference, setCdmaSubscription, getCdmaEriIcon, getCdmaEriText, ...) can
+ * these type of calls be more abstract. For example CallWaiting is common between the GSM/CDMA
+ * it would seem that doesn't need to be cdma specific. Also, should the application be directly
+ * dealing with the CdmaInformationRecord's could they be abstracted to something more generic.
+ */
+
public abstract class PhoneBase implements Phone {
private static final String LOG_TAG = "PHONE";
private static final boolean LOCAL_DEBUG = true;
@@ -90,6 +100,8 @@
protected static final int EVENT_RUIM_RECORDS_LOADED = 21;
protected static final int EVENT_NV_READY = 22;
protected static final int EVENT_SET_ENHANCED_VP = 23;
+ protected static final int EVENT_CDMA_CALL_WAITING = 24;
+ protected static final int EVENT_EMERGENCY_CALLBACK_MODE = 25;
// Key used to read/write current CLIR setting
public static final String CLIR_KEY = "clir_key";
@@ -187,7 +199,7 @@
setUnitTestMode(unitTestMode);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
- mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
+ mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
}
// Inherited documentation suffices.
@@ -204,7 +216,7 @@
mDnsCheckDisabled = b;
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
+ editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
editor.commit();
}
@@ -282,6 +294,35 @@
mCM.unregisterForInCallVoicePrivacyOff(h);
}
+ // Inherited documentation suffices.
+ public void registerForOtaStatusChange(Handler h, int what, Object obj){
+ mCM.registerForOtaSessionStatus(h,what,obj);
+ }
+
+ // Inherited documentation suffices.
+ public void unregisterForOtaStatusChange(Handler h){
+ mCM.unregisterForOtaSessionStatus(h);
+ }
+
+ // Inherited documentation suffices.
+ public void registerCdmaInformationRecord(Handler h, int what, Object obj){
+ mCM.registerCdmaInformationRecord(h,what,obj);
+ }
+
+ // Inherited documentation suffices.
+ public void unregisterCdmaInformationRecord(Handler h){
+ mCM.unregisterCdmaInformationRecord(h);
+ }
+
+ // Inherited documentation suffices.
+ public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+ mCM.registerForCdmaCallWaiting(h,what,obj);
+ }
+
+ // Inherited documentation suffices.
+ public void unregisterForCdmaCallWaiting(Handler h){
+ mCM.unregisterForCdmaCallWaiting(h);
+ }
/**
* Notifiy registrants of a new ringing Connection.
@@ -567,9 +608,6 @@
mCM.setPreferredNetworkType(networkType, response);
}
- /**
- * Set the status of the preferred Network Type: Global, CDMA only or GSM/UMTS only
- */
public void getPreferredNetworkType(Message response) {
mCM.getPreferredNetworkType(response);
}
@@ -582,12 +620,20 @@
mCM.setSmscAddress(address, result);
}
- public void setTTYModeEnabled(boolean enable, Message onComplete) {
+ public void setTTYMode(int ttyMode, Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
- public void queryTTYModeEnabled(Message onComplete) {
+ public void queryTTYMode(Message onComplete) {
+ // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+ Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ }
+
+ /**
+ * Send the exit emergency callback mode message
+ */
+ public void exitEmergencyCallbackMode(Message onComplete) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
@@ -638,4 +684,30 @@
public abstract String getPhoneName();
+ /**
+ * Returns the CDMA ERI icon index to display
+ */
+ public int getCdmaEriIconIndex() {
+ Log.e(LOG_TAG, "Error! getCdmaEriIconIndex should never be executed in GSM mode");
+ return -1;
+ }
+
+ /**
+ * Returns the CDMA ERI icon mode,
+ * 0 - ON
+ * 1 - FLASHING
+ */
+ public int getCdmaEriIconMode() {
+ Log.e(LOG_TAG, "Error! getCdmaEriIconMode should never be executed in GSM mode");
+ return -1;
+ }
+
+ /**
+ * Returns the CDMA ERI text,
+ */
+ public String getCdmaEriText() {
+ Log.e(LOG_TAG, "Error! getCdmaEriText should never be executed in GSM mode");
+ return "GSM nw, no ERI";
+ }
+
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 86e2f04..a84f74e 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -107,30 +107,49 @@
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
- switch(networkMode) {
- case RILConstants.NETWORK_MODE_CDMA:
- case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
- case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
- case RILConstants.NETWORK_MODE_GLOBAL:
- sProxyPhone = new PhoneProxy(new CDMAPhone(context,
- sCommandsInterface, sPhoneNotifier));
- Log.i(LOG_TAG, "Creating CDMAPhone");
- break;
- case RILConstants.NETWORK_MODE_WCDMA_PREF:
- case RILConstants.NETWORK_MODE_GSM_ONLY:
- case RILConstants.NETWORK_MODE_WCDMA_ONLY:
- case RILConstants.NETWORK_MODE_GSM_UMTS:
- default:
- sProxyPhone = new PhoneProxy(new GSMPhone(context,
- sCommandsInterface, sPhoneNotifier));
- Log.i(LOG_TAG, "Creating GSMPhone");
- break;
+ int phoneType = getPhoneType(networkMode);
+ if (phoneType == RILConstants.GSM_PHONE) {
+ sProxyPhone = new PhoneProxy(new GSMPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ Log.i(LOG_TAG, "Creating GSMPhone");
+ } else if (phoneType == RILConstants.CDMA_PHONE) {
+ sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ Log.i(LOG_TAG, "Creating CDMAPhone");
}
+
sMadeDefaults = true;
}
}
}
+ /*
+ * This function returns the type of the phone, depending
+ * on the network mode.
+ *
+ * @param network mode
+ * @return Phone Type
+ */
+ public static int getPhoneType(int networkMode) {
+ switch(networkMode) {
+ case RILConstants.NETWORK_MODE_CDMA:
+ case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+ case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+ return RILConstants.CDMA_PHONE;
+
+ case RILConstants.NETWORK_MODE_WCDMA_PREF:
+ case RILConstants.NETWORK_MODE_GSM_ONLY:
+ case RILConstants.NETWORK_MODE_WCDMA_ONLY:
+ case RILConstants.NETWORK_MODE_GSM_UMTS:
+ return RILConstants.GSM_PHONE;
+
+ case RILConstants.NETWORK_MODE_GLOBAL:
+ return RILConstants.CDMA_PHONE;
+ default:
+ return RILConstants.GSM_PHONE;
+ }
+ }
+
public static Phone getDefaultPhone() {
if (sLooper != Looper.myLooper()) {
throw new RuntimeException(
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index b76d801..a329cbb 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -26,6 +26,7 @@
import android.preference.PreferenceManager;
import android.telephony.CellLocation;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.util.Log;
import com.android.internal.telephony.cdma.CDMAPhone;
@@ -127,10 +128,9 @@
Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
ActivityManagerNative.broadcastStickyIntent(intent, null);
-
break;
default:
- Log.e(LOG_TAG, "Error! This handler was not registered for this message type. Message: "
+ Log.e(LOG_TAG,"Error! This handler was not registered for this message type. Message: "
+ msg.what);
break;
}
@@ -198,8 +198,8 @@
return mActivePhone.getActiveApn();
}
- public int getSignalStrengthASU() {
- return mActivePhone.getSignalStrengthASU();
+ public SignalStrength getSignalStrength() {
+ return mActivePhone.getSignalStrength();
}
public void registerForUnknownConnection(Handler h, int what, Object obj) {
@@ -306,6 +306,30 @@
mActivePhone.unregisterForInCallVoicePrivacyOff(h);
}
+ public void registerCdmaInformationRecord(Handler h, int what, Object obj) {
+ mActivePhone.registerCdmaInformationRecord(h,what,obj);
+ }
+
+ public void unregisterCdmaInformationRecord(Handler h) {
+ mActivePhone.unregisterCdmaInformationRecord(h);
+ }
+
+ public void registerForOtaStatusChange(Handler h, int what, Object obj){
+ mActivePhone.registerForOtaStatusChange(h,what,obj);
+ }
+
+ public void unregisterForOtaStatusChange(Handler h){
+ mActivePhone.unregisterForOtaStatusChange(h);
+ }
+
+ public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+ mActivePhone.registerForCdmaCallWaiting(h,what,obj);
+ }
+
+ public void unregisterForCdmaCallWaiting(Handler h){
+ mActivePhone.unregisterForCdmaCallWaiting(h);
+ }
+
public boolean getIccRecordsLoaded() {
return mActivePhone.getIccRecordsLoaded();
}
@@ -390,6 +414,10 @@
mActivePhone.stopDtmf();
}
+ public void sendBurstDtmf(String dtmfString) {
+ mActivePhone.sendBurstDtmf(dtmfString);
+ }
+
public void setRadioPower(boolean power) {
mActivePhone.setRadioPower(power);
}
@@ -628,6 +656,10 @@
return mActivePhone.getIccSerialNumber();
}
+ public String getMin() {
+ return mActivePhone.getMin();
+ }
+
public String getEsn() {
return mActivePhone.getEsn();
}
@@ -648,12 +680,16 @@
return mActivePhone.getIccPhoneBookInterfaceManager();
}
- public void setTTYModeEnabled(boolean enable, Message onComplete) {
- mActivePhone.setTTYModeEnabled(enable, onComplete);
+ public void setTTYMode(int ttyMode, Message onComplete) {
+ mActivePhone.setTTYMode(ttyMode, onComplete);
}
- public void queryTTYModeEnabled(Message onComplete) {
- mActivePhone.queryTTYModeEnabled(onComplete);
+ public void queryTTYMode(Message onComplete) {
+ mActivePhone.queryTTYMode(onComplete);
+ }
+
+ public void exitEmergencyCallbackMode(Message onComplete) {
+ mActivePhone.exitEmergencyCallbackMode(onComplete);
}
public void activateCellBroadcastSms(int activate, Message response) {
@@ -679,5 +715,17 @@
public void setSmscAddress(String address, Message result) {
mActivePhone.setSmscAddress(address, result);
}
+
+ public int getCdmaEriIconIndex() {
+ return mActivePhone.getCdmaEriIconIndex();
+ }
+
+ public int getCdmaEriIconMode() {
+ return mActivePhone.getCdmaEriIconMode();
+ }
+
+ public String getCdmaEriText() {
+ return mActivePhone.getCdmaEriText();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index fd822cd..b31161c 100644
--- a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -23,6 +23,7 @@
import android.os.Handler;
import android.os.Message;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -39,8 +40,6 @@
private static final String LOG_TAG = "PHONE";
private static final boolean DBG = false;
- public static final String INTENT_KEY_ASU = "asu";
-
private static final int NOTIF_PHONE = 1 << 0;
private static final int NOTIF_SERVICE = 1 << 1;
private static final int NOTIF_SIGNAL = 1 << 2;
@@ -49,7 +48,8 @@
Phone.State mPhoneState = Phone.State.IDLE;
ServiceState mServiceState = new ServiceState();
- int mAsu = -1;
+ SignalStrength mSignalStrength = new SignalStrength();
+
private Context mContext;
private Handler mTarget;
private IntentFilter mFilter;
@@ -106,12 +106,14 @@
* Throws RuntimeException if client has not called notifySignalStrength()
*/
public int getSignalStrength() {
+ // TODO: use new SignalStrength instead of asu
if ((mWants & NOTIF_SIGNAL) == 0) {
throw new RuntimeException
("client must call notifySignalStrength(int)");
}
+ int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
- return mAsu;
+ return (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
}
/**
@@ -129,10 +131,15 @@
int dBm = -1;
- if (mAsu != -1) {
- dBm = -113 + 2*mAsu;
+ if(!mSignalStrength.isGsm()) {
+ dBm = mSignalStrength.getCdmaDbm();
+ } else {
+ int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
+ int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
+ if (asu != -1) {
+ dBm = -113 + 2*asu;
+ }
}
-
return dBm;
}
@@ -180,8 +187,7 @@
try {
if (TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED.equals(action)) {
- mAsu = intent.getIntExtra(INTENT_KEY_ASU, mAsu);
- if (DBG) Log.d(LOG_TAG, "onReceiveIntent: set asu=" + mAsu);
+ mSignalStrength = SignalStrength.newFromBundle(intent.getExtras());
if (mTarget != null && getNotifySignalStrength()) {
Message message = Message.obtain(mTarget, mAsuEventWhat);
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index be18a39..070d233 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -38,8 +38,10 @@
import android.util.Config;
import android.util.Log;
+import com.android.internal.telephony.CdmaInformationRecord;
+import com.android.internal.telephony.cdma.CdmaCallWaiting;
+import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.gsm.NetworkInfo;
-import com.android.internal.telephony.gsm.PDPContextState;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import java.io.ByteArrayInputStream;
@@ -233,6 +235,7 @@
private static final int CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES = 31;
BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
sendScreenState(true);
@@ -562,18 +565,22 @@
mNetworkMode = networkMode;
//At startup mPhoneType is first set from networkMode
switch(networkMode) {
- case RILConstants.NETWORK_MODE_CDMA:
- case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
- case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
- case RILConstants.NETWORK_MODE_GLOBAL:
- mPhoneType = RILConstants.CDMA_PHONE;
- break;
case RILConstants.NETWORK_MODE_WCDMA_PREF:
case RILConstants.NETWORK_MODE_GSM_ONLY:
case RILConstants.NETWORK_MODE_WCDMA_ONLY:
case RILConstants.NETWORK_MODE_GSM_UMTS:
- default:
mPhoneType = RILConstants.GSM_PHONE;
+ break;
+ case RILConstants.NETWORK_MODE_CDMA:
+ case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+ case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+ mPhoneType = RILConstants.CDMA_PHONE;
+ break;
+ case RILConstants.NETWORK_MODE_GLOBAL:
+ mPhoneType = RILConstants.CDMA_PHONE;
+ break;
+ default:
+ mPhoneType = RILConstants.CDMA_PHONE;
}
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -1052,6 +1059,16 @@
send(rr);
}
+ public void
+ sendBurstDtmf(String dtmfString, Message result) {
+ RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BURST_DTMF, result);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+ rr.mp.writeString(dtmfString);
+
+ send(rr);
+ }
public void
sendSMS (String smscPDU, String pdu, Message result) {
@@ -1361,6 +1378,7 @@
if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)
+ " 0x" + Integer.toHexString(command)
+ " 0x" + Integer.toHexString(fileid) + " "
+ + " path: " + path + ","
+ p1 + "," + p2 + "," + p3);
send(rr);
@@ -1793,7 +1811,8 @@
rr.mp.writeInt(1);
rr.mp.writeInt(on ? 1 : 0);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
+ if (RILJ_LOGD) riljLog(rr.serialString()
+ + "> " + requestToString(rr.mRequest) + ": " + on);
send(rr);
}
@@ -1838,7 +1857,7 @@
* and/or radio knowing.
*/
if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
- setRadioPower(false, null);
+ setRadioPower(false, null);
} else {
if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
setRadioState(newState);
@@ -2055,6 +2074,7 @@
case RIL_REQUEST_DEVICE_IDENTITY: ret = responseStrings(p); break;
case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break;
case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
+ case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
default:
throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
//break;
@@ -2176,13 +2196,18 @@
case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break;
case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret = responseVoid(p); break;
case RIL_UNSOL_SIM_REFRESH: ret = responseInts(p); break;
- case RIL_UNSOL_CALL_RING: ret = responseVoid(p); break;
+ case RIL_UNSOL_CALL_RING: ret = responseCallRing(p); break;
case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: ret = responseCdmaSms(p); break;
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseString(p); break;
case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: ret = responseVoid(p); break;
+ case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
+ case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;
+ case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;
+ case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
+
default:
throw new RuntimeException("Unrecognized unsol response: " + response);
//break; (implied)
@@ -2415,6 +2440,39 @@
mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));
}
break;
+
+ case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE:
+ if (RILJ_LOGD) unsljLog(response);
+
+ if (mEmergencyCallbackModeRegistrant != null) {
+ mEmergencyCallbackModeRegistrant.notifyRegistrant();
+ }
+ break;
+
+ case RIL_UNSOL_CDMA_CALL_WAITING:
+ if (RILJ_LOGD) unsljLog(response);
+
+ if(mCallWaitingRegistrants != null) {
+ mCallWaitingRegistrants.notifyRegistrants(new AsyncResult (null, ret, null));
+ }
+ break;
+
+ case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS:
+ if (RILJ_LOGD) unsljLog(response);
+
+ if (mOtaSessionRegistrants != null) {
+ mOtaSessionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
+ }
+ break;
+
+ case RIL_UNSOL_CDMA_INFO_REC:
+ if (RILJ_LOGD)
+ unsljLog(response);
+ if (mInformationRecordsRegistrants != null) {
+ mInformationRecordsRegistrants.notifyRegistrants(new AsyncResult(null, ret,
+ null));
+ }
+ break;
}
}
@@ -2547,6 +2605,11 @@
String s = p.readString();
+ if (RILJ_LOGD) riljLog("< iccIO: "
+ + " 0x" + Integer.toHexString(sw1)
+ + " 0x" + Integer.toHexString(sw2) + " "
+ + s);
+
return new IccIoResult(sw1, sw2, s);
}
@@ -2677,14 +2740,14 @@
response.add(dc);
- if ( RILConstants.CDMA_VOICE_PRIVACY == voiceSettings ) {
+ if ( RILConstants.CDMA_VOICE_PRIVACY == voicePrivacy ) {
mVoicePrivacyOnRegistrants.notifyRegistrants();
Log.d(LOG_TAG, "InCall VoicePrivacy is enabled: " +
- Integer.toString(voiceSettings));
+ Integer.toString(voicePrivacy));
} else {
mVoicePrivacyOffRegistrants.notifyRegistrants();
Log.d(LOG_TAG, "InCall VoicePrivacy is disabled: " +
- Integer.toString(voiceSettings));
+ Integer.toString(voicePrivacy));
}
}
@@ -2696,21 +2759,21 @@
private Object
responseDataCallList(Parcel p) {
int num;
- ArrayList<PDPContextState> response;
+ ArrayList<DataCallState> response;
num = p.readInt();
- response = new ArrayList<PDPContextState>(num);
+ response = new ArrayList<DataCallState>(num);
for (int i = 0; i < num; i++) {
- PDPContextState pdp = new PDPContextState();
+ DataCallState dataCall = new DataCallState();
- pdp.cid = p.readInt();
- pdp.active = p.readInt();
- pdp.type = p.readString();
- pdp.apn = p.readString();
- pdp.address = p.readString();
+ dataCall.cid = p.readInt();
+ dataCall.active = p.readInt();
+ dataCall.type = p.readString();
+ dataCall.apn = p.readString();
+ dataCall.address = p.readString();
- response.add(pdp);
+ response.add(dataCall);
}
return response;
@@ -2771,42 +2834,135 @@
private Object
responseCDMA_BR_CNF(Parcel p) {
- int numServiceCategories;
+ int numInts;
int response[];
- numServiceCategories = p.readInt();
+ numInts = p.readInt();
- if (numServiceCategories == 0) {
- int numInts;
- numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
- response = new int[numInts];
+ response = new int[numInts];
- // indicate that a zero length table was received
- response[0] = 0;
- //for all supported service categories set 'english' as default language
- //and selection status to false
- for (int i = 1, j = 1
- ; i <= (CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES
- * CDMA_BSI_NO_OF_INTS_STRUCT)
- ; i += CDMA_BSI_NO_OF_INTS_STRUCT, j++ ) {
- response[i] = j;
- response[i+1] = 1;
- response[i+2] = 0;
- }
- } else {
- int numInts;
- numInts = numServiceCategories * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
- response = new int[numInts];
-
- response[0] = numServiceCategories;
- for (int i = 1 ; i < numInts; i++) {
- response[i] = p.readInt();
- }
+ response[0] = numInts;
+ for (int i = 1 ; i < numInts; i++) {
+ response[i] = p.readInt();
}
return response;
}
+ private Object
+ responseCdmaInformationRecord(Parcel p){
+
+ int num;
+ ArrayList<CdmaInformationRecord> response;
+
+ num = p.readInt();
+
+ response = new ArrayList<CdmaInformationRecord>(num);
+
+ for (int i = 0; i < num; i++) {
+ int name = p.readInt();
+ CdmaInformationRecord InfoRec = new CdmaInformationRecord(name);
+
+ char buffer[];
+ int length;
+ switch (name) {
+ case CdmaInformationRecord.RIL_CDMA_DISPLAY_INFO_REC:
+ case CdmaInformationRecord.RIL_CDMA_EXTENDED_DISPLAY_INFO_REC:
+ length = p.readInt();
+ buffer = new char[length];
+ for (int j = 0; j < length; j++) {
+ buffer[j] = (char)p.readInt();
+ }
+ InfoRec.createDisplayInfo(length, buffer);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC:
+ case CdmaInformationRecord.RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC:
+ case CdmaInformationRecord.RIL_CDMA_CONNECTED_NUMBER_INFO_REC:
+ length = p.readInt();
+ buffer = new char[length + 4];
+ for (int j = 0; j < (length + 4); j++) {
+ buffer[j] = (char)p.readInt();
+ }
+ InfoRec.createNumberInfo(length, buffer);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_SIGNAL_INFO_REC:
+ buffer = new char[4];
+ for (int j = 0; j < 4; j++) {
+ buffer[j] = (char)p.readInt();
+ }
+ InfoRec.createSignalInfo(buffer);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_REDIRECTING_NUMBER_INFO_REC:
+ length = p.readInt();
+ buffer = new char[length + 4];
+ int reason;
+ for (int j = 0; j < (length + 4); j++) {
+ buffer[j] = (char)p.readInt();
+ }
+ reason = p.readInt();
+ InfoRec.createRedirectingNumberInfo(length, buffer, reason);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_LINE_CONTROL_INFO_REC:
+ buffer = new char[4];
+ for (int j = 0; j < 4; j++) {
+ buffer[j] = (char)p.readInt();
+ }
+ InfoRec.createLineControlInfo(buffer);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_T53_CLIR_INFO_REC:
+ char ch = (char)p.readInt();
+ InfoRec.createT53ClirInfo(ch);
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_T53_RELEASE_INFO_REC:
+ break;
+
+ case CdmaInformationRecord.RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC:
+ char ul = (char)p.readInt();
+ char dl = (char)p.readInt();
+ InfoRec.createT53AudioControlInfo(ul, dl);
+ break;
+
+ default:
+ break;
+ }
+ response.add(InfoRec);
+ }
+
+ return response;
+ }
+
+ private Object
+ responseCdmaCallWaiting(Parcel p){
+ CdmaCallWaiting response = new CdmaCallWaiting();
+ response.number = p.readString();
+ response.numberPresentation = p.readInt();
+ response.name = p.readString();
+ response.signalInfoRecord.isPresent = p.readInt() == 0 ? false : true;
+ response.signalInfoRecord.signalType = p.readInt();
+ response.signalInfoRecord.alertPitch = p.readInt();
+ response.signalInfoRecord.signalCode = p.readInt();
+
+ return response;
+ }
+
+ private Object
+ responseCallRing(Parcel p){
+ char response[] = new char[4];
+
+ response[0] = (char) p.readInt(); // isPresent
+ response[1] = (char) p.readInt(); // signalType
+ response[2] = (char) p.readInt(); // alertPitch
+ response[3] = (char) p.readInt(); // signal
+
+ return response;
+ }
+
static String
requestToString(int request) {
/*
@@ -2915,6 +3071,7 @@
case RIL_REQUEST_DEVICE_IDENTITY: return "RIL_REQUEST_DEVICE_IDENTITY";
case RIL_REQUEST_GET_SMSC_ADDRESS: return "RIL_REQUEST_GET_SMSC_ADDRESS";
case RIL_REQUEST_SET_SMSC_ADDRESS: return "RIL_REQUEST_SET_SMSC_ADDRESS";
+ case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: return "REQUEST_EXIT_EMERGENCY_CALLBACK_MODE";
default: return "<unknown request>";
}
}
@@ -2949,6 +3106,14 @@
case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";
case RIL_UNSOL_OEM_HOOK_RAW: return "RIL_UNSOL_OEM_HOOK_RAW";
+ case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED";
+ case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_RESPONSE_CDMA_NEW_SMS";
+ case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_RESPONSE_NEW_BROADCAST_SMS";
+ case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL";
+ case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE";
+ case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING";
+ case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS";
+ case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC";
default: return "<unknown reponse>";
}
}
@@ -3048,7 +3213,7 @@
/**
* {@inheritDoc}
*/
- public void queryTTYModeEnabled(Message response) {
+ public void queryTTYMode(Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_QUERY_TTY_MODE, response);
@@ -3058,12 +3223,12 @@
/**
* {@inheritDoc}
*/
- public void setTTYModeEnabled(boolean enable, Message response) {
+ public void setTTYMode(int ttyMode, Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_SET_TTY_MODE, response);
rr.mp.writeInt(1);
- rr.mp.writeInt(enable ? 1 : 0);
+ rr.mp.writeInt(ttyMode);
send(rr);
}
@@ -3090,11 +3255,14 @@
send(rr);
}
+ /**
+ * TODO(Teleca): configValuesArray is represented as a RIL_BroadcastSMSConfig
+ * so we think this should be a class with the appropriate parameters not an array?
+ */
public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, response);
- rr.mp.writeInt(configValuesArray[0]);
- for(int i = 1; i <= (configValuesArray[0] * 3); i++) {
+ for(int i = 0; i < configValuesArray.length; i++) {
rr.mp.writeInt(configValuesArray[i]);
}
@@ -3113,4 +3281,16 @@
send(rr);
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void exitEmergencyCallbackMode(Message response) {
+ RILRequest rr
+ = RILRequest.obtain(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, response);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+ send(rr);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index bcf5141..44c863b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,6 +16,13 @@
package com.android.internal.telephony;
+/**
+ * TODO: This should probably not be an interface see
+ * http://www.javaworld.com/javaworld/javaqa/2001-06/01-qa-0608-constants.html and google with
+ * http://www.google.com/search?q=interface+constants&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a
+ *
+ * Also they should all probably be static final.
+ */
/**
* {@hide}
@@ -51,7 +58,7 @@
int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
- int PREFERRED_NETWORK_MODE = NETWORK_MODE_GSM_ONLY;
+ int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF;
/* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
int SUBSCRIPTION_FROM_RUIM = 0; /* CDMA subscription from RUIM when available */
@@ -67,6 +74,10 @@
int CDM_TTY_MODE_DISABLED = 0;
int CDM_TTY_MODE_ENABLED = 1;
+ int CDM_TTY_FULL_MODE = 1;
+ int CDM_TTY_HCO_MODE = 2;
+ int CDM_TTY_VCO_MODE = 3;
+
byte CDMA_VOICE_PRIVACY = 0x70; /* "p" value used in Ril_Call.isVoice if Privacy
is active */
@@ -208,6 +219,7 @@
int RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM = 96;
int RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97;
int RIL_REQUEST_DEVICE_IDENTITY = 98;
+ int RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99;
int RIL_REQUEST_GET_SMSC_ADDRESS = 100;
int RIL_REQUEST_SET_SMSC_ADDRESS = 101;
int RIL_UNSOL_RESPONSE_BASE = 1000;
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index f2bd361..d055c311 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -122,7 +122,7 @@
* CONCATENATED_16_BIT_REFERENCE message set. Should be
* incremented for each set of concatenated messages.
*/
- protected static int sConcatenatedRef;
+ private static int sConcatenatedRef;
private SmsCounter mCounter;
@@ -132,6 +132,11 @@
private static SmsMessageBase mSmsMessageBase;
private SmsMessageBase.SubmitPduBase mSubmitPduBase;
+ protected static int getNextConcatenatedRef() {
+ sConcatenatedRef += 1;
+ return sConcatenatedRef;
+ }
+
/**
* Implement the per-application based SMS control, which only allows
* a limit on the number of SMS/MMS messages an app can send in checking
@@ -419,12 +424,15 @@
/**
* If this is the last part send the parts out to the application, otherwise
* the part is stored for later processing.
+ *
+ * NOTE: concatRef (naturally) needs to be non-null, but portAddrs can be null.
*/
- protected void processMessagePart(SmsMessageBase sms, int referenceNumber,
- int sequence, int count, int destinationPort) {
+ protected void processMessagePart(SmsMessageBase sms,
+ SmsHeader.ConcatRef concatRef, SmsHeader.PortAddrs portAddrs) {
+
// Lookup all other related parts
StringBuilder where = new StringBuilder("reference_number =");
- where.append(referenceNumber);
+ where.append(concatRef.refNumber);
where.append(" AND address = ?");
String[] whereArgs = new String[] {sms.getOriginatingAddress()};
@@ -433,20 +441,19 @@
try {
cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
int cursorCount = cursor.getCount();
- if (cursorCount != count - 1) {
+ if (cursorCount != concatRef.msgCount - 1) {
// We don't have all the parts yet, store this one away
ContentValues values = new ContentValues();
values.put("date", new Long(sms.getTimestampMillis()));
values.put("pdu", HexDump.toHexString(sms.getPdu()));
values.put("address", sms.getOriginatingAddress());
- values.put("reference_number", referenceNumber);
- values.put("count", count);
- values.put("sequence", sequence);
- if (destinationPort != -1) {
- values.put("destination_port", destinationPort);
+ values.put("reference_number", concatRef.refNumber);
+ values.put("count", concatRef.msgCount);
+ values.put("sequence", concatRef.seqNumber);
+ if (portAddrs != null) {
+ values.put("destination_port", portAddrs.destPort);
}
mResolver.insert(mRawUri, values);
-
return;
}
@@ -454,7 +461,7 @@
int pduColumn = cursor.getColumnIndex("pdu");
int sequenceColumn = cursor.getColumnIndex("sequence");
- pdus = new byte[count][];
+ pdus = new byte[concatRef.msgCount][];
for (int i = 0; i < cursorCount; i++) {
cursor.moveToNext();
int cursorSequence = (int)cursor.getLong(sequenceColumn);
@@ -462,7 +469,7 @@
cursor.getString(pduColumn));
}
// This one isn't in the DB, so add it
- pdus[sequence - 1] = sms.getPdu();
+ pdus[concatRef.seqNumber - 1] = sms.getPdu();
// Remove the parts from the database
mResolver.delete(mRawUri, where.toString(), whereArgs);
@@ -473,31 +480,34 @@
if (cursor != null) cursor.close();
}
+ /**
+ * TODO(cleanup): The following code has duplicated logic with
+ * the radio-specific dispatchMessage code, which is fragile,
+ * in addition to being redundant. Instead, if this method
+ * maybe returned the reassembled message (or just contents),
+ * the following code (which is not really related to
+ * reconstruction) could be better consolidated.
+ */
+
// Dispatch the PDUs to applications
- switch (destinationPort) {
- case SmsHeader.PORT_WAP_PUSH: {
- // Build up the data stream
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- for (int i = 0; i < count; i++) {
- SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
- byte[] data = msg.getUserData();
- output.write(data, 0, data.length);
+ if (portAddrs != null) {
+ if (portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
+ // Build up the data stream
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ for (int i = 0; i < concatRef.msgCount; i++) {
+ SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
+ byte[] data = msg.getUserData();
+ output.write(data, 0, data.length);
+ }
+ // Handle the PUSH
+ mWapPush.dispatchWapPdu(output.toByteArray());
+ } else {
+ // The messages were sent to a port, so concoct a URI for it
+ dispatchPortAddressedPdus(pdus, portAddrs.destPort);
}
-
- // Handle the PUSH
- mWapPush.dispatchWapPdu(output.toByteArray());
- break;
- }
-
- case -1:
+ } else {
// The messages were not sent to a port
dispatchPdus(pdus);
- break;
-
- default:
- // The messages were sent to a port, so concoct a URI for it
- dispatchPortAddressedPdus(pdus, destinationPort);
- break;
}
}
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 7274e99..5112ba0 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -22,6 +22,7 @@
import android.os.Registrant;
import android.os.RegistrantList;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
/**
* {@hide}
@@ -50,6 +51,8 @@
public ServiceState ss;
protected ServiceState newSS;
+ public SignalStrength mSignalStrength;
+
// Used as a unique identifier to track requests associated with a poll
// and ignore stale responses.The value is a count-down of expected responses
// in this pollingContext
@@ -104,13 +107,15 @@
protected static final int EVENT_POLL_STATE_OPERATOR_CDMA = 25;
protected static final int EVENT_RUIM_READY = 26;
protected static final int EVENT_RUIM_RECORDS_LOADED = 27;
- protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA = 28;
- protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA = 29;
- protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA = 30;
- protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA = 31;
- protected static final int EVENT_GET_LOC_DONE_CDMA = 32;
- protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA = 33;
- protected static final int EVENT_NV_LOADED = 34;
+ protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA = 28;
+ protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA = 29;
+ protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA = 30;
+ protected static final int EVENT_GET_LOC_DONE_CDMA = 31;
+ protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA = 32;
+ protected static final int EVENT_NV_LOADED = 33;
+ protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION = 34;
+ protected static final int EVENT_NV_READY = 35;
+ protected static final int EVENT_ERI_FILE_LOADED = 36;
//***** Time Zones
protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
@@ -142,6 +147,9 @@
"uk", // U.K
};
+ //***** Registration denied reason
+ protected static final String REGISTRATION_DENIED_GEN = "General";
+ protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
//***** Constructors
public ServiceStateTracker() {
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
index 64b884e..d220648 100644
--- a/telephony/java/com/android/internal/telephony/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -16,227 +16,233 @@
package com.android.internal.telephony;
+import android.telephony.SmsMessage;
+
import com.android.internal.util.HexDump;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
import java.util.ArrayList;
/**
- * This class represents a SMS user data header.
- *
+ * SMS user data header, as specified in TS 23.040 9.2.3.24.
*/
public class SmsHeader {
- /** See TS 23.040 9.2.3.24 for description of this element ID. */
- public static final int CONCATENATED_8_BIT_REFERENCE = 0x00;
- /** See TS 23.040 9.2.3.24 for description of this element ID. */
- public static final int SPECIAL_SMS_MESSAGE_INDICATION = 0x01;
- /** See TS 23.040 9.2.3.24 for description of this element ID. */
- public static final int APPLICATION_PORT_ADDRESSING_8_BIT = 0x04;
- /** See TS 23.040 9.2.3.24 for description of this element ID. */
- public static final int APPLICATION_PORT_ADDRESSING_16_BIT= 0x05;
- /** See TS 23.040 9.2.3.24 for description of this element ID. */
- public static final int CONCATENATED_16_BIT_REFERENCE = 0x08;
+
+ // TODO(cleanup): this datastructure is generally referred to as
+ // the 'user data header' or UDH, and so the class name should
+ // change to reflect this...
+
+ /** SMS user data header information element identifiers.
+ * (see TS 23.040 9.2.3.24)
+ */
+ public static final int ELT_ID_CONCATENATED_8_BIT_REFERENCE = 0x00;
+ public static final int ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION = 0x01;
+ public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT = 0x04;
+ public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT = 0x05;
+ public static final int ELT_ID_SMSC_CONTROL_PARAMS = 0x06;
+ public static final int ELT_ID_UDH_SOURCE_INDICATION = 0x07;
+ public static final int ELT_ID_CONCATENATED_16_BIT_REFERENCE = 0x08;
+ public static final int ELT_ID_WIRELESS_CTRL_MSG_PROTOCOL = 0x09;
+ public static final int ELT_ID_TEXT_FORMATTING = 0x0A;
+ public static final int ELT_ID_PREDEFINED_SOUND = 0x0B;
+ public static final int ELT_ID_USER_DEFINED_SOUND = 0x0C;
+ public static final int ELT_ID_PREDEFINED_ANIMATION = 0x0D;
+ public static final int ELT_ID_LARGE_ANIMATION = 0x0E;
+ public static final int ELT_ID_SMALL_ANIMATION = 0x0F;
+ public static final int ELT_ID_LARGE_PICTURE = 0x10;
+ public static final int ELT_ID_SMALL_PICTURE = 0x11;
+ public static final int ELT_ID_VARIABLE_PICTURE = 0x12;
+ public static final int ELT_ID_USER_PROMPT_INDICATOR = 0x13;
+ public static final int ELT_ID_EXTENDED_OBJECT = 0x14;
+ public static final int ELT_ID_REUSED_EXTENDED_OBJECT = 0x15;
+ public static final int ELT_ID_COMPRESSION_CONTROL = 0x16;
+ public static final int ELT_ID_OBJECT_DISTR_INDICATOR = 0x17;
+ public static final int ELT_ID_STANDARD_WVG_OBJECT = 0x18;
+ public static final int ELT_ID_CHARACTER_SIZE_WVG_OBJECT = 0x19;
+ public static final int ELT_ID_EXTENDED_OBJECT_DATA_REQUEST_CMD = 0x1A;
+ public static final int ELT_ID_RFC_822_EMAIL_HEADER = 0x20;
+ public static final int ELT_ID_HYPERLINK_FORMAT_ELEMENT = 0x21;
+ public static final int ELT_ID_REPLY_ADDRESS_ELEMENT = 0x22;
+ public static final int ELT_ID_ENHANCED_VOICE_MAIL_INFORMATION = 0x23;
public static final int PORT_WAP_PUSH = 2948;
- public static final int PORT_WAP_WSP = 9200;
+ public static final int PORT_WAP_WSP = 9200;
- private byte[] m_data;
- private ArrayList<Element> m_elements = new ArrayList<Element>();
- public int nbrOfHeaders;
+ public static class PortAddrs {
+ public int destPort;
+ public int origPort;
+ public boolean areEightBits;
+ }
+
+ public static class ConcatRef {
+ public int refNumber;
+ public int seqNumber;
+ public int msgCount;
+ public boolean isEightBits;
+ }
/**
- * Creates an SmsHeader object from raw user data header bytes.
- *
- * @param data is user data header bytes
- * @return an SmsHeader object
+ * A header element that is not explicitly parsed, meaning not
+ * PortAddrs or ConcatRef.
*/
- public static SmsHeader parse(byte[] data) {
- SmsHeader header = new SmsHeader();
- header.m_data = data;
+ public static class MiscElt {
+ public int id;
+ public byte[] data;
+ }
- int index = 0;
- header.nbrOfHeaders = 0;
- while (index < data.length) {
- int id = data[index++] & 0xff;
- int length = data[index++] & 0xff;
- byte[] elementData = new byte[length];
- System.arraycopy(data, index, elementData, 0, length);
- header.add(new Element(id, elementData));
- index += length;
- header.nbrOfHeaders++;
+ public PortAddrs portAddrs;
+ public ConcatRef concatRef;
+ public ArrayList<MiscElt> miscEltList = new ArrayList<MiscElt>();
+
+ public SmsHeader() {}
+
+ /**
+ * Create structured SmsHeader object from serialized byte array representation.
+ * (see TS 23.040 9.2.3.24)
+ * @param data is user data header bytes
+ * @return SmsHeader object
+ */
+ public static SmsHeader fromByteArray(byte[] data) {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+ SmsHeader smsHeader = new SmsHeader();
+ while (inStream.available() > 0) {
+ /**
+ * NOTE: as defined in the spec, ConcatRef and PortAddr
+ * fields should not reoccur, but if they do the last
+ * occurrence is to be used.
+ */
+ int id = inStream.read();
+ int length = inStream.read();
+ ConcatRef concatRef;
+ PortAddrs portAddrs;
+ switch (id) {
+ case ELT_ID_CONCATENATED_8_BIT_REFERENCE:
+ concatRef = new ConcatRef();
+ concatRef.refNumber = inStream.read();
+ concatRef.msgCount = inStream.read();
+ concatRef.seqNumber = inStream.read();
+ concatRef.isEightBits = true;
+ smsHeader.concatRef = concatRef;
+ break;
+ case ELT_ID_CONCATENATED_16_BIT_REFERENCE:
+ concatRef = new ConcatRef();
+ concatRef.refNumber = (inStream.read() << 8) | inStream.read();
+ concatRef.msgCount = inStream.read();
+ concatRef.seqNumber = inStream.read();
+ concatRef.isEightBits = false;
+ smsHeader.concatRef = concatRef;
+ break;
+ case ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT:
+ portAddrs = new PortAddrs();
+ portAddrs.destPort = inStream.read();
+ portAddrs.origPort = inStream.read();
+ portAddrs.areEightBits = true;
+ smsHeader.portAddrs = portAddrs;
+ break;
+ case ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT:
+ portAddrs = new PortAddrs();
+ portAddrs.destPort = (inStream.read() << 8) | inStream.read();
+ portAddrs.origPort = (inStream.read() << 8) | inStream.read();
+ portAddrs.areEightBits = false;
+ smsHeader.portAddrs = portAddrs;
+ break;
+ default:
+ MiscElt miscElt = new MiscElt();
+ miscElt.id = id;
+ miscElt.data = new byte[length];
+ inStream.read(miscElt.data, 0, length);
+ smsHeader.miscEltList.add(miscElt);
+ }
+ }
+ return smsHeader;
+ }
+
+ /**
+ * Create serialized byte array representation from structured SmsHeader object.
+ * (see TS 23.040 9.2.3.24)
+ * @return Byte array representing the SmsHeader
+ */
+ public static byte[] toByteArray(SmsHeader smsHeader) {
+ if ((smsHeader.portAddrs == null) &&
+ (smsHeader.concatRef == null) &&
+ (smsHeader.miscEltList.size() == 0)) {
+ return null;
}
- return header;
- }
-
- public SmsHeader() { }
-
- /**
- * Returns the list of SmsHeader Elements that make up the header.
- *
- * @return the list of SmsHeader Elements.
- */
- public ArrayList<Element> getElements() {
- return m_elements;
- }
-
- /**
- * Add an element to the SmsHeader.
- *
- * @param element to add.
- */
- public void add(Element element) {
- m_elements.add(element);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream(SmsMessage.MAX_USER_DATA_BYTES);
+ ConcatRef concatRef = smsHeader.concatRef;
+ if (concatRef != null) {
+ if (concatRef.isEightBits) {
+ outStream.write(ELT_ID_CONCATENATED_8_BIT_REFERENCE);
+ outStream.write(3);
+ outStream.write(concatRef.refNumber);
+ } else {
+ outStream.write(ELT_ID_CONCATENATED_16_BIT_REFERENCE);
+ outStream.write(4);
+ outStream.write(concatRef.refNumber >>> 8);
+ outStream.write(concatRef.refNumber & 0x00FF);
+ }
+ outStream.write(concatRef.msgCount);
+ outStream.write(concatRef.seqNumber);
+ }
+ PortAddrs portAddrs = smsHeader.portAddrs;
+ if (portAddrs != null) {
+ if (portAddrs.areEightBits) {
+ outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT);
+ outStream.write(2);
+ outStream.write(portAddrs.destPort);
+ outStream.write(portAddrs.origPort);
+ } else {
+ outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT);
+ outStream.write(4);
+ outStream.write(portAddrs.destPort >>> 8);
+ outStream.write(portAddrs.destPort & 0x00FF);
+ outStream.write(portAddrs.origPort >>> 8);
+ outStream.write(portAddrs.origPort & 0x00FF);
+ }
+ }
+ for (MiscElt miscElt : smsHeader.miscEltList) {
+ outStream.write(miscElt.id);
+ outStream.write(miscElt.data.length);
+ outStream.write(miscElt.data, 0, miscElt.data.length);
+ }
+ return outStream.toByteArray();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
-
- builder.append("UDH LENGTH: " + m_data.length + " octets");
- builder.append("UDH: ");
- builder.append(HexDump.toHexString(m_data));
- builder.append("\n");
-
- for (Element e : getElements()) {
- builder.append(" 0x" + HexDump.toHexString((byte)e.getID()) + " - ");
- switch (e.getID()) {
- case CONCATENATED_8_BIT_REFERENCE: {
- builder.append("Concatenated Short Message 8bit ref\n");
- byte[] data = e.getData();
- builder.append(" " + data.length + " (0x");
- builder.append(HexDump.toHexString((byte)data.length)
- + ") Bytes - Information Element\n");
- builder.append(" " + data[0] + " : SM reference number\n");
- builder.append(" " + data[1] + " : number of messages\n");
- builder.append(" " + data[2] + " : this SM sequence number\n");
- break;
- }
-
- case CONCATENATED_16_BIT_REFERENCE: {
- builder.append("Concatenated Short Message 16bit ref\n");
- byte[] data = e.getData();
- builder.append(" " + data.length + " (0x");
- builder.append(HexDump.toHexString((byte)data.length)
- + ") Bytes - Information Element\n");
- builder.append(" " + (data[0] & 0xff) * 256 + (data[1] & 0xff)
- + " : SM reference number\n");
- builder.append(" " + data[2] + " : number of messages\n");
- builder.append(" " + data[3] + " : this SM sequence number\n");
- break;
- }
-
- case APPLICATION_PORT_ADDRESSING_8_BIT:
- {
- builder.append("Application port addressing 8bit\n");
- byte[] data = e.getData();
-
- builder.append(" " + data.length + " (0x");
- builder.append(HexDump.toHexString(
- (byte)data.length) + ") Bytes - Information Element\n");
-
- int source = (data[0] & 0xff);
- builder.append(" " + source + " : DESTINATION port\n");
-
- int dest = (data[1] & 0xff);
- builder.append(" " + dest + " : SOURCE port\n");
- break;
- }
-
- case APPLICATION_PORT_ADDRESSING_16_BIT: {
- builder.append("Application port addressing 16bit\n");
- byte[] data = e.getData();
-
- builder.append(" " + data.length + " (0x");
- builder.append(HexDump.toHexString((byte)data.length)
- + ") Bytes - Information Element\n");
-
- int source = (data[0] & 0xff) << 8;
- source |= (data[1] & 0xff);
- builder.append(" " + source + " : DESTINATION port\n");
-
- int dest = (data[2] & 0xff) << 8;
- dest |= (data[3] & 0xff);
- builder.append(" " + dest + " : SOURCE port\n");
- break;
- }
-
- default: {
- builder.append("Unknown element\n");
- break;
- }
- }
+ builder.append("UserDataHeader ");
+ builder.append("{ ConcatRef ");
+ if (concatRef == null) {
+ builder.append("unset");
+ } else {
+ builder.append("{ refNumber=" + concatRef.refNumber);
+ builder.append(", msgCount=" + concatRef.msgCount);
+ builder.append(", seqNumber=" + concatRef.seqNumber);
+ builder.append(", isEightBits=" + concatRef.isEightBits);
+ builder.append(" }");
}
-
+ builder.append(", PortAddrs ");
+ if (portAddrs == null) {
+ builder.append("unset");
+ } else {
+ builder.append("{ destPort=" + portAddrs.destPort);
+ builder.append(", origPort=" + portAddrs.origPort);
+ builder.append(", areEightBits=" + portAddrs.areEightBits);
+ builder.append(" }");
+ }
+ for (MiscElt miscElt : miscEltList) {
+ builder.append(", MiscElt ");
+ builder.append("{ id=" + miscElt.id);
+ builder.append(", length=" + miscElt.data.length);
+ builder.append(", data=" + HexDump.toHexString(miscElt.data));
+ builder.append(" }");
+ }
+ builder.append(" }");
return builder.toString();
}
- private int calcSize() {
- int size = 1; // +1 for the UDHL field
- for (Element e : m_elements) {
- size += e.getData().length;
- size += 2; // 1 byte ID, 1 byte length
- }
-
- return size;
- }
-
- /**
- * Converts SmsHeader object to a byte array as specified in TS 23.040 9.2.3.24.
- * @return Byte array representing the SmsHeader
- */
- public byte[] toByteArray() {
- if (m_elements.size() == 0) return null;
-
- if (m_data == null) {
- int size = calcSize();
- int cur = 1;
- m_data = new byte[size];
-
- m_data[0] = (byte) (size-1); // UDHL does not include itself
-
- for (Element e : m_elements) {
- int length = e.getData().length;
- m_data[cur++] = (byte) e.getID();
- m_data[cur++] = (byte) length;
- System.arraycopy(e.getData(), 0, m_data, cur, length);
- cur += length;
- }
- }
-
- return m_data;
- }
-
- /**
- * A single Element in the SMS User Data Header.
- *
- * See TS 23.040 9.2.3.24.
- *
- */
- public static class Element {
- private byte[] m_data;
- private int m_id;
-
- public Element(int id, byte[] data) {
- m_id = id;
- m_data = data;
- }
-
- /**
- * Returns the Information Element Identifier for this element.
- *
- * @return the IE identifier.
- */
- public int getID() {
- return m_id;
- }
-
- /**
- * Returns the data portion of this element.
- *
- * @return element data.
- */
- public byte[] getData() {
- return m_data;
- }
- }
}
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 1aad38d..31bb652 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -245,8 +245,6 @@
/**
* Returns an object representing the user data header
*
- * @return an object representing the user data header
- *
* {@hide}
*/
public SmsHeader getUserDataHeader() {
@@ -254,9 +252,14 @@
}
/**
+ * TODO(cleanup): The term PDU is used in a seemingly non-unique
+ * manner -- for example, what is the difference between this byte
+ * array and the contents of SubmitPdu objects. Maybe a more
+ * illustrative term would be appropriate.
+ */
+
+ /**
* Returns the raw PDU for the message.
- *
- * @return the raw PDU for the message.
*/
public byte[] getPdu() {
return mPdu;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index c342233..91aa34e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -53,7 +53,20 @@
*/
public static final String ACTION_RADIO_TECHNOLOGY_CHANGED
= "android.intent.action.RADIO_TECHNOLOGY";
-
+ /**
+ * <p>Broadcast Action: The emergency callback mode is entered.
+ *
+ * <p class="note">
+ * You can <em>not</em> receive this through components declared
+ * in manifests, only by explicitly registering for it with
+ * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
+ * android.content.IntentFilter) Context.registerReceiver()}.
+ *
+ * <p class="note">
+ * Requires no permission.
+ */
+ public static final String ACTION_EMERGENCY_CALLBACK_MODE_ENTERED
+ = "android.intent.action.EMERGENCY_CALLBACK_MODE";
/**
* Broadcast Action: The phone's signal strength has changed. The intent will have the
* following extra values:</p>
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 396b42d..453185f 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -44,6 +44,7 @@
* Availability: when registered to a network
*/
static final String PROPERTY_OPERATOR_ALPHA = "gsm.operator.alpha";
+ //TODO: most of these proprieties are generic, substitute gsm. with phone. bug 1856959
/** Numeric name (MCC+MNC) of current registered operator.
* Availability: when registered to a network
@@ -68,6 +69,8 @@
*/
static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
+ static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
+
//****** SIM Card
/**
* One of <code>"UNKNOWN"</code> <code>"ABSENT"</code> <code>"PIN_REQUIRED"</code>
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 8ffb7ec..03f7f98 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -16,7 +16,9 @@
package com.android.internal.telephony.cdma;
+import android.app.ActivityManagerNative;
import android.content.Context;
+import android.content.Intent;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
@@ -28,6 +30,7 @@
import android.telephony.CellLocation;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.text.TextUtils;
import android.util.Log;
@@ -48,6 +51,8 @@
import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.PhoneSubInfo;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
import java.util.ArrayList;
import java.util.List;
@@ -71,8 +76,13 @@
RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
RuimSmsInterfaceManager mRuimSmsInterfaceManager;
PhoneSubInfo mSubInfo;
+ EriManager mEriManager;
- protected RegistrantList mNvLoadedRegistrants = new RegistrantList();
+ // mNvLoadedRegistrants are informed after the EVENT_NV_READY
+ private RegistrantList mNvLoadedRegistrants = new RegistrantList();
+
+ // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
+ private RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
private String mEsn;
private String mMeid;
@@ -102,6 +112,7 @@
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
mSubInfo = new PhoneSubInfo(this);
+ mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
@@ -111,10 +122,13 @@
mCM.setOnCallRing(h, EVENT_CALL_RING, null);
mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForNVReady(h, EVENT_NV_READY, null);
+ mCM.registerForCdmaCallWaiting(h,EVENT_CDMA_CALL_WAITING,null);
+ mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE, null);
+
//Change the system setting
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.CDMA_PHONE);
+ SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
+ new Integer(RILConstants.CDMA_PHONE).toString());
}
public void dispose() {
@@ -129,6 +143,7 @@
mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(h);
mCM.unSetOnCallRing(h);
+ mCM.unregisterForCdmaCallWaiting(h);
//Force all referenced classes to unregister their former registered events
mCT.dispose();
@@ -141,6 +156,7 @@
mRuimPhoneBookInterfaceManager.dispose();
mRuimSmsInterfaceManager.dispose();
mSubInfo.dispose();
+ mEriManager.dispose();
}
}
@@ -155,6 +171,7 @@
this.mDataConnection = null;
this.mCT = null;
this.mSST = null;
+ this.mEriManager = null;
}
protected void finalize() {
@@ -229,6 +246,10 @@
case DATAINANDOUT:
ret = DataActivityState.DATAINANDOUT;
break;
+
+ case DORMANT:
+ ret = DataActivityState.DORMANT;
+ break;
}
}
return ret;
@@ -261,9 +282,8 @@
}
}
-
- public int getSignalStrengthASU() {
- return mSST.rssi == 99 ? -1 : mSST.rssi;
+ public SignalStrength getSignalStrength() {
+ return mSST.mSignalStrength;
}
public boolean
@@ -350,6 +370,10 @@
return mRuimRecords.getMdnNumber();
}
+ public String getMin() {
+ return mRuimRecords.getMin();
+ }
+
public void getCallWaiting(Message onComplete) {
mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
}
@@ -476,10 +500,10 @@
ret = DataState.CONNECTED;
} else if (mSST == null) {
- // Radio Technology Change is ongoning, dispose() and removeReferences() have
- // already been called
+ // Radio Technology Change is ongoning, dispose() and removeReferences() have
+ // already been called
- ret = DataState.DISCONNECTED;
+ ret = DataState.DISCONNECTED;
} else if (mSST.getCurrentCdmaDataConnectionState()
== ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
// If we're out of service, open TCP sockets may still work
@@ -541,6 +565,21 @@
mCM.stopDtmf(null);
}
+ public void sendBurstDtmf(String dtmfString) {
+ boolean check = true;
+ for (int itr = 0;itr < dtmfString.length(); itr++) {
+ if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
+ Log.e(LOG_TAG,
+ "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
+ check = false;
+ break;
+ }
+ }
+ if ((mCT.state == Phone.State.OFFHOOK)&&(check)) {
+ mCM.sendBurstDtmf(dtmfString, null);
+ }
+ }
+
public void getAvailableNetworks(Message response) {
Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
}
@@ -767,6 +806,12 @@
}
break;
+ case EVENT_EMERGENCY_CALLBACK_MODE: {
+ Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received");
+ Intent intent =
+ new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_ENTERED);
+ ActivityManagerNative.broadcastStickyIntent(intent, null);
+ }
case EVENT_RUIM_RECORDS_LOADED:{
Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
}
@@ -800,7 +845,18 @@
case EVENT_NV_READY:{
Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
//Inform the Service State Tracker
+ mEriManager.loadEriFile();
mNvLoadedRegistrants.notifyRegistrants();
+ if(mEriManager.isEriFileLoaded()) {
+ // when the ERI file is loaded
+ Log.d(LOG_TAG, "ERI read, notify registrants");
+ mEriFileLoadedRegistrants.notifyRegistrants();
+ }
+ }
+ break;
+
+ case EVENT_CDMA_CALL_WAITING:{
+ Log.d(LOG_TAG, "Event EVENT_CDMA_CALL_WAITING Received");
}
break;
@@ -841,6 +897,15 @@
mNvLoadedRegistrants.remove(h);
}
+ public void registerForEriFileLoaded(Handler h, int what, Object obj) {
+ Registrant r = new Registrant (h, what, obj);
+ mEriFileLoadedRegistrants.add(r);
+ }
+
+ public void unregisterForEriFileLoaded(Handler h) {
+ mEriFileLoadedRegistrants.remove(h);
+ }
+
// override for allowing access from other classes of this package
/**
* {@inheritDoc}
@@ -866,15 +931,22 @@
/**
* Set the TTY mode of the CDMAPhone
*/
- public void setTTYModeEnabled(boolean enable, Message onComplete) {
- this.mCM.setTTYModeEnabled(enable, onComplete);
+ public void setTTYMode(int ttyMode, Message onComplete) {
+ this.mCM.setTTYMode(ttyMode, onComplete);
}
/**
* Queries the TTY mode of the CDMAPhone
*/
- public void queryTTYModeEnabled(Message onComplete) {
- this.mCM.queryTTYModeEnabled(onComplete);
+ public void queryTTYMode(Message onComplete) {
+ this.mCM.queryTTYMode(onComplete);
+ }
+
+ /**
+ * Sends Exit EmergencyCallbackMode Exit request on CDMAPhone
+ */
+ public void exitEmergencyCallbackMode(Message onComplete) {
+ this.mCM.exitEmergencyCallbackMode(onComplete);
}
/**
@@ -908,4 +980,244 @@
public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
mSMS.setCellBroadcastConfig(configValuesArray, response);
}
+
+ public void registerForOtaSessionStatus(Handler h, int what, Object obj){
+ mCM.registerForOtaSessionStatus(h, what, obj);
+ }
+
+ public void unregisterForOtaSessionStatus(Handler h){
+ mCM.unregisterForOtaSessionStatus(h);
+ }
+
+/**
+ * TODO(Teleca): The code in getCdmaEriIconIndex, getCdmaEriIconMode & getCdmaEriText share a
+ * lot of logic, refactor.
+ */
+ /**
+ * Returns the CDMA ERI icon index to display,
+ * it returns 1, EriInfo.ROAMING_INDICATOR_OFF, in case there is no icon to display
+ */
+ @Override
+ public int getCdmaEriIconIndex() {
+ int roamInd = getServiceState().getCdmaRoamingIndicator();
+ int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+ int ret = -1;
+
+ switch (roamInd) {
+ // Handling the standard roaming indicator (non-ERI)
+ case EriInfo.ROAMING_INDICATOR_ON:
+ case EriInfo.ROAMING_INDICATOR_OFF:
+ case EriInfo.ROAMING_INDICATOR_FLASH:
+ Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): " + roamInd);
+ ret = roamInd;
+ break;
+
+ // Handling the Enhanced Roaming Indicator (roamInd > 2)
+ default:
+ if (!mEriManager.isEriFileLoaded()) {
+ /**
+ * TODO(Teleca): What is going on here? Conditionals on the variable being
+ * switched? Seems unreasonably confusing... Especially since the above comment
+ * indicates this should always be true... If we used explicit returns, the
+ * switch could be used to filter specific cases for early bail, and the rest
+ * could then be dealt with outside the switch...
+ */
+
+ if(defRoamInd > 2) {
+ Log.d(LOG_TAG, "ERI File not loaded, using: "
+ + EriInfo.ROAMING_INDICATOR_FLASH);
+ ret = EriInfo.ROAMING_INDICATOR_FLASH;
+ } else {
+ Log.d(LOG_TAG, "ERI File not loaded, using: " + defRoamInd);
+ ret = defRoamInd;
+ }
+ } else if (mEriManager.getEriInfo(roamInd) == null) {
+ if(mEriManager.getEriInfo(defRoamInd) == null) {
+/**
+ * TODO(Teleca): Why the redundant code? Especially since it results in this very strange looking
+ * almost-identical conditional... How about calling each version of mEriManager.getEriInfo just
+ * once, and conditionalizing on the results..
+ */
+ Log.e(LOG_TAG, "Error: ERI entry: " + roamInd
+ + " not present, defRoamInd: " + defRoamInd
+ + " not defined in ERI file");
+ ret = EriInfo.ROAMING_INDICATOR_ON;
+ } else {
+ int iconIndex = mEriManager.getEriInfo(defRoamInd).mIconIndex;
+ Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, using icon: "
+ + iconIndex);
+ ret = iconIndex;
+ }
+ } else {
+ int iconIndex = mEriManager.getEriInfo(roamInd).mIconIndex;
+ Log.d(LOG_TAG, "Using ERI icon: " + iconIndex);
+ ret = iconIndex;
+ }
+ break;
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the CDMA ERI icon mode,
+ * 0 - ON
+ * 1 - FLASHING
+ */
+ @Override
+ public int getCdmaEriIconMode() {
+ int roamInd = getServiceState().getCdmaRoamingIndicator();
+ int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+ int ret = -1;
+
+ switch (roamInd) {
+ // Handling the standard roaming indicator (non-ERI)
+ case EriInfo.ROAMING_INDICATOR_ON:
+ case EriInfo.ROAMING_INDICATOR_OFF:
+ Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): normal");
+ ret = EriInfo.ROAMING_ICON_MODE_NORMAL;
+ break;
+
+ case EriInfo.ROAMING_INDICATOR_FLASH:
+ Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): flashing");
+ ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+ break;
+
+ // Handling the Enhanced Roaming Indicator (roamInd > 2)
+ default:
+ if (!mEriManager.isEriFileLoaded()) {
+ if(defRoamInd > 2) {
+ Log.d(LOG_TAG, "ERI File not loaded, defRoamInd > 2, flashing");
+ ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+ } else {
+ switch (defRoamInd) {
+ // Handling the standard roaming indicator (non-ERI)
+ case EriInfo.ROAMING_INDICATOR_ON:
+ case EriInfo.ROAMING_INDICATOR_OFF:
+ Log.d(LOG_TAG, "ERI File not loaded, normal");
+ ret = EriInfo.ROAMING_ICON_MODE_NORMAL;
+ break;
+
+ case EriInfo.ROAMING_INDICATOR_FLASH:
+ Log.d(LOG_TAG, "ERI File not loaded, normal");
+ ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+ break;
+ }
+ }
+ } else if (mEriManager.getEriInfo(roamInd) == null) {
+ if(mEriManager.getEriInfo(defRoamInd) == null) {
+ Log.e(LOG_TAG, "Error: defRoamInd not defined in ERI file, normal");
+ ret = EriInfo.ROAMING_ICON_MODE_NORMAL;
+ } else {
+ int mode = mEriManager.getEriInfo(defRoamInd).mIconMode;
+ Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, icon mode: "
+ + mode);
+ ret = mode;
+ }
+ } else {
+ int mode = mEriManager.getEriInfo(roamInd).mIconMode;
+ Log.d(LOG_TAG, "Using ERI icon mode: " + mode);
+ ret = mode;
+ }
+ break;
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the CDMA ERI text,
+ */
+ @Override
+ public String getCdmaEriText() {
+ int roamInd = getServiceState().getCdmaRoamingIndicator();
+ int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+ String ret = "ERI text";
+
+ switch (roamInd) {
+ // Handling the standard roaming indicator (non-ERI)
+ case EriInfo.ROAMING_INDICATOR_ON:
+ ret = EriInfo.ROAMING_TEXT_0;
+ break;
+ case EriInfo.ROAMING_INDICATOR_OFF:
+ ret = EriInfo.ROAMING_TEXT_1;
+ break;
+ case EriInfo.ROAMING_INDICATOR_FLASH:
+ ret = EriInfo.ROAMING_TEXT_2;
+ break;
+
+ // Handling the standard ERI
+ case 3:
+ ret = EriInfo.ROAMING_TEXT_3;
+ break;
+ case 4:
+ ret = EriInfo.ROAMING_TEXT_4;
+ break;
+ case 5:
+ ret = EriInfo.ROAMING_TEXT_5;
+ break;
+ case 6:
+ ret = EriInfo.ROAMING_TEXT_6;
+ break;
+ case 7:
+ ret = EriInfo.ROAMING_TEXT_7;
+ break;
+ case 8:
+ ret = EriInfo.ROAMING_TEXT_8;
+ break;
+ case 9:
+ ret = EriInfo.ROAMING_TEXT_9;
+ break;
+ case 10:
+ ret = EriInfo.ROAMING_TEXT_10;
+ break;
+ case 11:
+ ret = EriInfo.ROAMING_TEXT_11;
+ break;
+ case 12:
+ ret = EriInfo.ROAMING_TEXT_12;
+ break;
+
+ // Handling the non standard Enhanced Roaming Indicator (roamInd > 63)
+ default:
+ if (!mEriManager.isEriFileLoaded()) {
+ if(defRoamInd > 2) {
+ Log.d(LOG_TAG, "ERI File not loaded, defRoamInd > 2, " +
+ EriInfo.ROAMING_TEXT_2);
+ ret = EriInfo.ROAMING_TEXT_2;
+ } else {
+ switch (defRoamInd) {
+ // Handling the standard roaming indicator (non-ERI)
+ case EriInfo.ROAMING_INDICATOR_ON:
+ Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_0);
+ ret = EriInfo.ROAMING_TEXT_0;
+ break;
+ case EriInfo.ROAMING_INDICATOR_OFF:
+ Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_1);
+ ret = EriInfo.ROAMING_TEXT_1;
+ break;
+ case EriInfo.ROAMING_INDICATOR_FLASH:
+ Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_2);
+ ret = EriInfo.ROAMING_TEXT_2;
+ break;
+ }
+ }
+ } else if (mEriManager.getEriInfo(roamInd) == null) {
+ if(mEriManager.getEriInfo(defRoamInd) == null) {
+ Log.e(LOG_TAG, "Error: defRoamInd not defined in ERI file, "
+ + EriInfo.ROAMING_TEXT_0);
+ ret = EriInfo.ROAMING_TEXT_0;
+ } else {
+ String eriText = mEriManager.getEriInfo(defRoamInd).mEriText;
+ Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, eri text: "
+ + eriText);
+ ret = eriText;
+ }
+ } else {
+ String eriText = mEriManager.getEriInfo(roamInd).mEriText;
+ Log.d(LOG_TAG, "Using ERI text: " + eriText);
+ ret = eriText;
+ }
+ break;
+ }
+ return ret;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
index ea557b2..9af245c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
@@ -25,26 +25,40 @@
*
*/
public interface CallFailCause {
- static final int NORMAL_CLEARING = 16;
+ static final int NORMAL_CLEARING = 16;
// Busy Tone
- static final int USER_BUSY = 17;
+ static final int USER_BUSY = 17;
+ // TODO(Teleca): Should we remove commented out values?
// // No Tone
-// static final int NUMBER_CHANGED = 22;
-// static final int STATUS_ENQUIRY = 30;
- static final int NORMAL_UNSPECIFIED = 31;
+// static final int NUMBER_CHANGED = 22;
+// static final int STATUS_ENQUIRY = 30;
+ static final int NORMAL_UNSPECIFIED = 31;
//
// // Congestion Tone
-// static final int NO_CIRCUIT_AVAIL = 34;
-// static final int TEMPORARY_FAILURE = 41;
-// static final int SWITCHING_CONGESTION = 42;
-// static final int CHANNEL_NOT_AVAIL = 44;
-// static final int QOS_NOT_AVAIL = 49;
-// static final int BEARER_NOT_AVAIL = 58;
+ static final int NO_CIRCUIT_AVAIL = 34;
+// static final int TEMPORARY_FAILURE = 41;
+// static final int SWITCHING_CONGESTION = 42;
+// static final int CHANNEL_NOT_AVAIL = 44;
+// static final int QOS_NOT_AVAIL = 49;
+// static final int BEARER_NOT_AVAIL = 58;
//
// // others
-// static final int ACM_LIMIT_EXCEEDED = 68;
-// static final int CALL_BARRED = 240;
-// static final int FDN_BLOCKED = 241;
+ static final int ACM_LIMIT_EXCEEDED = 68;
+ static final int CALL_BARRED = 240;
+ static final int FDN_BLOCKED = 241;
+
+ static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000;
+ static final int CDMA_DROP = 1001;
+ static final int CDMA_INTERCEPT = 1002;
+ static final int CDMA_REORDER = 1003;
+ static final int CDMA_SO_REJECT = 1004;
+ static final int CDMA_RETRY_ORDER = 1005;
+ static final int CDMA_ACCESS_FAILURE = 1006;
+ static final int CDMA_PREEMPTED = 1007;
+
+ // For non-emergency number dialed while in emergency callback mode.
+ static final int CDMA_NOT_EMERGENCY = 1008;
+
static final int ERROR_UNSPECIFIED = 0xffff;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java
new file mode 100644
index 0000000..64841d7
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java
@@ -0,0 +1,33 @@
+/*
+ * 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.telephony.cdma;
+
+import com.android.internal.telephony.CdmaInformationRecord;
+
+public class CdmaCallWaiting {
+ public String number;
+ public int numberPresentation;
+ public String name;
+
+ public CdmaInformationRecord.CdmaSignalInfoRec signalInfoRecord =
+ new CdmaInformationRecord.CdmaSignalInfoRec();
+
+ @Override
+ public String toString() {
+ return "CdmaCallWaiting: {" + " number: " + number + " numberPresentation: "
+ + numberPresentation + " name: " + name + " signalInfoRecord: "
+ + signalInfoRecord + " }";
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index cdad4a7..0a237c6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -84,7 +84,7 @@
static final int EVENT_PAUSE_DONE = 2;
static final int EVENT_NEXT_POST_DIAL = 3;
static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
-
+
//***** Constants
static final int PAUSE_DELAY_FIRST_MILLIS = 100;
static final int PAUSE_DELAY_MILLIS = 3 * 1000;
@@ -139,7 +139,7 @@
CdmaConnection (Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) {
createWakeLock(context);
acquireWakeLock();
-
+
owner = ct;
h = new MyHandler(owner.getLooper());
@@ -344,6 +344,32 @@
switch (causeCode) {
case CallFailCause.USER_BUSY:
return DisconnectCause.BUSY;
+ case CallFailCause.NO_CIRCUIT_AVAIL:
+ return DisconnectCause.CONGESTION;
+ case CallFailCause.ACM_LIMIT_EXCEEDED:
+ return DisconnectCause.LIMIT_EXCEEDED;
+ case CallFailCause.CALL_BARRED:
+ return DisconnectCause.CALL_BARRED;
+ case CallFailCause.FDN_BLOCKED:
+ return DisconnectCause.FDN_BLOCKED;
+ case CallFailCause.CDMA_LOCKED_UNTIL_POWER_CYCLE:
+ return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE;
+ case CallFailCause.CDMA_DROP:
+ return DisconnectCause.CDMA_DROP;
+ case CallFailCause.CDMA_INTERCEPT:
+ return DisconnectCause.CDMA_INTERCEPT;
+ case CallFailCause.CDMA_REORDER:
+ return DisconnectCause.CDMA_REORDER;
+ case CallFailCause.CDMA_SO_REJECT:
+ return DisconnectCause.CDMA_SO_REJECT;
+ case CallFailCause.CDMA_RETRY_ORDER:
+ return DisconnectCause.CDMA_RETRY_ORDER;
+ case CallFailCause.CDMA_ACCESS_FAILURE:
+ return DisconnectCause.CDMA_ACCESS_FAILURE;
+ case CallFailCause.CDMA_PREEMPTED:
+ return DisconnectCause.CDMA_PREEMPTED;
+ case CallFailCause.CDMA_NOT_EMERGENCY:
+ return DisconnectCause.CDMA_NOT_EMERGENCY;
case CallFailCause.ERROR_UNSPECIFIED:
case CallFailCause.NORMAL_CLEARING:
default:
@@ -352,7 +378,7 @@
if (serviceState == ServiceState.STATE_POWER_OFF) {
return DisconnectCause.POWER_OFF;
} else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
- || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
+ || serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
return DisconnectCause.OUT_OF_SERVICE;
} else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
&& phone.getIccCard().getState() != RuimCard.State.READY) {
@@ -549,7 +575,7 @@
return postDialString.substring(nextPostDialChar);
}
-
+
@Override
protected void finalize()
{
@@ -583,7 +609,7 @@
c = 0;
} else {
boolean isValid;
-
+
setPostDialState(PostDialState.STARTED);
c = postDialString.charAt(nextPostDialChar++);
@@ -653,31 +679,31 @@
}
/**
- * Set post dial state and acquire wake lock while switching to "started"
- * state, the wake lock will be released if state switches out of "started"
- * state or after WAKE_LOCK_TIMEOUT_MILLIS.
+ * Set post dial state and acquire wake lock while switching to "started"
+ * state, the wake lock will be released if state switches out of "started"
+ * state or after WAKE_LOCK_TIMEOUT_MILLIS.
* @param s new PostDialState
*/
private void setPostDialState(PostDialState s) {
- if (postDialState != PostDialState.STARTED
+ if (postDialState != PostDialState.STARTED
&& s == PostDialState.STARTED) {
acquireWakeLock();
Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
- } else if (postDialState == PostDialState.STARTED
+ } else if (postDialState == PostDialState.STARTED
&& s != PostDialState.STARTED) {
h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
releaseWakeLock();
}
postDialState = s;
}
-
+
private void
createWakeLock(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
}
-
+
private void
acquireWakeLock() {
log("acquireWakeLock");
@@ -693,7 +719,7 @@
}
}
}
-
+
private void log(String msg) {
Log.d(LOG_TAG, "[CDMAConn] " + msg);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 651c5051..64f9387 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -44,6 +44,7 @@
import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnectionTracker;
@@ -98,6 +99,13 @@
"com.android.internal.telephony.cdma-reconnect";
private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+ /**
+ * Constants for the data connection activity:
+ * physical link down/up
+ */
+ private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1;
+ private static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
+
// Possibly promoate to base class, the only difference is
// the INTENT_RECONNECT_ALARM action is a different string.
// Do consider technology changes if it is promoted.
@@ -258,7 +266,7 @@
}
/**
- * Simply tear down data connections due to radio off
+ * Simply tear down data connections due to radio off
* and don't setup again.
*/
public void cleanConnectionBeforeRadioOff() {
@@ -515,7 +523,7 @@
* override it with an unconditional power on.
*/
}
-
+
private Runnable mPollNetStat = new Runnable() {
public void run() {
@@ -608,19 +616,19 @@
/**
* Return true if data connection need to be setup after disconnected due to
* reason.
- *
+ *
* @param reason the reason why data is disconnected
- * @return true if try setup data connection is need for this reason
+ * @return true if try setup data connection is need for this reason
*/
private boolean retryAfterDisconnected(String reason) {
boolean retry = true;
-
+
if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
- Phone.REASON_DATA_DISABLED.equals(reason) ) {
+ Phone.REASON_DATA_DISABLED.equals(reason) ) {
retry = false;
}
return retry;
- }
+ }
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
@@ -843,6 +851,8 @@
}
protected void onDataStateChanged (AsyncResult ar) {
+ ArrayList<DataCallState> dataCallStates = (ArrayList<DataCallState>)(ar.result);
+
if (ar.exception != null) {
// This is probably "radio not available" or something
// of that sort. If so, the whole connection is going
@@ -851,7 +861,14 @@
}
if (state == State.CONNECTED) {
- Log.i(LOG_TAG, "Data connection has changed.");
+ if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_UP ) {
+ activity = Activity.NONE;
+ phone.notifyDataActivity();
+ } else if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_DOWN ) {
+ activity = Activity.DORMANT;
+ phone.notifyDataActivity();
+ }
+ } else {
int cid = -1;
EventLog.List val = new EventLog.List(cid,
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 42c0583..a3d00d7 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -29,7 +29,6 @@
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SMSDispatcher;
-//import com.android.internal.telephony.SMSDispatcher.SmsTracker;
import com.android.internal.telephony.cdma.SmsMessage;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.util.HexDump;
@@ -42,8 +41,11 @@
final class CdmaSMSDispatcher extends SMSDispatcher {
private static final String TAG = "CDMA";
+ private CDMAPhone mCdmaPhone;
+
CdmaSMSDispatcher(CDMAPhone phone) {
super(phone);
+ mCdmaPhone = phone;
}
/**
@@ -70,50 +72,39 @@
if (smsb == null) {
return;
}
- SmsMessage sms = (SmsMessage) smsb;
- int teleService;
- boolean handled = false;
// Decode BD stream and set sms variables.
+ SmsMessage sms = (SmsMessage) smsb;
sms.parseSms();
- teleService = sms.getTeleService();
+ int teleService = sms.getTeleService();
+ boolean handled = false;
// Teleservices W(E)MT and VMN are handled together:
- if ((SmsEnvelope.TELESERVICE_WMT == teleService)
- ||(SmsEnvelope.TELESERVICE_WEMT == teleService)
- ||(SmsEnvelope.TELESERVICE_VMN == teleService)){
+ if ((teleService == SmsEnvelope.TELESERVICE_WMT)
+ || (teleService == SmsEnvelope.TELESERVICE_WEMT)
+ || (teleService == SmsEnvelope.TELESERVICE_VMN)) {
// From here on we need decoded BD.
// Special case the message waiting indicator messages
if (sms.isMWISetMessage()) {
- ((CDMAPhone) mPhone).updateMessageWaitingIndicator(true);
-
- if (sms.isMwiDontStore()) {
- handled = true;
- }
-
+ mCdmaPhone.updateMessageWaitingIndicator(true);
+ handled |= sms.isMwiDontStore();
if (Config.LOGD) {
- Log.d(TAG,
- "Received voice mail indicator set SMS shouldStore=" + !handled);
+ Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
}
} else if (sms.isMWIClearMessage()) {
- ((CDMAPhone) mPhone).updateMessageWaitingIndicator(false);
-
- if (sms.isMwiDontStore()) {
- handled = true;
- }
-
+ mCdmaPhone.updateMessageWaitingIndicator(false);
+ handled |= sms.isMwiDontStore();
if (Config.LOGD) {
- Log.d(TAG,
- "Received voice mail indicator clear SMS shouldStore=" + !handled);
+ Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
}
}
}
- if (null == sms.getUserData()){
- handled = true;
+ if (sms.getUserData() == null) {
if (Config.LOGD) {
Log.d(TAG, "Received SMS without user data");
}
+ handled = true;
}
if (handled) return;
@@ -123,82 +114,44 @@
return;
}
- // Parse the headers to see if this is partial, or port addressed
- int referenceNumber = -1;
- int count = 0;
- int sequence = 0;
- int destPort = -1;
- // From here on we need BD distributed to SMS member variables.
+ /**
+ * TODO(cleanup): Why are we using a getter method for this
+ * (and for so many other sms fields)? Trivial getters and
+ * setters like this are direct violations of the style guide.
+ * If the purpose is to protect agaist writes (by not
+ * providing a setter) then any protection is illusory (and
+ * hence bad) for cases where the values are not primitives,
+ * such as this call for the header. Since this is an issue
+ * with the public API it cannot be changed easily, but maybe
+ * something can be done eventually.
+ */
+ SmsHeader smsHeader = sms.getUserDataHeader();
- SmsHeader header = sms.getUserDataHeader();
- if (header != null) {
- for (SmsHeader.Element element : header.getElements()) {
- try {
- switch (element.getID()) {
- case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
- byte[] data = element.getData();
-
- referenceNumber = data[0] & 0xff;
- count = data[1] & 0xff;
- sequence = data[2] & 0xff;
-
- // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
- // is zero, or sequence > count, ignore the entire element
- if (count == 0 || sequence == 0 || sequence > count) {
- referenceNumber = -1;
- }
- break;
- }
-
- case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
- byte[] data = element.getData();
-
- referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
- count = data[2] & 0xff;
- sequence = data[3] & 0xff;
-
- // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
- // is zero, or sequence > count, ignore the entire element
- if (count == 0 || sequence == 0 || sequence > count) {
- referenceNumber = -1;
- }
- break;
- }
-
- case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
- byte[] data = element.getData();
-
- destPort = (data[0] & 0xff) << 8;
- destPort |= (data[1] & 0xff);
-
- break;
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- Log.e(TAG, "Bad element in header", e);
- return; // TODO: NACK the message or something, don't just discard.
- }
- }
- }
-
- if (referenceNumber == -1) {
- // notify everyone of the message if it isn't partial
+ /**
+ * TODO(cleanup): Since both CDMA and GSM use the same header
+ * format, this dispatch processing is naturally identical,
+ * and code should probably not be replicated explicitly.
+ */
+ // See if message is partial or port addressed.
+ if ((smsHeader == null) || (smsHeader.concatRef == null)) {
+ // Message is not partial (not part of concatenated sequence).
byte[][] pdus = new byte[1][];
pdus[0] = sms.getPdu();
- if (destPort != -1) {// GSM-style WAP indication
- if (destPort == SmsHeader.PORT_WAP_PUSH) {
+ if (smsHeader != null && smsHeader.portAddrs != null) {
+ if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
+ // GSM-style WAP indication
mWapPush.dispatchWapPdu(sms.getUserData());
}
- // The message was sent to a port, so concoct a URI for it
- dispatchPortAddressedPdus(pdus, destPort);
+ // The message was sent to a port, so concoct a URI for it.
+ dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
} else {
- // It's a normal message, dispatch it
+ // Normal short and non-port-addressed message, dispatch it.
dispatchPdus(pdus);
}
} else {
- // Process the message part
- processMessagePart(sms, referenceNumber, sequence, count, destPort);
+ // Process the message part.
+ processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
}
}
@@ -314,41 +267,49 @@
}
/** {@inheritDoc} */
- protected void sendMultipartText(String destinationAddress, String scAddress,
+ protected void sendMultipartText(String destAddr, String scAddr,
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents) {
- int ref = ++sConcatenatedRef & 0xff;
+ /**
+ * TODO(cleanup): There is no real code difference between
+ * this and the GSM version, and hence it should be moved to
+ * the base class or consolidated somehow, provided calling
+ * the proper submitpdu stuff can be arranged.
+ */
- for (int i = 0, count = parts.size(); i < count; i++) {
- // build SmsHeader data
- byte[] data = new byte[5];
- data[0] = (byte) SmsHeader.CONCATENATED_8_BIT_REFERENCE;
- data[1] = (byte) 3; // 3 bytes follow
- data[2] = (byte) ref; // reference #, unique per message
- data[3] = (byte) count; // total part count
- data[4] = (byte) (i + 1); // 1-based sequence
+ int refNumber = getNextConcatenatedRef() & 0x00FF;
+
+ for (int i = 0, msgCount = parts.size(); i < msgCount; i++) {
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = refNumber;
+ concatRef.seqNumber = i + 1; // 1-based sequence
+ concatRef.msgCount = msgCount;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
PendingIntent sentIntent = null;
- PendingIntent deliveryIntent = null;
-
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
+
+ PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > i) {
deliveryIntent = deliveryIntents.get(i);
}
- SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
- parts.get(i), deliveryIntent != null, data);
+ SmsMessage.SubmitPdu submitPdu = SmsMessage.getSubmitPdu(scAddr, destAddr,
+ parts.get(i), deliveryIntent != null, smsHeader);
- sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+ sendSubmitPdu(submitPdu, sentIntent, deliveryIntent);
}
}
- protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+ protected void sendSubmitPdu(SmsMessage.SubmitPdu submitPdu, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
- super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+ sendRawPdu(submitPdu.encodedScAddress, submitPdu.encodedMessage,
+ sentIntent, deliveryIntent);
}
/** {@inheritDoc} */
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index d5cad1c..dbb0f93 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -33,6 +33,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony.Intents;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.cdma.CdmaCellLocation;
import android.text.TextUtils;
import android.util.EventLog;
@@ -70,8 +71,13 @@
CdmaCellLocation cellLoc;
CdmaCellLocation newCellLoc;
- int rssi = 99; // signal strength 0-31, 99=unknown
- // That's "received signal strength indication" fyi
+ /**
+ * TODO(Teleca): I don't think the initialization to -1 for all of these are
+ * really necessary, I don't seem them in GsmServiceStateTracker. Also,
+ * all of the other initialization is unnecessary as I believe Java guarantees
+ * 0, false & null, but if you think it's better than do all of them there are
+ * a few that aren't initialized.
+ */
/**
* The access technology currently in use: DATA_ACCESS_
@@ -80,9 +86,16 @@
private int newNetworkType = 0;
private boolean mCdmaRoaming = false;
+ private int mRoamingIndicator = -1;
+ private int mIsInPrl = -1;
+ private int mDefaultRoamingIndicator = -1;
- private int cdmaDataConnectionState = -1;//Initial we assume no data connection
- private int newCdmaDataConnectionState = -1;//Initial we assume no data connection
+ /**
+ * TODO(Teleca): Maybe these should be initialized to STATE_OUT_OF_SERVICE like gprsState
+ * in GsmServiceStateTracker and remove the comment.
+ */
+ private int cdmaDataConnectionState = -1; // Initially we assume no data connection
+ private int newCdmaDataConnectionState = -1; // Initially we assume no data connection
private int mRegistrationState = -1;
private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
@@ -95,12 +108,25 @@
// Keep track of SPN display rules, so we only broadcast intent if something changes.
private String curSpn = null;
- private String curPlmn = null;
+ private String curEriText = null;
private int curSpnRule = 0;
+ private String mMdn = null;
+ private int mHomeSystemId = -1;
+ private int mHomeNetworkId = -1;
+ private String mMin = null;
+ private boolean isEriTextLoaded = false;
+ private boolean isSubscriptionFromRuim = false;
+
+ /**
+ * TODO(Teleca): Is this purely for debugging purposes, or do we expect this string to be
+ * passed around (eg, to the UI)? If the latter, it would be better to pass around a
+ * reasonCode, and let the UI provide its own strings.
+ */
+ private String mRegistrationDeniedReason = null;
+
//***** Constants
static final String LOG_TAG = "CDMA";
- static final String TMUK = "23430";
private ContentResolver cr;
@@ -124,6 +150,7 @@
newSS = new ServiceState();
cellLoc = new CdmaCellLocation();
newCellLoc = new CdmaCellLocation();
+ mSignalStrength = new SignalStrength();
cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
@@ -133,7 +160,8 @@
cm.registerForRUIMReady(this, EVENT_RUIM_READY, null);
- phone.registerForNvLoaded(this, EVENT_NV_LOADED,null);
+ cm.registerForNVReady(this, EVENT_NV_READY, null);
+ phone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
// system setting property AIRPLANE_MODE_ON is set in Settings.
int airplaneMode = Settings.System.getInt(
@@ -145,7 +173,7 @@
cr.registerContentObserver(
Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
mAutoTimeObserver);
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mNeedToRegForRuimLoaded = true;
}
@@ -156,14 +184,15 @@
cm.unregisterForRadioStateChanged(this);
cm.unregisterForNetworkStateChanged(this);
cm.unregisterForRUIMReady(this);
- phone.unregisterForNvLoaded(this);
+ cm.unregisterForNVReady(this);
+ phone.unregisterForEriFileLoaded(this);
phone.mRuimRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cr.unregisterContentObserver(this.mAutoTimeObserver);
}
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "CdmaServiceStateTracker finalized");
+ if (DBG) log("CdmaServiceStateTracker finalized");
}
void registerForNetworkAttach(Handler h, int what, Object obj) {
@@ -246,13 +275,21 @@
// The RUIM is now ready i.e if it was locked
// it has been unlocked. At this stage, the radio is already
// powered on.
+ isSubscriptionFromRuim = true;
if (mNeedToRegForRuimLoaded) {
phone.mRuimRecords.registerForRecordsLoaded(this,
EVENT_RUIM_RECORDS_LOADED, null);
mNeedToRegForRuimLoaded = false;
}
// restore the previous network selection.
- phone.restoreSavedNetworkSelection(null);
+ pollState();
+
+ // Signal strength polling stops when radio is off
+ queueNextSignalStrengthPoll();
+ break;
+
+ case EVENT_NV_READY:
+ isSubscriptionFromRuim = false;
pollState();
// Signal strength polling stops when radio is off
queueNextSignalStrengthPoll();
@@ -328,9 +365,9 @@
}
break;
- case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA: //Fall through
- case EVENT_POLL_STATE_REGISTRATION_CDMA: //Fall through
+ case EVENT_POLL_STATE_REGISTRATION_CDMA:
case EVENT_POLL_STATE_OPERATOR_CDMA:
+ case EVENT_POLL_STATE_CDMA_SUBSCRIPTION:
ar = (AsyncResult) msg.obj;
handlePollStateResult(msg.what, ar);
break;
@@ -355,7 +392,6 @@
break;
case EVENT_RUIM_RECORDS_LOADED:
- case EVENT_NV_LOADED:
updateSpnDisplay();
break;
@@ -367,6 +403,12 @@
}
break;
+ case EVENT_ERI_FILE_LOADED:
+ // Repoll the state once the ERI file has been loaded
+ if (DBG) log("[CdmaServiceStateTracker] ERI file has been loaded, repolling.");
+ pollState();
+ break;
+
default:
Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
break;
@@ -391,13 +433,14 @@
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
}
dcTracker.cleanConnectionBeforeRadioOff();
-
- // poll data state up to 15 times, with a 100ms delay
+
+ // Poll data state up to 15 times, with a 100ms delay
// totaling 1.5 sec. Normal data disable action will finish in 100ms.
for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
- if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
- && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
- Log.d(LOG_TAG, "Data shutdown complete.");
+ DataConnectionTracker.State currentState = dcTracker.getState();
+ if (currentState != DataConnectionTracker.State.CONNECTED
+ && currentState != DataConnectionTracker.State.DISCONNECTING) {
+ if (DBG) log("Data shutdown complete.");
break;
}
SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
@@ -409,29 +452,29 @@
protected void updateSpnDisplay() {
- // TODO Check this method again, because it is not sure at the moment how
- // the RUIM handles the SIM stuff
+ // TODO(Teleca): Check this method again, because it is not sure at the moment how
+ // the RUIM handles the SIM stuff. Please complete this function.
//int rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric());
String spn = null; //phone.mRuimRecords.getServiceProviderName();
- String plmn = ss.getOperatorAlphaLong();
+ String eri = ss.getOperatorAlphaLong();
- if (!TextUtils.equals(this.curPlmn, plmn)) {
+ if (!TextUtils.equals(this.curEriText, eri)) {
//TODO (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
boolean showSpn = false;
//TODO (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
- boolean showPlmn = true;
+ boolean showEri = true;
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
intent.putExtra(Intents.EXTRA_SPN, spn);
- intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
- intent.putExtra(Intents.EXTRA_PLMN, plmn);
+ intent.putExtra(Intents.EXTRA_SHOW_PLMN, showEri);
+ intent.putExtra(Intents.EXTRA_PLMN, eri);
phone.getContext().sendStickyBroadcast(intent);
}
//curSpnRule = rule;
//curSpn = spn;
- this.curPlmn = plmn;
+ this.curEriText = eri;
}
/**
@@ -473,11 +516,17 @@
}
} else try {
switch (what) {
- case EVENT_POLL_STATE_REGISTRATION_CDMA:
- //offset, because we don't want the first 3 values in the int-array
+ case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE,
+ // the offset is because we don't want the
+ // first 3 values in the
+ // responseValuesRegistrationState array.
final int offset = 3;
states = (String[])ar.result;
+ /**
+ * TODO(Teleca): Change from array to a "Class" or local
+ * variables so names instead of index's can be used.
+ */
int responseValuesRegistrationState[] = {
-1, //[0] radioTechnology
-1, //[1] baseStationId
@@ -486,38 +535,40 @@
0, //[4] cssIndicator; init with 0, because it is treated as a boolean
-1, //[5] systemId
-1, //[6] networkId
- -1, //[7] TSB-58 Roaming indicator // NEWRIL:TODO UNUSED
- -1, //[8] Indicates if current system is in PRL // NEWRIL:TODO UNUSED
- -1, //[9] Is default roaming indicator from PRL // NEWRIL:TODO UNUSED
- -1, //[10] If registration state is 3 this is reason for denial // NEWRIL:TODO UNUSED
+ -1, //[7] Roaming indicator
+ -1, //[8] Indicates if current system is in PRL
+ -1, //[9] Is default roaming indicator from PRL
+ -1, //[10] If registration state is 3 this is reason for denial
};
- if (states.length > 0) {
+ if (states.length == 14) {
try {
this.mRegistrationState = Integer.parseInt(states[0]);
- if (states.length >= 10) {
- for(int i = 0; i < states.length - offset; i++) {
- if (states[i + offset] != null
- && states[i + offset].length() > 0) {
- try {
- responseValuesRegistrationState[i] =
- Integer.parseInt(states[i + offset], 16);
- }
- catch(NumberFormatException ex) {
- Log.w(LOG_TAG, "Warning! There is an unexpected value"
- + "returned as response from "
- + "RIL_REQUEST_REGISTRATION_STATE.");
- }
- }
- }
- }
- else {
- Log.e(LOG_TAG, "Too less parameters returned from"
- + " RIL_REQUEST_REGISTRATION_STATE");
- }
} catch (NumberFormatException ex) {
Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
}
+ try {
+ responseValuesRegistrationState[0] = Integer.parseInt(states[3]);
+ responseValuesRegistrationState[1] = Integer.parseInt(states[4], 16);
+ responseValuesRegistrationState[2] = Integer.parseInt(states[5], 16);
+ responseValuesRegistrationState[3] = Integer.parseInt(states[6], 16);
+ responseValuesRegistrationState[4] = Integer.parseInt(states[7]);
+ responseValuesRegistrationState[5] = Integer.parseInt(states[8]);
+ responseValuesRegistrationState[6] = Integer.parseInt(states[9]);
+ responseValuesRegistrationState[7] = Integer.parseInt(states[10]);
+ responseValuesRegistrationState[8] = Integer.parseInt(states[11]);
+ responseValuesRegistrationState[9] = Integer.parseInt(states[12]);
+ responseValuesRegistrationState[10] = Integer.parseInt(states[13]);
+ }
+ catch(NumberFormatException ex) {
+ Log.w(LOG_TAG, "Warning! There is an unexpected value"
+ + "returned as response from "
+ + "RIL_REQUEST_REGISTRATION_STATE.");
+ }
+ } else {
+ throw new RuntimeException("Warning! Wrong number of parameters returned from "
+ + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
+ + states.length);
}
mCdmaRoaming = regCodeIsRoaming(this.mRegistrationState);
@@ -529,26 +580,62 @@
newSS.setSystemAndNetworkId(responseValuesRegistrationState[5],
responseValuesRegistrationState[6]);
+ mRoamingIndicator = responseValuesRegistrationState[7];
+ mIsInPrl = responseValuesRegistrationState[8];
+ mDefaultRoamingIndicator = responseValuesRegistrationState[9];
+
newNetworkType = responseValuesRegistrationState[0];
// values are -1 if not available
newCellLoc.setCellLocationData(responseValuesRegistrationState[1],
responseValuesRegistrationState[2],
responseValuesRegistrationState[3]);
- break;
- case EVENT_POLL_STATE_OPERATOR_CDMA:
- String opNames[] = (String[])ar.result;
+ if (responseValuesRegistrationState[10] == 0) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
+ } else if (responseValuesRegistrationState[10] == 1) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
+ } else {
+ mRegistrationDeniedReason = "";
+ }
- if (opNames != null && opNames.length >= 3) {
- newSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
+ if (mRegistrationState == 3) {
+ if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
}
break;
- case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA:
- ints = (int[])ar.result;
- newSS.setIsManualSelection(ints[0] == 1);
+ case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
+ String opNames[] = (String[])ar.result;
+
+ if (opNames != null && opNames.length >= 3) {
+ // TODO(Teleca): Is this necessary here and in the else clause?
+ newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+ if (phone.mCM.getRadioState().isNVReady()) {
+ // In CDMA in case on NV the ss.mOperatorAlphaLong is set later with the
+ // ERI text, so here is ignored what is coming from the modem
+ newSS.setOperatorName(null, opNames[1], opNames[2]);
+ } else {
+ newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+ }
+ } else {
+ Log.w(LOG_TAG, "error parsing opNames");
+ }
break;
+
+ case EVENT_POLL_STATE_CDMA_SUBSCRIPTION: // Handle RIL_CDMA_SUBSCRIPTION
+ String cdmaSubscription[] = (String[])ar.result;
+
+ if (cdmaSubscription != null && cdmaSubscription.length >= 4) {
+ mMdn = cdmaSubscription[0];
+ mHomeSystemId = Integer.parseInt(cdmaSubscription[1], 16);
+ mHomeNetworkId = Integer.parseInt(cdmaSubscription[2], 16);
+ mMin = cdmaSubscription[3];
+
+ } else {
+ Log.w(LOG_TAG, "error parsing cdmaSubscription");
+ }
+ break;
+
default:
Log.e(LOG_TAG, "RIL response handle in wrong phone!"
+ " Expected CDMA RIL request and get GSM RIL request.");
@@ -563,29 +650,58 @@
pollingContext[0]--;
if (pollingContext[0] == 0) {
- newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+ boolean namMatch = false;
+ if ((mHomeSystemId != 0) && (mHomeSystemId == newSS.getSystemId()) ) {
+ namMatch = true;
+ }
- switch(this.mRegistrationState) {
- case ServiceState.REGISTRATION_STATE_HOME_NETWORK:
- newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_HOME_NETWORK);
- break;
- case ServiceState.REGISTRATION_STATE_ROAMING:
- newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING);
- break;
- case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
- newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE);
- break;
- default:
- Log.w(LOG_TAG, "Received a different registration state, "
- + "but don't changed the extended cdma roaming mode.");
+ // Setting SS Roaming (general)
+ if (isSubscriptionFromRuim) {
+ newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+ } else {
+ newSS.setRoaming(mCdmaRoaming);
+ }
+
+ /**
+ * TODO(Teleca): This would be simpler if mIsInPrl was a "boolean" as the
+ * name implies rather than tri-state. Above I've suggested that the -1's
+ * might be able to be removed, if so please simplify this. Otherwise change
+ * the name to mPrlState or some such. Also the logic can be simplified
+ * by testing for "mIsInPrl" only once.
+ */
+ // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
+ // TODO(Teleca): use constants for the standard roaming indicators
+ if (mIsInPrl == 0 && mRegistrationState == 5) {
+ // System is acquired but prl not loaded or no prl match
+ newSS.setCdmaRoamingIndicator(2); //FLASHING
+ } else if (!namMatch && (mIsInPrl == 1)) {
+ // System is acquired, no nam match, prl match
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+ } else if (namMatch && (mIsInPrl == 1) && mRoamingIndicator <= 2) {
+ // System is acquired, nam match, prl match, mRoamingIndicator <= 2
+ newSS.setCdmaRoamingIndicator(1); //OFF
+ } else if (namMatch && (mIsInPrl == 1) && mRoamingIndicator > 2) {
+ // System is acquired, nam match, prl match, mRoamingIndicator > 2
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+ }
+ newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
+
+ // NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
+ // depending on the mRoamingIndicator.
+
+ if (DBG) {
+ log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
+ + ". mCdmaRoaming = " + mCdmaRoaming + ", namMatch = " + namMatch
+ + ", mIsInPrl= " + mIsInPrl + ", mRoamingIndicator = " + mRoamingIndicator
+ + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
}
pollStateDone();
}
}
- private void setRssiDefaultValues() {
- rssi = 99;
+ private void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, false);
}
/**
@@ -606,7 +722,7 @@
case RADIO_UNAVAILABLE:
newSS.setStateOutOfService();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
pollStateDone();
@@ -615,7 +731,7 @@
case RADIO_OFF:
newSS.setStateOff();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
pollStateDone();
@@ -627,10 +743,10 @@
log("Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
- pollStateDone();
+ //NOTE: pollStateDone() is not needed in this case
break;
default:
@@ -639,20 +755,21 @@
// are allowed to arrive out-of-order
pollingContext[0]++;
- //RIL_REQUEST_OPERATOR is necessary for CDMA
- cm.getOperator(
- obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+ // RIL_REQUEST_CDMA_SUBSCRIPTION is necessary for CDMA
+ cm.getCDMASubscription(
+ obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION, pollingContext));
- pollingContext[0]++;
- //RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
- cm.getRegistrationState(
- obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+ pollingContext[0]++;
+ // RIL_REQUEST_OPERATOR is necessary for CDMA
+ cm.getOperator(
+ obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
- pollingContext[0]++;
- //RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE necessary for CDMA
- cm.getNetworkSelectionMode(
- obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA, pollingContext));
- break;
+ pollingContext[0]++;
+ // RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
+ cm.getRegistrationState(
+ obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+
+ break;
}
}
@@ -685,12 +802,7 @@
private void
pollStateDone() {
- if (DBG) {
- Log.d(LOG_TAG, "Poll ServiceState done: " +
- " oldSS=[" + ss );
- Log.d(LOG_TAG, "Poll ServiceState done: " +
- " newSS=[" + newSS);
- }
+ if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
boolean hasRegistered =
ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -757,6 +869,22 @@
}
if (hasChanged) {
+ if (phone.mCM.getRadioState().isNVReady()) {
+ String eriText;
+ // Now the CDMAPhone sees the new ServiceState so it can get the new ERI text
+ if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ eriText = phone.getCdmaEriText();
+ } else {
+ // Note that this is valid only for mRegistrationState 2,3,4, not 0!
+ /**
+ * TODO(Teleca): From the comment this apparently isn't always true
+ * should there be additional logic with other strings?
+ */
+ eriText = EriInfo.SEARCHING_TEXT;
+ }
+ ss.setCdmaEriText(eriText);
+ }
+
String operatorNumeric;
phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
@@ -784,8 +912,6 @@
phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
ss.getRoaming() ? "true" : "false");
- phone.setSystemProperty(PROPERTY_OPERATOR_ISMANUAL,
- ss.getIsManualSelection() ? "true" : "false");
updateSpnDisplay();
phone.notifyServiceStateChanged(ss);
@@ -825,10 +951,7 @@
// Couldn't find a proper timezone. Perhaps the DST data is wrong.
guess = findTimeZone(offset, !dst, when);
}
- if (DBG) {
- Log.d(LOG_TAG, "getNitzTimeZone returning "
- + (guess == null ? guess : guess.getID()));
- }
+ if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
return guess;
}
@@ -865,41 +988,49 @@
msg = obtainMessage();
msg.what = EVENT_POLL_SIGNAL_STRENGTH;
- // TODO Done't poll signal strength if screen is off
+ // TODO(Teleca): Don't poll signal strength if screen is off
sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
}
/**
- * send signal-strength-changed notification if rssi changed
+ * send signal-strength-changed notification if changed
* Called both for solicited and unsolicited signal stength updates
*/
private void
onSignalStrengthResult(AsyncResult ar) {
- int oldRSSI = rssi;
+ SignalStrength oldSignalStrength = mSignalStrength;
if (ar.exception != null) {
- // 99 = unknown
- // most likely radio is resetting/disconnected
- rssi = 99;
+ // Most likely radio is resetting/disconnected change to default values.
+ setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;
+ int offset = 2;
- // bug 658816 seems to be a case where the result is 0-length
- if (ints.length != 0) {
- rssi = ints[0];
- } else {
- Log.e(LOG_TAG, "Bogus signal strength response");
- rssi = 99;
+ int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -1;
+ int cdmaEcio = (ints[offset+1] > 0) ? -ints[offset+1] : -1;
+
+ int evdoRssi = -1;
+ int evdoEcio = -1;
+ int evdoSnr = -1;
+ if ((networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+ || (networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
+ evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -1;
+ evdoEcio = (ints[offset+3] > 0) ? -ints[offset+3] : -1;
+ evdoSnr = ((ints[offset+4] > 0) && (ints[offset+4] <= 8)) ? ints[offset+4] : -1;
}
+
+ mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
+ evdoRssi, evdoEcio, evdoSnr, false);
}
- if (rssi != oldRSSI) {
+ if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
- log("onSignalStrengthResult() Phone already destroyed: " + ex
- + "Signal Stranth not notified");
+ log("onSignalStrengthResult() Phone already destroyed: " + ex
+ + "SignalStrength not notified");
}
}
}
@@ -943,9 +1074,7 @@
case 3: // 3 is "registration denied", fall through
case 4: // 4 is "unknown" no vaild in current baseband
return ServiceState.STATE_OUT_OF_SERVICE;
- case 5:// fall through
- case 6:
- // Registered and: roaming (5) or roaming affiliates (6)
+ case 5:// 5 is "Registered, roaming"
return ServiceState.STATE_IN_SERVICE;
default:
@@ -983,6 +1112,8 @@
boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
+ // NOTE: in case of RUIM we should completely ignore the ERI data file and
+ // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS)
String onsl = s.getOperatorAlphaLong();
String onss = s.getOperatorAlphaShort();
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
new file mode 100644
index 0000000..40358c8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
@@ -0,0 +1,65 @@
+/*
+ * 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.telephony.cdma;
+
+public final class EriInfo {
+
+ public static final int ROAMING_INDICATOR_ON = 0;
+ public static final int ROAMING_INDICATOR_OFF = 1;
+ public static final int ROAMING_INDICATOR_FLASH = 2;
+
+ public static final int ROAMING_ICON_MODE_NORMAL = 0;
+ public static final int ROAMING_ICON_MODE_FLASH = 1;
+
+ /**
+ * TODO(Teleca): These strings appear to be used by the UI
+ * hence they must be changed to resources so they can be
+ * translated to the appropriate language.
+ */
+ public static final String ROAMING_TEXT_0 = "Roaming Indicator On";
+ public static final String ROAMING_TEXT_1 = "Roaming Indicator Off";
+ public static final String ROAMING_TEXT_2 = "Roaming Indicator Flashing";
+ public static final String ROAMING_TEXT_3 = "Out of Neighborhood";
+ public static final String ROAMING_TEXT_4 = "Out of Building";
+ public static final String ROAMING_TEXT_5 = "Roaming - Preferred System";
+ public static final String ROAMING_TEXT_6 = "Roaming - Available System";
+ public static final String ROAMING_TEXT_7 = "Roaming - Alliance Partner";
+ public static final String ROAMING_TEXT_8 = "Roaming - Premium Partner";
+ public static final String ROAMING_TEXT_9 = "Roaming - Full Service Functionality";
+ public static final String ROAMING_TEXT_10 = "Roaming - Partial Service Functionality";
+ public static final String ROAMING_TEXT_11 = "Roaming Banner On";
+ public static final String ROAMING_TEXT_12 = "Roaming Banner Off";
+
+ public static final String SEARCHING_TEXT = "Searching for Svc.";
+
+
+ public int mRoamingIndicator;
+ public int mIconIndex;
+ public int mIconMode;
+ public String mEriText;
+ public int mCallPromptId;
+ public int mAlertId;
+
+ public EriInfo (int roamingIndicator, int iconIndex, int iconMode, String eriText,
+ int callPromptId, int alertId) {
+
+ this.mRoamingIndicator = roamingIndicator;
+ this.mIconIndex = iconIndex;
+ this.mIconMode = iconMode;
+ this.mEriText = eriText;
+ this.mCallPromptId = callPromptId;
+ this.mAlertId = alertId;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
new file mode 100644
index 0000000..d905e66
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -0,0 +1,224 @@
+/*
+ * 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.telephony.cdma;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+
+import com.android.internal.util.XmlUtils;
+
+import java.util.HashMap;
+
+/**
+ * TODO(Teleca): Please as some comments on how this class is to
+ * be used. We've removed Handler as a base class and instead
+ * recommend that child classes add a Handler as a member if its
+ * needed.
+ */
+
+
+public final class EriManager {
+
+ class EriFile {
+ public static final int MAX_ERI_ENTRIES = 30;
+
+ public int mVersionNumber; // File version number
+ public int mNumberOfEriEntries; // Number of entries
+ public int mEriFileType; // Eri Phase 0/1
+ //public int mNumberOfIconImages; // reserved for future use
+ //public int mIconImageType; // reserved for future use
+ public String[] mCallPromptId; // reserved for future use
+ public HashMap<Integer, EriInfo> mRoamIndTable; // Roaming Indicator Table
+
+ public EriFile() {
+ this.mVersionNumber = -1;
+ this.mNumberOfEriEntries = 0;
+ this.mEriFileType = -1;
+ this.mCallPromptId = new String[] { "", "", "" };
+ this.mRoamIndTable = new HashMap<Integer, EriInfo>();
+ }
+
+ }
+
+ static final String LOG_TAG = "CDMA";
+
+ public static final int ERI_FROM_XML = 0;
+ public static final int ERI_FROM_FILE_SYSTEM = 1;
+ public static final int ERI_FROM_MODEM = 2;
+
+ private PhoneBase mPhone;
+ private Context mContext;
+ private int mEriFileSource = ERI_FROM_XML;
+ private boolean isEriFileLoaded = false;
+ private EriFile mEriFile;
+
+ public EriManager(PhoneBase phone, Context context, int eriFileSource) {
+ this.mPhone = phone;
+ this.mContext = context;
+ this.mEriFileSource = eriFileSource;
+ this.mEriFile = new EriFile();
+ }
+
+ public void dispose() {
+ mEriFile = new EriFile();
+ isEriFileLoaded = false;
+ }
+
+
+ public void loadEriFile() {
+ switch (mEriFileSource) {
+ case ERI_FROM_MODEM:
+ loadEriFileFromModem();
+ break;
+
+ case ERI_FROM_FILE_SYSTEM:
+ loadEriFileFromFileSystem();
+ break;
+
+ case ERI_FROM_XML:
+ default:
+ loadEriFileFromXml();
+ break;
+ }
+ }
+
+ /**
+ * Load the ERI file from the MODEM through chipset specific RIL_REQUEST_OEM_HOOK
+ *
+ * In this case the ERI file can be updated from the Phone Support Tool available
+ * from the Chipset vendor
+ */
+ private void loadEriFileFromModem() {
+ // NOT IMPLEMENTED, Chipset vendor/Operator specific
+ }
+
+ /**
+ * Load the ERI file from a File System file
+ *
+ * In this case the a Phone Support Tool to update the ERI file must be provided
+ * to the Operator
+ */
+ private void loadEriFileFromFileSystem() {
+ // NOT IMPLEMENTED, Chipset vendor/Operator specific
+ }
+
+ /**
+ * Load the ERI file from the application framework resources encoded in XML
+ *
+ */
+ private void loadEriFileFromXml() {
+ Resources r = mContext.getResources();
+ XmlResourceParser parser = r.getXml(com.android.internal.R.xml.eri);
+ try {
+ XmlUtils.beginDocument(parser, "EriFile");
+ mEriFile.mVersionNumber = Integer.parseInt(
+ parser.getAttributeValue(null, "VersionNumber"));
+ mEriFile.mNumberOfEriEntries = Integer.parseInt(
+ parser.getAttributeValue(null, "NumberOfEriEntries"));
+ mEriFile.mEriFileType = Integer.parseInt(
+ parser.getAttributeValue(null, "EriFileType"));
+
+ int parsedEriEntries = 0;
+ while(true) {
+ XmlUtils.nextElement(parser);
+ String name = parser.getName();
+ if (name == null) {
+ if (parsedEriEntries != mEriFile.mNumberOfEriEntries)
+ Log.e(LOG_TAG, "Error Parsing ERI file: " + mEriFile.mNumberOfEriEntries
+ + " defined, " + parsedEriEntries + " parsed!");
+ break;
+ } else if (name.equals("CallPromptId")) {
+ int id = Integer.parseInt(parser.getAttributeValue(null, "Id"));
+ String text = parser.getAttributeValue(null, "CallPromptText");
+ if (id >= 0 && id <= 2) {
+ mEriFile.mCallPromptId[id] = text;
+ } else {
+ Log.e(LOG_TAG, "Error Parsing ERI file: found" + id + " CallPromptId");
+ }
+
+ } else if (name.equals("EriInfo")) {
+ int roamingIndicator = Integer.parseInt(
+ parser.getAttributeValue(null, "RoamingIndicator"));
+ int iconIndex = Integer.parseInt(parser.getAttributeValue(null, "IconIndex"));
+ int iconMode = Integer.parseInt(parser.getAttributeValue(null, "IconMode"));
+ String eriText = parser.getAttributeValue(null, "EriText");
+ int callPromptId = Integer.parseInt(
+ parser.getAttributeValue(null, "CallPromptId"));
+ int alertId = Integer.parseInt(parser.getAttributeValue(null, "AlertId"));
+ parsedEriEntries++;
+ mEriFile.mRoamIndTable.put(roamingIndicator, new EriInfo (roamingIndicator,
+ iconIndex, iconMode, eriText, callPromptId, alertId));
+ }
+ }
+
+ isEriFileLoaded = true;
+
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Got exception while loading ERI file.", e);
+ } finally {
+ parser.close();
+ }
+ }
+
+ /**
+ * Returns the version of the ERI file
+ *
+ */
+ public int getEriFileVersion() {
+ return mEriFile.mVersionNumber;
+ }
+
+ /**
+ * Returns the number of ERI entries parsed
+ *
+ */
+ public int getEriNumberOfEntries() {
+ return mEriFile.mNumberOfEriEntries;
+ }
+
+ /**
+ * Returns the ERI file type value ( 0 for Phase 0, 1 for Phase 1)
+ *
+ */
+ public int getEriFileType() {
+ return mEriFile.mEriFileType;
+ }
+
+ /**
+ * Returns if the ERI file has been loaded
+ *
+ */
+ public boolean isEriFileLoaded() {
+ return isEriFileLoaded;
+ }
+
+ /**
+ * Returns the EriInfo record associated with roamingIndicator
+ * or null if the entry is not found
+ */
+ public EriInfo getEriInfo(int roamingIndicator) {
+ if (mEriFile.mRoamIndTable.containsKey(roamingIndicator)) {
+ return mEriFile.mRoamIndTable.get(roamingIndicator);
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
index 9de6c42..3e2a29b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -68,7 +68,12 @@
}
protected String getEFPath(int efid) {
- // TODO(): Implement for CDMA EFs.
+ switch(efid) {
+ case EF_SMS:
+ case EF_CST:
+ case EF_RUIM_SPN:
+ return MF_SIM + DF_CDMA;
+ }
return getCommonIccEFPath(efid);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index b18a3f1..321824f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -49,13 +49,12 @@
private static final boolean DBG = true;
//***** Instance Variables
- String imsi_m;
- String mdn = null; // My mobile number
- String h_sid;
- String h_nid;
- String min2_min1; // 10 digit MIN value MIN2+MIN1 NEWRIL:TODO currently unused
- // is not initialized
+ private String mImsi; // TODO(Teleca): to be checked, if this should be removed!
+ private String mMyMobileNumber;
+ private String mSid; // TODO(Teleca): Unused should this be removed
+ private String mNid; // TODO(Teleca): Unused should this be removed
+ private String mMin2Min1;
//***** Event Constants
@@ -63,6 +62,7 @@
private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
private static final int EVENT_GET_ICCID_DONE = 5;
+ private static final int EVENT_NV_READY = 9;
private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
private static final int EVENT_UPDATE_DONE = 14;
private static final int EVENT_GET_SST_DONE = 17;
@@ -74,8 +74,6 @@
private static final int EVENT_RUIM_REFRESH = 31;
- //***** Constructor
-
RuimRecords(CDMAPhone p) {
super(p);
@@ -88,6 +86,7 @@
p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+ p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
// NOTE the EVENT_SMS_ON_RUIM is not registered
p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
@@ -104,10 +103,12 @@
phone.mCM.unSetOnIccRefresh(this);
}
+ @Override
protected void finalize() {
if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
}
+ @Override
protected void onRadioOffOrNotAvailable() {
countVoiceMessages = 0;
mncLength = 0;
@@ -124,17 +125,20 @@
recordsRequested = false;
}
- //***** Public Methods
-
/** Returns null if RUIM is not yet ready */
public String getIMSI_M() {
- return imsi_m;
+ return mImsi;
}
public String getMdnNumber() {
- return mdn;
+ return mMyMobileNumber;
}
+ public String getMin() {
+ return mMin2Min1;
+ }
+
+ @Override
public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
// In CDMA this is Operator/OEM dependent
AsyncResult.forMessage((onComplete)).exception =
@@ -148,6 +152,7 @@
* @param fileChanged indicates whether any files changed
* @param fileList if non-null, a list of EF files that changed
*/
+ @Override
public void onRefresh(boolean fileChanged, int[] fileList) {
if (fileChanged) {
// A future optimization would be to inspect fileList and
@@ -157,11 +162,12 @@
}
}
- /** Returns the 5 or 6 digit MCC/MNC of the operator that
+ /**
+ * Returns the 5 or 6 digit MCC/MNC of the operator that
* provided the RUIM card. Returns null of RUIM is not yet ready
*/
- String getRUIMOperatorNumeric() {
- if (imsi_m == null) {
+ public String getRUIMOperatorNumeric() {
+ if (mImsi == null) {
return null;
}
@@ -169,7 +175,7 @@
// Length = length of MCC + length of MNC
// TODO: change spec name
// length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
- return imsi_m.substring(0, 3 + mncLength);
+ return mImsi.substring(0, 3 + mncLength);
}
// Guess the MNC length based on the MCC if we don't
@@ -177,12 +183,12 @@
int mcc;
- mcc = Integer.parseInt(imsi_m.substring(0,3));
+ mcc = Integer.parseInt(mImsi.substring(0,3));
- return imsi_m.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
+ return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
}
- //***** Overridden from Handler
+ @Override
public void handleMessage(Message msg) {
AsyncResult ar;
@@ -194,7 +200,9 @@
case EVENT_RUIM_READY:
onRuimReady();
break;
-
+ case EVENT_NV_READY:
+ onNvReady();
+ break;
case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
onRadioOffOrNotAvailable();
break;
@@ -212,14 +220,12 @@
break;
}
- mdn = localTemp[0];
- h_sid = localTemp[1];
- h_nid = localTemp[2];
- if (localTemp.length >= 3) { // NEWRIL:TODO remove when new ril always returns min2_min1
- min2_min1 = localTemp[3];
- }
+ mMyMobileNumber = localTemp[0];
+ mSid = localTemp[1];
+ mNid = localTemp[2];
+ mMin2Min1 = localTemp[3];
- Log.d(LOG_TAG, "MDN: " + mdn);
+ Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
break;
@@ -277,6 +283,7 @@
}
}
+ @Override
protected void onRecordLoaded() {
// One record loaded successfully or failed, In either case
// we need to update the recordsToLoad count
@@ -290,6 +297,7 @@
}
}
+ @Override
protected void onAllRecordsLoaded() {
Log.d(LOG_TAG, "RuimRecords: record load complete");
@@ -301,9 +309,6 @@
RuimCard.INTENT_VALUE_ICC_LOADED, null);
}
-
- //***** Private Methods
-
private void onRuimReady() {
/* broadcast intent ICC_READY here so that we can make sure
READY is sent before IMSI ready
@@ -318,6 +323,11 @@
}
+ private void onNvReady() {
+ phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
+
+ }
+
private void fetchRuimRecords() {
recordsRequested = true;
@@ -391,9 +401,9 @@
}
}
+ @Override
protected void log(String s) {
Log.d(LOG_TAG, "[RuimRecords] " + s);
}
}
-
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 343a22e..b2083ed 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -277,6 +277,15 @@
}
/**
+ * TODO(cleanup): why do getSubmitPdu methods take an scAddr input
+ * and do nothing with it? GSM allows us to specify a SC (eg,
+ * when responding to an SMS that explicitly requests the response
+ * is sent to a specific SC), or pass null to use the default
+ * value. Is there no similar notion in CDMA? Or do we just not
+ * have it hooked up?
+ */
+
+ /**
* Get an SMS-SUBMIT PDU for a destination address and a message
*
* @param scAddr Service Centre address. Null means use default.
@@ -290,88 +299,53 @@
* Returns null on encode error.
* @hide
*/
- public static SubmitPdu getSubmitPdu(String scAddr,
- String destAddr, String message,
- boolean statusReportRequested, byte[] headerData) {
- /**
- * TODO(cleanup): why does this method take an scAddr input
- * and do nothing with it? GSM allows us to specify a SC (eg,
- * when responding to an SMS that explicitly requests the
- * response is sent to a specific SC), or pass null to use the
- * default value. Is there no similar notion in CDMA? Or do
- * we just not have it hooked up?
- */
+ public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message,
+ boolean statusReportRequested, SmsHeader smsHeader) {
+ /**
+ * TODO(cleanup): Do we really want silent failure like this?
+ * Would it not be much more reasonable to make sure we don't
+ * call this function if we really want nothing done?
+ */
if (message == null || destAddr == null) {
return null;
}
UserData uData = new UserData();
uData.payloadStr = message;
- if(headerData != null) {
- /**
- * TODO(cleanup): we force the outside to deal with _all_
- * of the raw details of properly constructing serialized
- * headers, unserialze here, and then promptly reserialze
- * during encoding -- rather undesirable.
- */
- uData.userDataHeader = SmsHeader.parse(headerData);
- }
-
- return privateGetSubmitPdu(destAddr, statusReportRequested, uData, (headerData == null));
- }
-
-
- /**
- * Get an SMS-SUBMIT PDU for a destination address and a message
- *
- * @param scAddress Service Centre address. Null means use default.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
- */
- public static SubmitPdu getSubmitPdu(String scAddress,
- String destinationAddress, String message,
- boolean statusReportRequested) {
- return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+ uData.userDataHeader = smsHeader;
+ return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
}
/**
* Get an SMS-SUBMIT PDU for a data message to a destination address & port
*
- * @param scAddress Service Centre address. null == use default
- * @param destinationAddress the address of the destination for the message
- * @param destinationPort the port to deliver the message to at the
+ * @param scAddr Service Centre address. null == use default
+ * @param destAddr the address of the destination for the message
+ * @param destPort the port to deliver the message to at the
* destination
* @param data the data for the message
* @return a <code>SubmitPdu</code> containing the encoded SC
* address, if applicable, and the encoded message.
* Returns null on encode error.
*/
- public static SubmitPdu getSubmitPdu(String scAddress,
- String destAddr, short destinationPort, byte[] data,
- boolean statusReportRequested) {
+ public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, short destPort,
+ byte[] data, boolean statusReportRequested) {
/**
- * TODO(cleanup): if we had properly exposed SmsHeader
- * information, this mess of many getSubmitPdu public
- * interface methods that currently pollute the api could have
- * been much more cleanly collapsed into one.
+ * TODO(cleanup): this is not a general-purpose SMS creation
+ * method, but rather something specialized to messages
+ * containing OCTET encoded (meaning non-human-readable) user
+ * data. The name should reflect that, and not just overload.
*/
- /**
- * TODO(cleanup): header serialization should be put somewhere
- * canonical to allow proper debugging and reuse.
- */
- byte[] destPort = new byte[4];
- destPort[0] = (byte) ((destinationPort >> 8) & 0xFF); // MSB of destination port
- destPort[1] = (byte) (destinationPort & 0xFF); // LSB of destination port
- destPort[2] = 0x00; // MSB of originating port
- destPort[3] = 0x00; // LSB of originating port
+ SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+ portAddrs.destPort = destPort;
+ portAddrs.origPort = 0;
+ portAddrs.areEightBits = false;
+
SmsHeader smsHeader = new SmsHeader();
- smsHeader.add(
- new SmsHeader.Element(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT, destPort));
- smsHeader.nbrOfHeaders = smsHeader.getElements().size();
+ smsHeader.portAddrs = portAddrs;
UserData uData = new UserData();
uData.userDataHeader = smsHeader;
@@ -379,7 +353,7 @@
uData.msgEncodingSet = true;
uData.payload = data;
- return privateGetSubmitPdu(destAddr, statusReportRequested, uData, true);
+ return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
}
static class PduParser {
@@ -445,31 +419,23 @@
* {@inheritDoc}
*/
public boolean isMWIClearMessage() {
- if ((mBearerData != null) && (0 == mBearerData.numberOfMessages)) {
- return true;
- }
- return false;
+ return ((mBearerData != null) && (mBearerData.numberOfMessages == 0));
}
/**
* {@inheritDoc}
*/
public boolean isMWISetMessage() {
- if ((mBearerData != null) && (mBearerData.numberOfMessages >0)) {
- return true;
- }
- return false;
+ return ((mBearerData != null) && (mBearerData.numberOfMessages > 0));
}
/**
* {@inheritDoc}
*/
public boolean isMwiDontStore() {
- if ((mBearerData != null) && (mBearerData.numberOfMessages >0)
- && (null == mBearerData.userData)) {
- return true;
- }
- return false;
+ return ((mBearerData != null) &&
+ (mBearerData.numberOfMessages > 0) &&
+ (mBearerData.userData == null));
}
/**
@@ -478,7 +444,7 @@
* shifted to the bits 31-16.
*/
public int getStatus() {
- return(status<<16);
+ return (status << 16);
}
/**
@@ -518,7 +484,7 @@
*/
private void parsePdu(byte[] pdu) {
ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
- DataInputStream dis = new DataInputStream(new BufferedInputStream(bais));
+ DataInputStream dis = new DataInputStream(bais);
byte length;
int bearerDataLength;
SmsEnvelope env = new SmsEnvelope();
@@ -568,38 +534,23 @@
protected void parseSms() {
mBearerData = BearerData.decode(mEnvelope.bearerData);
messageRef = mBearerData.messageId;
+ if (mBearerData.userData != null) {
+ userData = mBearerData.userData.payload;
+ userDataHeader = mBearerData.userData.userDataHeader;
+ messageBody = mBearerData.userData.payloadStr;
+ }
- // TP-Message-Type-Indicator
- // (See 3GPP2 C.S0015-B, v2, 4.5.1)
- int messageType = mBearerData.messageType;
-
- switch (messageType) {
+ // TP-Message-Type-Indicator (See 3GPP2 C.S0015-B, v2, 4.5.1)
+ switch (mBearerData.messageType) {
case BearerData.MESSAGE_TYPE_USER_ACK:
case BearerData.MESSAGE_TYPE_READ_ACK:
case BearerData.MESSAGE_TYPE_DELIVER:
- // Deliver (mobile-terminated only)
- parseSmsDeliver();
- break;
case BearerData.MESSAGE_TYPE_DELIVERY_ACK:
- parseSmsDeliveryAck();
break;
-
default:
- // the rest of these
- throw new RuntimeException("Unsupported message type: " + messageType);
+ throw new RuntimeException("Unsupported message type: " + mBearerData.messageType);
}
- }
- /**
- * TODO(cleanup): why are there two nearly identical functions
- * below? More rubbish...
- */
-
- /**
- * Parses a SMS-DELIVER message. (mobile-terminated only)
- * See 3GPP2 C.S0015-B, v2, 4.4.1
- */
- private void parseSmsDeliver() {
if (originatingAddress != null) {
originatingAddress.address = new String(originatingAddress.origBytes);
if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
@@ -612,46 +563,13 @@
if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
- parseUserData(mBearerData.userData);
- }
-
- /**
- * Parses a SMS-DELIVER message. (mobile-terminated only)
- * See 3GPP2 C.S0015-B, v2, 4.4.1
- */
- private void parseSmsDeliveryAck() {
- if (originatingAddress != null) {
- originatingAddress.address = new String(originatingAddress.origBytes);
- if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
- + originatingAddress.address);
- }
-
- if (mBearerData.timeStamp != null) {
- scTimeMillis = PduParser.getSCTimestampMillis(mBearerData.timeStamp);
- }
-
- if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
-
- if (mBearerData.errorClass != BearerData.ERROR_UNDEFINED) {
+ // TODO(Teleca): do we really want this test to occur only for DELIVERY_ACKs?
+ if ((mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) &&
+ (mBearerData.errorClass != BearerData.ERROR_UNDEFINED)) {
status = mBearerData.errorClass << 8;
status |= mBearerData.messageStatus;
}
- parseUserData(mBearerData.userData);
- }
-
- /**
- * Copy parsed user data out from internal datastructures.
- */
- private void parseUserData(UserData uData) {
- if (uData == null) {
- return;
- }
-
- userData = uData.payload;
- userDataHeader = uData.userDataHeader;
- messageBody = uData.payloadStr;
-
if (messageBody != null) {
if (Config.LOGV) Log.v(LOG_TAG, "SMS message body: '" + messageBody + "'");
parseMessageBody();
@@ -708,7 +626,7 @@
* @return byte stream for SubmitPdu.
*/
private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested,
- UserData userData, boolean useNewId) {
+ UserData userData) {
/**
* TODO(cleanup): give this function a more meaningful name.
@@ -720,7 +638,7 @@
BearerData bearerData = new BearerData();
bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
- if (useNewId) setNextMessageId();
+ if (userData != null) setNextMessageId();
bearerData.messageId = nextMessageId;
bearerData.deliveryAckReq = statusReportRequested;
@@ -812,6 +730,15 @@
dos.write(env.bearerData, 0, env.bearerData.length);
dos.close();
+ /**
+ * TODO(cleanup) -- This is the only place where mPdu is
+ * defined, and this is not obviously the only place where
+ * it needs to be defined. It would be much nicer if
+ * accessing the serialized representation used a less
+ * fragile mechanism. Maybe the getPdu method could
+ * generate a representation if there was not yet one?
+ */
+
mPdu = baos.toByteArray();
} catch (IOException ex) {
Log.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index e64d022..05c8c9d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -189,8 +189,12 @@
public int messageStatus = STATUS_UNDEFINED;
/**
- * 1-bit value that indicates whether a User Data Header is present.
+ * 1-bit value that indicates whether a User Data Header (UDH) is present.
* (See 3GPP2 C.S0015-B, v2, 4.5.1)
+ *
+ * NOTE: during encoding, this value will be set based on the
+ * presence of a UDH in the structured data, any existing setting
+ * will be overwritten.
*/
public boolean hasUserDataHeader;
@@ -248,25 +252,27 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append("BearerData:\n");
- builder.append(" messageType: " + messageType + "\n");
- builder.append(" messageId: " + (int)messageId + "\n");
- builder.append(" priority: " + (priorityIndicatorSet ? priority : "not set") + "\n");
- builder.append(" privacy: " + (privacyIndicatorSet ? privacy : "not set") + "\n");
- builder.append(" alert: " + (alertIndicatorSet ? alert : "not set") + "\n");
- builder.append(" displayMode: " + (displayModeSet ? displayMode : "not set") + "\n");
- builder.append(" language: " + (languageIndicatorSet ? language : "not set") + "\n");
- builder.append(" errorClass: " + (messageStatusSet ? errorClass : "not set") + "\n");
- builder.append(" msgStatus: " + (messageStatusSet ? messageStatus : "not set") + "\n");
- builder.append(" hasUserDataHeader: " + hasUserDataHeader + "\n");
- builder.append(" timeStamp: " + timeStamp + "\n");
- builder.append(" userAckReq: " + userAckReq + "\n");
- builder.append(" deliveryAckReq: " + deliveryAckReq + "\n");
- builder.append(" readAckReq: " + readAckReq + "\n");
- builder.append(" reportReq: " + reportReq + "\n");
- builder.append(" numberOfMessages: " + numberOfMessages + "\n");
- builder.append(" callbackNumber: " + callbackNumber + "\n");
- builder.append(" userData: " + userData + "\n");
+ builder.append("BearerData ");
+ builder.append("{ messageType=" + messageType);
+ builder.append(", messageId=" + (int)messageId);
+ builder.append(", priority=" + (priorityIndicatorSet ? priority : "unset"));
+ builder.append(", privacy=" + (privacyIndicatorSet ? privacy : "unset"));
+ builder.append(", alert=" + (alertIndicatorSet ? alert : "unset"));
+ builder.append(", displayMode=" + (displayModeSet ? displayMode : "unset"));
+ builder.append(", language=" + (languageIndicatorSet ? language : "unset"));
+ builder.append(", errorClass=" + (messageStatusSet ? errorClass : "unset"));
+ builder.append(", msgStatus=" + (messageStatusSet ? messageStatus : "unset"));
+ builder.append(", timeStamp=" +
+ ((timeStamp != null) ? HexDump.toHexString(timeStamp) : "unset"));
+ builder.append(", userAckReq=" + userAckReq);
+ builder.append(", deliveryAckReq=" + deliveryAckReq);
+ builder.append(", readAckReq=" + readAckReq);
+ builder.append(", reportReq=" + reportReq);
+ builder.append(", numberOfMessages=" + numberOfMessages);
+ builder.append(", callbackNumber=" + callbackNumber);
+ builder.append(", hasUserDataHeader=" + hasUserDataHeader);
+ builder.append(", userData=" + userData);
+ builder.append(" }");
return builder.toString();
}
@@ -335,12 +341,19 @@
private static void encodeUserDataPayload(UserData uData)
throws CodingException
{
+ byte[] headerData = null;
+ if (uData.userDataHeader != null) headerData = SmsHeader.toByteArray(uData.userDataHeader);
+ int headerDataLen = (headerData == null) ? 0 : headerData.length + 1; // + length octet
+
+ byte[] payloadData;
if (uData.msgEncodingSet) {
if (uData.msgEncoding == UserData.ENCODING_OCTET) {
if (uData.payload == null) {
Log.e(LOG_TAG, "user data with octet encoding but null payload");
// TODO(code_review): reasonable for fail case? or maybe bail on encoding?
- uData.payload = new byte[0];
+ payloadData = new byte[0];
+ } else {
+ payloadData = uData.payload;
}
} else {
if (uData.payloadStr == null) {
@@ -349,11 +362,11 @@
uData.payloadStr = "";
}
if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) {
- uData.payload = encode7bitGsm(uData.payloadStr);
+ payloadData = encode7bitGsm(uData.payloadStr);
} else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) {
- uData.payload = encode7bitAscii(uData.payloadStr);
+ payloadData = encode7bitAscii(uData.payloadStr);
} else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
- uData.payload = encodeUtf16(uData.payloadStr);
+ payloadData = encodeUtf16(uData.payloadStr);
} else {
throw new CodingException("unsupported user data encoding (" +
uData.msgEncoding + ")");
@@ -367,19 +380,28 @@
uData.payloadStr = "";
}
try {
- uData.payload = encode7bitAscii(uData.payloadStr);
+ payloadData = encode7bitAscii(uData.payloadStr);
uData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
} catch (CodingException ex) {
- uData.payload = encodeUtf16(uData.payloadStr);
+ payloadData = encodeUtf16(uData.payloadStr);
uData.msgEncoding = UserData.ENCODING_UNICODE_16;
}
uData.msgEncodingSet = true;
uData.numFields = uData.payloadStr.length();
}
- if (uData.payload.length > SmsMessage.MAX_USER_DATA_BYTES) {
- throw new CodingException("encoded user data too large (" + uData.payload.length +
+
+ int totalLength = payloadData.length + headerDataLen;
+ if (totalLength > SmsMessage.MAX_USER_DATA_BYTES) {
+ throw new CodingException("encoded user data too large (" + totalLength +
" > " + SmsMessage.MAX_USER_DATA_BYTES + " bytes)");
}
+
+ uData.payload = new byte[totalLength];
+ if (headerData != null) {
+ uData.payload[0] = (byte)headerData.length;
+ System.arraycopy(headerData, 0, uData.payload, 1, headerData.length);
+ }
+ System.arraycopy(payloadData, 0, uData.payload, headerDataLen, payloadData.length);
}
private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream)
@@ -394,11 +416,6 @@
*
*/
int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
- byte[] headerData = null;
- if (bData.hasUserDataHeader) {
- headerData = bData.userData.userDataHeader.toByteArray();
- dataBits += headerData.length * 8;
- }
int paramBits = dataBits + 13;
if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
(bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
@@ -413,7 +430,6 @@
outStream.write(8, bData.userData.msgType);
}
outStream.write(8, bData.userData.numFields);
- if (headerData != null) outStream.writeByteArray(headerData.length * 8, headerData);
outStream.writeByteArray(dataBits, bData.userData.payload);
if (paddingBits > 0) outStream.write(paddingBits, 0);
}
@@ -557,6 +573,8 @@
* @return data byta array of raw encoded SMS bearer data.
*/
public static byte[] encode(BearerData bData) {
+ bData.hasUserDataHeader = ((bData.userData != null) &&
+ (bData.userData.userDataHeader != null));
try {
BitwiseOutputStream outStream = new BitwiseOutputStream(200);
outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
@@ -723,11 +741,11 @@
{
int offset = 0;
if (hasUserDataHeader) {
- int udhLen = userData.payload[0];
- offset += udhLen;
+ int udhLen = userData.payload[0] & 0x00FF;
+ offset += udhLen + 1;
byte[] headerData = new byte[udhLen];
System.arraycopy(userData.payload, 1, headerData, 0, udhLen);
- userData.userDataHeader = SmsHeader.parse(headerData);
+ userData.userDataHeader = SmsHeader.fromByteArray(headerData);
}
switch (userData.msgEncoding) {
case UserData.ENCODING_OCTET:
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index 02e94ad..7c37bc2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -93,14 +93,15 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append("UserData:\n");
- builder.append(" msgEncoding: " + (msgEncodingSet ? msgEncoding : "not set") + "\n");
- builder.append(" msgType: " + msgType + "\n");
- builder.append(" paddingBits: " + paddingBits + "\n");
- builder.append(" numFields: " + (int)numFields + "\n");
- builder.append(" userDataHeader: " + userDataHeader + "\n");
- builder.append(" payload: '" + HexDump.toHexString(payload) + "'");
- builder.append(", payloadStr: '" + payloadStr + "'");
+ builder.append("UserData ");
+ builder.append("{ msgEncoding=" + (msgEncodingSet ? msgEncoding : "unset"));
+ builder.append(", msgType=" + msgType);
+ builder.append(", paddingBits=" + paddingBits);
+ builder.append(", numFields=" + (int)numFields);
+ builder.append(", userDataHeader=" + userDataHeader);
+ builder.append(", payload='" + HexDump.toHexString(payload) + "'");
+ builder.append(", payloadStr='" + payloadStr + "'");
+ builder.append(" }");
return builder.toString();
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index a2d3c5e..3459dcd 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -34,6 +34,7 @@
import android.telephony.CellLocation;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.text.TextUtils;
import android.util.Log;
@@ -67,6 +68,7 @@
import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.PhoneSubInfo;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.gsm.stk.StkService;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.IccVmNotSupportedException;
@@ -203,9 +205,9 @@
}
}
- //Change the system setting
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE);
+ //Change the system property
+ SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
+ new Integer(RILConstants.GSM_PHONE).toString());
}
public void dispose() {
@@ -285,9 +287,8 @@
return mDataConnection.getActiveApnString();
}
- public int
- getSignalStrengthASU() {
- return mSST.rssi == 99 ? -1 : mSST.rssi;
+ public SignalStrength getSignalStrength() {
+ return mSST.mSignalStrength;
}
public boolean
@@ -825,6 +826,11 @@
}
public void
+ sendBurstDtmf(String dtmfString) {
+ Log.e(LOG_TAG, "[GSMPhone] sendBurstDtmf() is a CDMA method");
+ }
+
+ public void
setRadioPower(boolean power) {
mSST.setRadioPower(power);
}
@@ -832,21 +838,21 @@
private void storeVoiceMailNumber(String number) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
- editor.putString(VM_NUMBER, number);
+ editor.putString(VM_NUMBER, number);
editor.commit();
setVmSimImsi(getSubscriberId());
}
public String getVoiceMailNumber() {
// Read from the SIM. If its null, try reading from the shared preference area.
- String number = mSIMRecords.getVoiceMailNumber();
+ String number = mSIMRecords.getVoiceMailNumber();
if (TextUtils.isEmpty(number)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
number = sp.getString(VM_NUMBER, null);
- }
+ }
return number;
}
-
+
private String getVmSimImsi() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
return sp.getString(VM_SIM_IMSI, null);
@@ -858,7 +864,7 @@
editor.putString(VM_SIM_IMSI, imsi);
editor.commit();
}
-
+
public String getVoiceMailAlphaTag() {
String ret;
@@ -872,6 +878,11 @@
return ret;
}
+ public String getMin() {
+ Log.e(LOG_TAG, "[GSMPhone] getMin() is a CDMA method");
+ return "0";
+ }
+
public String getDeviceId() {
return mImei;
}
@@ -922,13 +933,13 @@
public void setVoiceMailNumber(String alphaTag,
String voiceMailNumber,
Message onComplete) {
-
- Message resp;
+
+ Message resp;
mVmNumber = voiceMailNumber;
resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
mSIMRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
-
+
private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
switch (commandInterfaceCFReason) {
case CF_REASON_UNCONDITIONAL:
@@ -1307,11 +1318,11 @@
case EVENT_SIM_RECORDS_LOADED:
updateCurrentCarrierInProvider();
-
+
// Check if this is a different SIM than the previous one. If so unset the
// voice mail number.
String imsi = getVmSimImsi();
- if (imsi != null && !getSubscriberId().equals(imsi)) {
+ if (imsi != null && !getSubscriberId().equals(imsi)) {
storeVoiceMailNumber(null);
setVmSimImsi(null);
}
@@ -1393,7 +1404,7 @@
onComplete.sendToTarget();
}
break;
-
+
case EVENT_SET_VM_NUMBER_DONE:
ar = (AsyncResult)msg.obj;
if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
@@ -1407,7 +1418,7 @@
}
break;
-
+
case EVENT_GET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
@@ -1450,7 +1461,7 @@
/**
* Sets the "current" field in the telephony provider according to the SIM's operator
- *
+ *
* @return true for success; false otherwise.
*/
boolean updateCurrentCarrierInProvider() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 9e6ebc4..1d7aaf1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -50,6 +50,7 @@
import android.util.EventLog;
import android.util.Log;
+import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnectionTracker;
@@ -779,7 +780,7 @@
}
private boolean
- pdpStatesHasCID (ArrayList<PDPContextState> states, int cid) {
+ pdpStatesHasCID (ArrayList<DataCallState> states, int cid) {
for (int i = 0, s = states.size() ; i < s ; i++) {
if (states.get(i).cid == cid) return true;
}
@@ -788,9 +789,11 @@
}
private boolean
- pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid) {
+ pdpStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
for (int i = 0, s = states.size() ; i < s ; i++) {
- if (states.get(i).cid == cid) return (states.get(i).active != 0);
+ if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
+ return true;
+ }
}
return false;
@@ -825,9 +828,9 @@
* previous state
*/
protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
- ArrayList<PDPContextState> pdpStates;
+ ArrayList<DataCallState> pdpStates;
- pdpStates = (ArrayList<PDPContextState>)(ar.result);
+ pdpStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 3e73caf..699142a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -39,8 +39,11 @@
final class GsmSMSDispatcher extends SMSDispatcher {
private static final String TAG = "GSM";
+ private GSMPhone mGsmPhone;
+
GsmSMSDispatcher(GSMPhone phone) {
super(phone);
+ mGsmPhone = phone;
}
/**
@@ -97,110 +100,41 @@
// Special case the message waiting indicator messages
if (sms.isMWISetMessage()) {
- ((GSMPhone) mPhone).updateMessageWaitingIndicator(true);
-
- if (sms.isMwiDontStore()) {
- handled = true;
- }
-
+ mGsmPhone.updateMessageWaitingIndicator(true);
+ handled |= sms.isMwiDontStore();
if (Config.LOGD) {
- Log.d(TAG,
- "Received voice mail indicator set SMS shouldStore="
- + !handled);
+ Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
}
} else if (sms.isMWIClearMessage()) {
- ((GSMPhone) mPhone).updateMessageWaitingIndicator(false);
-
- if (sms.isMwiDontStore()) {
- handled = true;
- }
-
+ mGsmPhone.updateMessageWaitingIndicator(false);
+ handled |= sms.isMwiDontStore();
if (Config.LOGD) {
- Log.d(TAG,
- "Received voice mail indicator clear SMS shouldStore="
- + !handled);
+ Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
}
}
- if (handled) {
- return;
- }
+ if (handled) return;
- // Parse the headers to see if this is partial, or port addressed
- int referenceNumber = -1;
- int count = 0;
- int sequence = 0;
- int destPort = -1;
-
- SmsHeader header = sms.getUserDataHeader();
- if (header != null) {
- for (SmsHeader.Element element : header.getElements()) {
- try {
- switch (element.getID()) {
- case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
- byte[] data = element.getData();
-
- referenceNumber = data[0] & 0xff;
- count = data[1] & 0xff;
- sequence = data[2] & 0xff;
-
- // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
- // is zero, or sequence > count, ignore the entire element
- if (count == 0 || sequence == 0 || sequence > count) {
- referenceNumber = -1;
- }
- break;
- }
-
- case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
- byte[] data = element.getData();
-
- referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
- count = data[2] & 0xff;
- sequence = data[3] & 0xff;
-
- // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
- // is zero, or sequence > count, ignore the entire element
- if (count == 0 || sequence == 0 || sequence > count) {
- referenceNumber = -1;
- }
- break;
- }
-
- case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
- byte[] data = element.getData();
-
- destPort = (data[0] & 0xff) << 8;
- destPort |= (data[1] & 0xff);
-
- break;
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- Log.e(TAG, "Bad element in header", e);
- return; // TODO: NACK the message or something, don't just discard.
- }
- }
- }
-
- if (referenceNumber == -1) {
- // notify everyone of the message if it isn't partial
+ SmsHeader smsHeader = sms.getUserDataHeader();
+ // See if message is partial or port addressed.
+ if ((smsHeader == null) || (smsHeader.concatRef == null)) {
+ // Message is not partial (not part of concatenated sequence).
byte[][] pdus = new byte[1][];
pdus[0] = sms.getPdu();
- if (destPort != -1) {
- if (destPort == SmsHeader.PORT_WAP_PUSH) {
+ if (smsHeader != null && smsHeader.portAddrs != null) {
+ if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
mWapPush.dispatchWapPdu(sms.getUserData());
}
- // The message was sent to a port, so concoct a URI for it
- dispatchPortAddressedPdus(pdus, destPort);
+ // The message was sent to a port, so concoct a URI for it.
+ dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
} else {
- // It's a normal message, dispatch it
+ // Normal short and non-port-addressed message, dispatch it.
dispatchPdus(pdus);
}
} else {
- // Process the message part
- processMessagePart(sms, referenceNumber, sequence, count, destPort);
+ // Process the message part.
+ processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
}
}
@@ -208,28 +142,30 @@
protected void sendMultipartText(String destinationAddress, String scAddress,
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents) {
- int ref = ++sConcatenatedRef & 0xff;
- for (int i = 0, count = parts.size(); i < count; i++) {
- // build SmsHeader
- byte[] data = new byte[3];
- data[0] = (byte) ref; // reference #, unique per message
- data[1] = (byte) count; // total part count
- data[2] = (byte) (i + 1); // 1-based sequence
- SmsHeader header = new SmsHeader();
- header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+ int refNumber = getNextConcatenatedRef() & 0x00FF;
+
+ for (int i = 0, msgCount = parts.size(); i < msgCount; i++) {
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = refNumber;
+ concatRef.seqNumber = i + 1; // 1-based sequence
+ concatRef.msgCount = msgCount;
+ concatRef.isEightBits = false;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+
PendingIntent sentIntent = null;
- PendingIntent deliveryIntent = null;
-
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
+
+ PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > i) {
deliveryIntent = deliveryIntents.get(i);
}
SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
- parts.get(i), deliveryIntent != null, header.toByteArray());
+ parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader));
sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
}
@@ -259,18 +195,16 @@
* to the recipient. The raw pdu of the status report is in the
* extended data ("pdu").
*/
- private void sendMultipartTextWithPermit(String destinationAddress,
+ private void sendMultipartTextWithPermit(String destinationAddress,
String scAddress, ArrayList<String> parts,
- ArrayList<PendingIntent> sentIntents,
+ ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents) {
-
- PendingIntent sentIntent = null;
- PendingIntent deliveryIntent = null;
-
+
// check if in service
int ss = mPhone.getServiceState().getState();
if (ss != ServiceState.STATE_IN_SERVICE) {
for (int i = 0, count = parts.size(); i < count; i++) {
+ PendingIntent sentIntent = null;
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
@@ -280,26 +214,29 @@
return;
}
- int ref = ++sConcatenatedRef & 0xff;
+ int refNumber = getNextConcatenatedRef() & 0x00FF;
- for (int i = 0, count = parts.size(); i < count; i++) {
- // build SmsHeader
- byte[] data = new byte[3];
- data[0] = (byte) ref; // reference #, unique per message
- data[1] = (byte) count; // total part count
- data[2] = (byte) (i + 1); // 1-based sequence
- SmsHeader header = new SmsHeader();
- header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
-
+ for (int i = 0, msgCount = parts.size(); i < msgCount; i++) {
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = refNumber;
+ concatRef.seqNumber = i + 1; // 1-based sequence
+ concatRef.msgCount = msgCount;
+ concatRef.isEightBits = false;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+
+ PendingIntent sentIntent = null;
if (sentIntents != null && sentIntents.size() > i) {
sentIntent = sentIntents.get(i);
}
+
+ PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > i) {
deliveryIntent = deliveryIntents.get(i);
}
SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
- parts.get(i), deliveryIntent != null, header.toByteArray());
+ parts.get(i), deliveryIntent != null, SmsHeader.toByteArray(smsHeader));
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("smsc", pdus.encodedScAddress);
@@ -307,7 +244,7 @@
SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent);
sendSms(tracker);
- }
+ }
}
/** {@inheritDoc} */
@@ -376,4 +313,3 @@
}
}
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 9ab1002..7a4ea64 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -38,6 +38,7 @@
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony.Intents;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.Config;
@@ -73,6 +74,14 @@
* {@hide}
*/
final class GsmServiceStateTracker extends ServiceStateTracker {
+
+ /**
+ * TODO(Teleca): John Huang asks: Will you be adding handling of
+ * "reason for registration denied in EVENT_POLL_STATE_REGISTRATION?
+ * I see some handling of this in CdmaServiceStateTracker, but as I
+ * understand it this field was added at the request of a GSM carrier.
+ */
+
//***** Instance Variables
GSMPhone phone;
GsmCellLocation cellLoc;
@@ -80,9 +89,6 @@
int mPreferredNetworkType;
RestrictedState rs;
- int rssi = 99; // signal strength 0-31, 99=unknown
- // That's "received signal strength indication" fyi
-
private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
@@ -121,7 +127,7 @@
private boolean mStartedGprsRegCheck = false;
// Already sent the event-log for no gprs register
private boolean mReportedGprsNoReg = false;
-
+
/**
* The Notification object given to the NotificationManager.
*/
@@ -151,9 +157,9 @@
static final int CS_DISABLED = 1004; // Access Control enables all voice/sms service
static final int CS_NORMAL_ENABLED = 1005; // Access Control blocks normal voice/sms service
static final int CS_EMERGENCY_ENABLED = 1006; // Access Control blocks emergency call service
-
+
// notification id
- static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted
+ static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted
static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@@ -177,6 +183,7 @@
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
rs = new RestrictedState();
+ mSignalStrength = new SignalStrength();
PowerManager powerManager =
(PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
@@ -201,7 +208,7 @@
cr.registerContentObserver(
Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
mAutoTimeObserver);
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mNeedToRegForSimLoaded = true;
}
@@ -280,7 +287,7 @@
* @param obj placed in Message.obj
*/
/*protected*/ void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
+ Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
Registrant r = new Registrant(h, what, obj);
psRestrictEnabledRegistrants.add(r);
@@ -300,7 +307,7 @@
* @param obj placed in Message.obj
*/
/*protected*/ void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
+ Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
Registrant r = new Registrant(h, what, obj);
psRestrictDisabledRegistrants.add(r);
@@ -308,7 +315,7 @@
r.notifyRegistrant();
}
}
-
+
/*protected*/ void unregisterForPsRestrictedDisabled(Handler h) {
psRestrictDisabledRegistrants.remove(h);
}
@@ -506,13 +513,13 @@
}
mStartedGprsRegCheck = false;
break;
-
+
case EVENT_RESTRICTED_STATE_CHANGED:
// This is a notification from
// CommandsInterface.setOnRestrictedStateChanged
Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_RESTRICTED_STATE_CHANGED");
-
+
ar = (AsyncResult) msg.obj;
onRestrictedStateChanged(ar);
@@ -542,11 +549,11 @@
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
}
dcTracker.cleanConnectionBeforeRadioOff();
-
+
// poll data state up to 15 times, with a 100ms delay
// totaling 1.5 sec. Normal data disable action will finish in 100ms.
for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
- if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
+ if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
&& dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
Log.d(LOG_TAG, "Data shutdown complete.");
break;
@@ -557,7 +564,7 @@
cm.setRadioPower(false, null);
} // Otherwise, we're in the desired state
}
-
+
protected void updateSpnDisplay() {
int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
String spn = phone.mSIMRecords.getServiceProviderName();
@@ -699,9 +706,8 @@
}
- private void
- setRssiDefaultValues() {
- rssi = 99;
+ private void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, true);
}
/**
@@ -722,7 +728,7 @@
case RADIO_UNAVAILABLE:
newSS.setStateOutOfService();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
pollStateDone();
@@ -731,7 +737,7 @@
case RADIO_OFF:
newSS.setStateOff();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
pollStateDone();
@@ -745,10 +751,10 @@
Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
- setRssiDefaultValues();
+ setSignalStrengthDefaultValues();
mGotCountryCode = false;
- pollStateDone();
+ //NOTE: pollStateDone() is not needed in this case
break;
default:
@@ -1044,17 +1050,18 @@
}
/**
- * send signal-strength-changed notification if rssi changed
+ * send signal-strength-changed notification if changed
* Called both for solicited and unsolicited signal stength updates
*/
private void
onSignalStrengthResult(AsyncResult ar) {
- int oldRSSI = rssi;
+ SignalStrength oldSignalStrength = mSignalStrength;
+ int rssi = 99;
if (ar.exception != null) {
- // 99 = unknown
+ // -1 = unknown
// most likely radio is resetting/disconnected
- rssi = 99;
+ setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;
@@ -1067,13 +1074,16 @@
}
}
- if (rssi != oldRSSI) {
+ mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
+ -1, -1, -1, true);
+
+ if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
- Log.d(LOG_TAG, "onSignalStrengthResult() Phone already destroyed: " + ex
- + "Signal Stranth not notified");
+ log("onSignalStrengthResult() Phone already destroyed: " + ex
+ + "SignalStrength not notified");
}
}
}
@@ -1089,27 +1099,27 @@
{
Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
RestrictedState newRs = new RestrictedState();
-
+
Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
-
+
if (ar.exception == null) {
int[] ints = (int[])ar.result;
int state = ints[0];
-
+
newRs.setCsEmergencyRestricted(
((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
//ignore the normal call and data restricted state before SIM READY
- if (phone.getIccCard().getState() == IccCard.State.READY) {
+ if (phone.getIccCard().getState() == IccCard.State.READY) {
newRs.setCsNormalRestricted(
((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
newRs.setPsRestricted(
(state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
}
-
- Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
-
+
+ Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
+
if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
psRestrictEnabledRegistrants.notifyRegistrants();
setNotification(PS_ENABLED);
@@ -1117,9 +1127,9 @@
psRestrictDisabledRegistrants.notifyRegistrants();
setNotification(PS_DISABLED);
}
-
+
/**
- * There are two kind of cs restriction, normal and emergency. So
+ * There are two kind of cs restriction, normal and emergency. So
* there are 4 x 4 combinations in current and new restricted states
* and we only need to notify when state is changed.
*/
@@ -1129,32 +1139,32 @@
setNotification(CS_DISABLED);
} else if (!newRs.isCsNormalRestricted()) {
// remove normal restriction
- setNotification(CS_EMERGENCY_ENABLED);
+ setNotification(CS_EMERGENCY_ENABLED);
} else if (!newRs.isCsEmergencyRestricted()) {
// remove emergency restriction
- setNotification(CS_NORMAL_ENABLED);
+ setNotification(CS_NORMAL_ENABLED);
}
} else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
- setNotification(CS_DISABLED);
+ setNotification(CS_DISABLED);
} else if (newRs.isCsRestricted()) {
// enable all restriction
setNotification(CS_ENABLED);
} else if (newRs.isCsNormalRestricted()) {
// remove emergency restriction and enable normal restriction
- setNotification(CS_NORMAL_ENABLED);
+ setNotification(CS_NORMAL_ENABLED);
}
} else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
- setNotification(CS_DISABLED);
+ setNotification(CS_DISABLED);
} else if (newRs.isCsRestricted()) {
// enable all restriction
setNotification(CS_ENABLED);
} else if (newRs.isCsEmergencyRestricted()) {
// remove normal restriction and enable emergency restriction
- setNotification(CS_EMERGENCY_ENABLED);
+ setNotification(CS_EMERGENCY_ENABLED);
}
} else {
if (newRs.isCsRestricted()) {
@@ -1162,10 +1172,10 @@
setNotification(CS_ENABLED);
} else if (newRs.isCsEmergencyRestricted()) {
// enable emergency restriction
- setNotification(CS_EMERGENCY_ENABLED);
+ setNotification(CS_EMERGENCY_ENABLED);
} else if (newRs.isCsNormalRestricted()) {
// enable normal restriction
- setNotification(CS_NORMAL_ENABLED);
+ setNotification(CS_NORMAL_ENABLED);
}
}
@@ -1527,7 +1537,7 @@
/**
* Post a notification to NotificationManager for restricted state
- *
+ *
* @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
*/
private void setNotification(int notifyType) {
@@ -1546,7 +1556,7 @@
CharSequence details = "";
CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle);
int notificationId = CS_NOTIFICATION;
-
+
switch (notifyType) {
case PS_ENABLED:
notificationId = PS_NOTIFICATION;
@@ -1557,24 +1567,24 @@
break;
case CS_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
- break;
+ break;
case CS_NORMAL_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
- break;
+ break;
case CS_EMERGENCY_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);;
- break;
+ break;
case CS_DISABLED:
// do nothing and cancel the notification later
- break;
+ break;
}
-
+
Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
mNotification.tickerText = title;
- mNotification.setLatestEventInfo(context, title, details,
+ mNotification.setLatestEventInfo(context, title, details,
mNotification.contentIntent);
-
- NotificationManager notificationManager = (NotificationManager)
+
+ NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
@@ -1585,4 +1595,8 @@
notificationManager.notify(notificationId, mNotification);
}
}
+
+ private void log(String s) {
+ Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/MccTable.java b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
index 6198979..e18da56 100644
--- a/telephony/java/com/android/internal/telephony/gsm/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
@@ -182,7 +182,7 @@
table.add(new MccEntry(222,"it",2,"Europe/Rome","it")); //Italy
table.add(new MccEntry(225,"va",2,"Europe/Rome","it")); //Vatican City State
table.add(new MccEntry(226,"ro",2)); //Romania
- table.add(new MccEntry(228,"ch",2,"Europe/Zurich","en")); //Switzerland (Confederation of)
+ table.add(new MccEntry(228,"ch",2,"Europe/Zurich","de")); //Switzerland (Confederation of)
table.add(new MccEntry(230,"cz",2,"Europe/Prague","cs")); //Czech Republic
table.add(new MccEntry(231,"sk",2)); //Slovak Republic
table.add(new MccEntry(232,"at",2,"Europe/Vienna","de")); //Austria
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 88acb1b..3f794a8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -95,16 +95,20 @@
apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
}
+ private void tearDownData(Message msg) {
+ if (dataLink != null) {
+ dataLink.disconnect();
+ }
+
+ if (phone.mCM.getRadioState().isOn()) {
+ phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
+ }
+ }
+
protected void disconnect(Message msg) {
onDisconnect = msg;
if (state == State.ACTIVE) {
- if (dataLink != null) {
- dataLink.disconnect();
- }
-
- if (phone.mCM.getRadioState().isOn()) {
- phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
- }
+ tearDownData(msg);
} else if (state == State.ACTIVATING) {
receivedDisconnectReq = true;
} else {
@@ -243,7 +247,7 @@
// Don't bother reporting success if there's already a
// pending disconnect request, since DataConnectionTracker
// has already updated its state.
- disconnect(onDisconnect);
+ tearDownData(onDisconnect);
} else {
String[] response = ((String[]) ar.result);
cid = Integer.parseInt(response[0]);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 867b719..ed61c3f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -330,9 +330,20 @@
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, short destinationPort, byte[] data,
boolean statusReportRequested) {
- if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
+
+ SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+ portAddrs.destPort = destinationPort;
+ portAddrs.origPort = 0;
+ portAddrs.areEightBits = false;
+
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.portAddrs = portAddrs;
+
+ byte[] smsHeaderData = SmsHeader.toByteArray(smsHeader);
+
+ if ((data.length + smsHeaderData.length + 1) > MAX_USER_DATA_BYTES) {
Log.e(LOG_TAG, "SMS data message may only contain "
- + (MAX_USER_DATA_BYTES - 7) + " bytes");
+ + (MAX_USER_DATA_BYTES - smsHeaderData.length - 1) + " bytes");
return null;
}
@@ -348,21 +359,12 @@
// (no TP-Validity-Period)
- // User data size
- bo.write(data.length + 7);
+ // Total size
+ bo.write(data.length + smsHeaderData.length + 1);
- // User data header size
- bo.write(0x06); // header is 6 octets
-
- // User data header, indicating the destination port
- bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port
- // addressing
- // header
- bo.write(0x04); // each port is 2 octets
- bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port
- bo.write(destinationPort & 0xFF); // LSB of destination port
- bo.write(0x00); // MSB of originating port
- bo.write(0x00); // LSB of originating port
+ // User data header
+ bo.write(smsHeaderData.length);
+ bo.write(smsHeaderData, 0, smsHeaderData.length);
// User data
bo.write(data, 0, data.length);
@@ -562,7 +564,7 @@
byte[] udh = new byte[userDataHeaderLength];
System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength);
- userDataHeader = SmsHeader.parse(udh);
+ userDataHeader = SmsHeader.fromByteArray(udh);
offset += userDataHeaderLength;
int headerBits = (userDataHeaderLength + 1) * 8;
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 5c69017..42bb2e0 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -26,8 +26,8 @@
import com.android.internal.telephony.BaseCommands;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.gsm.CallFailCause;
-import com.android.internal.telephony.gsm.PDPContextState;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.Phone;
@@ -59,7 +59,7 @@
private final static String SIM_PUK2_CODE = "87654321";
//***** Instance Variables
-
+
SimulatedGsmCallState simulatedCallState;
HandlerThread mHandlerThread;
SimLockState mSimLockedState;
@@ -79,7 +79,7 @@
ArrayList<Message> pausedResponses = new ArrayList<Message>();
int nextCallFailCause = CallFailCause.NORMAL_CLEARING;
-
+
//***** Constructor
public
@@ -88,9 +88,9 @@
mHandlerThread = new HandlerThread("SimulatedCommands");
mHandlerThread.start();
Looper looper = mHandlerThread.getLooper();
-
+
simulatedCallState = new SimulatedGsmCallState(looper);
-
+
setRadioState(RadioState.RADIO_OFF);
mSimLockedState = INITIAL_LOCK_STATE;
mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
@@ -353,11 +353,11 @@
public void
setSuppServiceNotifications(boolean enable, Message result) {
resultSuccess(result, null);
-
+
if (enable && mSsnNotifyOn) {
Log.w(LOG_TAG, "Supp Service Notifications already enabled!");
}
-
+
mSsnNotifyOn = enable;
}
@@ -465,7 +465,7 @@
unimplemented(result);
}
- /**
+ /**
* returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
@@ -479,13 +479,13 @@
resultSuccess(result, simulatedCallState.getDriverCalls());
} else {
//Log.i("GSM", "[SimCmds] getCurrentCalls: SIM not ready!");
- resultFail(result,
+ resultFail(result,
new CommandException(
CommandException.Error.RADIO_NOT_AVAILABLE));
}
}
- /**
+ /**
* @deprecated
*/
public void getPDPContextList(Message result) {
@@ -497,13 +497,13 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
- * ar.result contains a List of PDPContextState
+ * ar.result contains a List of DataCallState
*/
public void getDataCallList(Message result) {
- resultSuccess(result, new ArrayList<PDPContextState>(0));
+ resultSuccess(result, new ArrayList<DataCallState>(0));
}
- /**
+ /**
* returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
@@ -520,7 +520,7 @@
resultSuccess(result, null);
}
- /**
+ /**
* returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
@@ -531,7 +531,7 @@
resultSuccess(result, "012345678901234");
}
- /**
+ /**
* returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
@@ -542,7 +542,7 @@
resultSuccess(result, "012345678901234");
}
- /**
+ /**
* returned message
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
@@ -553,7 +553,7 @@
resultSuccess(result, "99");
}
- /**
+ /**
* Hang up one individual connection.
* returned message
* retMsg.obj = AsyncResult ar
@@ -566,7 +566,7 @@
*/
public void hangupConnection (int gsmIndex, Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
if (!success){
@@ -588,7 +588,7 @@
*/
public void hangupWaitingOrBackground (Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('0', '\0');
if (!success){
@@ -600,7 +600,7 @@
/**
* 3GPP 22.030 6.5.5
- * "Releases all active calls (if any exist) and accepts
+ * "Releases all active calls (if any exist) and accepts
* the other (held or waiting) call."
*
* ar.exception carries exception on failure
@@ -609,7 +609,7 @@
*/
public void hangupForegroundResumeBackground (Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('1', '\0');
if (!success){
@@ -621,7 +621,7 @@
/**
* 3GPP 22.030 6.5.5
- * "Places all active calls (if any exist) on hold and accepts
+ * "Places all active calls (if any exist) on hold and accepts
* the other (held or waiting) call."
*
* ar.exception carries exception on failure
@@ -630,7 +630,7 @@
*/
public void switchWaitingOrHoldingAndActive (Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('2', '\0');
if (!success){
@@ -647,10 +647,10 @@
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
* ar.result is null on success and failure
- */
+ */
public void conference (Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('3', '\0');
if (!success){
@@ -682,7 +682,7 @@
/**
* 3GPP 22.030 6.5.5
- * "Places all active calls on hold except call X with which
+ * "Places all active calls on hold except call X with which
* communication shall be supported."
*/
public void separateConnection (int gsmIndex, Message result) {
@@ -703,10 +703,10 @@
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
* ar.result is null on success and failure
- */
+ */
public void acceptCall (Message result) {
boolean success;
-
+
success = simulatedCallState.onAnswer();
if (!success){
@@ -716,15 +716,15 @@
}
}
- /**
+ /**
* also known as UDUB
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
* ar.result is null on success and failure
- */
+ */
public void rejectCall (Message result) {
boolean success;
-
+
success = simulatedCallState.onChld('0', '\0');
if (!success){
@@ -734,7 +734,7 @@
}
}
- /**
+ /**
* cause code returned as Integer in Message.obj.response
* Returns integer cause code defined in TS 24.008
* Annex H or closest approximation.
@@ -765,11 +765,11 @@
public void getMute (Message result) {unimplemented(result);}
- /**
+ /**
* response.obj is an AsyncResult
* response.obj.result is an int[2]
- * response.obj.result[0] is received signal strength (0-31, 99)
- * response.obj.result[1] is bit error rate (0-7, 99)
+ * response.obj.result[0] is received signal strength (0-31, 99)
+ * response.obj.result[1] is bit error rate (0-7, 99)
* as defined in TS 27.007 8.5
*/
public void getSignalStrength (Message result) {
@@ -893,7 +893,7 @@
* response.obj.result[0] is long alpha or null if unregistered
* response.obj.result[1] is short alpha or null if unregistered
* response.obj.result[2] is numeric or null if unregistered
- */
+ */
public void getOperator(Message result) {
String[] ret = new String[3];
@@ -908,7 +908,7 @@
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
* ar.result is null on success and failure
- */
+ */
public void sendDtmf(char c, Message result) {
resultSuccess(result, null);
}
@@ -932,10 +932,19 @@
}
/**
+ * ar.exception carries exception on failure
+ * ar.userObject contains the orignal value of result.obj
+ * ar.result is null on success and failure
+ */
+ public void sendBurstDtmf(String dtmfString, Message result) {
+ resultSuccess(result, null);
+ }
+
+ /**
* smscPDU is smsc address in PDU form GSM BCD format prefixed
* by a length byte (as expected by TS 27.005) or NULL for default SMSC
* pdu is SMS in PDU format as an ASCII hex string
- * less the SMSC address
+ * less the SMSC address
*/
public void sendSMS (String smscPDU, String pdu, Message result) {unimplemented(result);}
@@ -1040,8 +1049,8 @@
unimplemented(result);
}
- /**
- * parameters equivilient to 27.007 AT+CRSM command
+ /**
+ * parameters equivilient to 27.007 AT+CRSM command
* response.obj will be an AsyncResult
* response.obj.userObj will be a SimIoResult on success
*/
@@ -1052,7 +1061,7 @@
/**
* (AsyncResult)response.obj).result is an int[] with element [0] set to
- * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
+ * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
*
* @param response is callback message
*/
@@ -1063,46 +1072,46 @@
* response.obj will be a an int[2]
*
* response.obj[0] will be TS 27.007 +CLIR parameter 'n'
- * 0 presentation indicator is used according to the subscription of the CLIR service
- * 1 CLIR invocation
- * 2 CLIR suppression
+ * 0 presentation indicator is used according to the subscription of the CLIR service
+ * 1 CLIR invocation
+ * 2 CLIR suppression
*
* response.obj[1] will be TS 27.007 +CLIR parameter 'm'
- * 0 CLIR not provisioned
- * 1 CLIR provisioned in permanent mode
- * 2 unknown (e.g. no network, etc.)
- * 3 CLIR temporary mode presentation restricted
- * 4 CLIR temporary mode presentation allowed
+ * 0 CLIR not provisioned
+ * 1 CLIR provisioned in permanent mode
+ * 2 unknown (e.g. no network, etc.)
+ * 3 CLIR temporary mode presentation restricted
+ * 4 CLIR temporary mode presentation allowed
*/
public void getCLIR(Message result) {unimplemented(result);}
-
+
/**
* clirMode is one of the CLIR_* constants above
*
* response.obj is null
*/
-
+
public void setCLIR(int clirMode, Message result) {unimplemented(result);}
/**
* (AsyncResult)response.obj).result is an int[] with element [0] set to
- * 0 for disabled, 1 for enabled.
+ * 0 for disabled, 1 for enabled.
*
* @param serviceClass is a sum of SERVICE_CLASS_*
* @param response is callback message
*/
-
+
public void queryCallWaiting(int serviceClass, Message response) {
unimplemented(response);
}
-
+
/**
* @param enable is true to enable, false to disable
* @param serviceClass is a sum of SERVICE_CLASS_*
* @param response is callback message
*/
-
+
public void setCallWaiting(boolean enable, int serviceClass,
Message response) {
unimplemented(response);
@@ -1111,9 +1120,9 @@
/**
* @param action is one of CF_ACTION_*
* @param cfReason is one of CF_REASON_*
- * @param serviceClass is a sum of SERVICE_CLASSS_*
+ * @param serviceClass is a sum of SERVICE_CLASSS_*
*/
- public void setCallForward(int action, int cfReason, int serviceClass,
+ public void setCallForward(int action, int cfReason, int serviceClass,
String number, int timeSeconds, Message result) {unimplemented(result);}
/**
@@ -1121,7 +1130,7 @@
*
* ((AsyncResult)response.obj).result will be an array of
* CallForwardInfo's
- *
+ *
* An array of length 0 means "disabled for all codes"
*/
public void queryCallForwardStatus(int cfReason, int serviceClass,
@@ -1155,7 +1164,7 @@
public void getAvailableNetworks(Message result) {unimplemented(result);}
public void getBasebandVersion (Message result) {
- resultSuccess(result, "SimulatedCommands");
+ resultSuccess(result, "SimulatedCommands");
}
/**
@@ -1167,7 +1176,7 @@
public void triggerIncomingUssd(String statusCode, String message) {
if (mUSSDRegistrant != null) {
String[] result = {statusCode, message};
- mUSSDRegistrant.notifyResult(result);
+ mUSSDRegistrant.notifyResult(result);
}
}
@@ -1215,7 +1224,7 @@
//***** SimulatedRadioControl
-
+
/** Start the simulated phone ringing */
public void
triggerRing(String number) {
@@ -1249,9 +1258,9 @@
simulatedCallState.setNextDialFailImmediately(b);
}
- public void
+ public void
setNextCallFailCause(int gsmCause) {
- nextCallFailCause = gsmCause;
+ nextCallFailCause = gsmCause;
}
public void
@@ -1319,7 +1328,7 @@
private void unimplemented(Message result) {
if (result != null) {
- AsyncResult.forMessage(result).exception
+ AsyncResult.forMessage(result).exception
= new RuntimeException("Unimplemented");
if (pausedResponseCount > 0) {
@@ -1359,13 +1368,13 @@
unimplemented(response);
}
- public void
+ public void
getCDMASubscription(Message response) {
Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
unimplemented(response);
}
- public void
+ public void
setCdmaSubscription(int cdmaSubscriptionType, Message response) {
Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
unimplemented(response);
@@ -1403,7 +1412,7 @@
* @param serviceClass is a sum of SERVICE_CLASS_*
* @param response is callback message
*/
- public void setTTYModeEnabled(boolean enable, Message response) {
+ public void setTTYMode(int ttyMode, Message response) {
Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
unimplemented(response);
}
@@ -1411,12 +1420,12 @@
/**
* Query the TTY mode for the CDMA phone
* (AsyncResult)response.obj).result is an int[] with element [0] set to
- * 0 for disabled, 1 for enabled.
- *
+ * 0 for disabled, 1 for enabled.
+ *
* @param serviceClass is a sum of SERVICE_CLASS_*
* @param response is callback message
*/
- public void queryTTYModeEnabled(Message response) {
+ public void queryTTYMode(Message response) {
Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
unimplemented(response);
}
@@ -1451,4 +1460,11 @@
}
+ public void exitEmergencyCallbackMode(Message response) {
+ // TODO method stub
+ }
+
+ public void forceDataDormancy(Message response) {
+ // TODO method stub
+ }
}
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index dded745..2ea020e 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -159,6 +159,9 @@
public void updateNetworkState(int state) {
}
+ public void updateLocation(Location location) {
+ }
+
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index b3e88e1..f8d5d4d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -136,6 +136,81 @@
}
@SmallTest
+ public void testUserDataHeaderConcatRefFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 55;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0xEE;
+ concatRef.msgCount = 2;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs, null);
+ }
+
+ @SmallTest
+ public void testUserDataHeaderMixedFeedback() throws Exception {
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+ bearerData.messageId = 42;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 0x34;
+ concatRef.msgCount = 5;
+ concatRef.seqNumber = 2;
+ concatRef.isEightBits = false;
+ SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+ portAddrs.destPort = 88;
+ portAddrs.origPort = 66;
+ portAddrs.areEightBits = false;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+ smsHeader.portAddrs = portAddrs;
+ byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+ SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ UserData userData = new UserData();
+ userData.payloadStr = "User Data Header (UDH) feedback test";
+ userData.userDataHeader = smsHeader;
+ bearerData.userData = userData;
+ byte[] encodedSms = BearerData.encode(bearerData);
+ BearerData revBearerData = BearerData.decode(encodedSms);
+ decodedHeader = revBearerData.userData.userDataHeader;
+ assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
+ assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
+ assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
+ assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
+ assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
+ assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
+ assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
+ }
+
+ @SmallTest
public void testReplyOption() throws Exception {
String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
index d775dc2..f623080 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
@@ -509,9 +509,14 @@
Cursor c;
mDatabase.execSQL("CREATE TABLE tokens (" +
"token TEXT COLLATE unicode," +
- "source INTEGER " +
+ "source INTEGER," +
+ "token_index INTEGER," +
+ "tag TEXT" +
");");
- String[] cols = new String[]{"token", "source"};
+ mDatabase.execSQL("CREATE TABLE tokens_no_index (" +
+ "token TEXT COLLATE unicode," +
+ "source INTEGER" +
+ ");");
Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
"SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null));
@@ -523,60 +528,152 @@
"SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null));
Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
- "SELECT _TOKENIZE('tokens', 1, 'some string ok', ' ')", null));
-
+ "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null));
+ Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null));
+
+ Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null));
+ Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT _TOKENIZE('tokens_no_index', 21, 'foo bar baz', ' ', 0)", null));
+
// test Chinese
String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca");
Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
- "SELECT _TOKENIZE('tokens', 1,'" + chinese + "', ' ')", null));
+ "SELECT _TOKENIZE('tokens', 12,'" + chinese + "', ' ', 1)", null));
String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g");
Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
- "SELECT _TOKENIZE('tokens', 1, '" + icustr + "', ' ')", null));
+ "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null));
- Assert.assertEquals(7, DatabaseUtils.longForQuery(mDatabase,
+ Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens;", null));
String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
key = DatabaseUtils.getHexCollationKey("Hjonneva");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
key = DatabaseUtils.getHexCollationKey("some string ok");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+ "SELECT tag from tokens where token GLOB '" + key + "*'", null));
key = DatabaseUtils.getHexCollationKey("string");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+ "SELECT tag from tokens where token GLOB '" + key + "*'", null));
key = DatabaseUtils.getHexCollationKey("ok");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
-
+ Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+ "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+
+ key = DatabaseUtils.getHexCollationKey("second field");
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
+ "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+ key = DatabaseUtils.getHexCollationKey("field");
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
+ "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+
key = DatabaseUtils.getHexCollationKey(chinese);
String[] a = new String[1];
a[0] = key;
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token= ?", a));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token= ?", a));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token= ?", a));
a[0] += "*";
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB ?", a));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB ?", a));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB ?", a));
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token= '" + key + "'", null));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token= '" + key + "'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token= '" + key + "'", null));
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5");
Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+ key = DatabaseUtils.getHexCollationKey("\u5c3d\u5f84\u60ca");
+ Log.d("DatabaseGeneralTest", "key = " + key);
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
"SELECT count(*) from tokens where token GLOB 'ab*'", null));
+
+ key = DatabaseUtils.getHexCollationKey("some string ok");
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(20, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null));
+
+ key = DatabaseUtils.getHexCollationKey("bar");
+ Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null));
+ Assert.assertEquals(21, DatabaseUtils.longForQuery(mDatabase,
+ "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null));
}
@MediumTest
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
index 360352b..9d44fd9 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
@@ -69,10 +69,15 @@
SmsHeader header = sms.getUserDataHeader();
assertNotNull(header);
-
- Iterator<SmsHeader.Element> elements = header.getElements().iterator();
- assertNotNull(elements);
-
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
pdu = "07914140279510F6440A8111110301003BF56080207130238A3B0B05040B8423F"
+ "000032A0202362E3130322E3137312E3135302F524E453955304A6D7135514141"
@@ -81,9 +86,15 @@
header = sms.getUserDataHeader();
assertNotNull(header);
-
- elements = header.getElements().iterator();
- assertNotNull(elements);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 42);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
/*
* UCS-2 encoded SMS
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java
new file mode 100644
index 0000000..46a12fd
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.unit_tests.content;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.net.Uri;
+import android.content.ContentValues;
+import android.content.ContentProviderOperation;
+import android.content.OperationApplicationException;
+import android.content.ContentProviderResult;
+import android.content.ContentProvider;
+import android.text.TextUtils;
+import android.database.Cursor;
+import junit.framework.TestCase;
+
+import java.util.Map;
+import java.util.Hashtable;
+
+@SmallTest
+public class ContentProviderOperationTest extends TestCase {
+ private final static Uri sTestUri1 = Uri.parse("content://authority/blah");
+ private final static ContentValues sTestValues1;
+
+ static {
+ sTestValues1 = new ContentValues();
+ sTestValues1.put("a", 1);
+ sTestValues1.put("b", "two");
+ }
+
+ public void testInsert() throws OperationApplicationException {
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .withValues(sTestValues1)
+ .build();
+ ContentProviderResult result = op1.apply(new TestContentProvider() {
+ public Uri insert(Uri uri, ContentValues values) {
+ assertEquals(sTestUri1.toString(), uri.toString());
+ assertEquals(sTestValues1.toString(), values.toString());
+ return uri.buildUpon().appendPath("19").build();
+ }
+ }, null, 0);
+ assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+ }
+
+ public void testInsertNoValues() throws OperationApplicationException {
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .build();
+ ContentProviderResult result = op1.apply(new TestContentProvider() {
+ public Uri insert(Uri uri, ContentValues values) {
+ assertEquals(sTestUri1.toString(), uri.toString());
+ assertNull(values);
+ return uri.buildUpon().appendPath("19").build();
+ }
+ }, null, 0);
+ assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+ }
+
+ public void testInsertFailed() {
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .withValues(sTestValues1)
+ .build();
+ try {
+ op1.apply(new TestContentProvider() {
+ public Uri insert(Uri uri, ContentValues values) {
+ assertEquals(sTestUri1.toString(), uri.toString());
+ assertEquals(sTestValues1.toString(), values.toString());
+ return null;
+ }
+ }, null, 0);
+ fail("the apply should have thrown an OperationApplicationException");
+ } catch (OperationApplicationException e) {
+ // this is the expected case
+ }
+ }
+
+ public void testInsertWithBackRefs() throws OperationApplicationException {
+ ContentValues valuesBackRefs = new ContentValues();
+ valuesBackRefs.put("a1", 3);
+ valuesBackRefs.put("a2", 1);
+
+ ContentProviderResult[] previousResults = new ContentProviderResult[4];
+ previousResults[0] = new ContentProviderResult(100);
+ previousResults[1] = new ContentProviderResult(101);
+ previousResults[2] = new ContentProviderResult(102);
+ previousResults[3] = new ContentProviderResult(103);
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .withValues(sTestValues1)
+ .withValueBackReferences(valuesBackRefs)
+ .build();
+ ContentProviderResult result = op1.apply(new TestContentProvider() {
+ public Uri insert(Uri uri, ContentValues values) {
+ assertEquals(sTestUri1.toString(), uri.toString());
+ ContentValues expected = new ContentValues(sTestValues1);
+ expected.put("a1", 103);
+ expected.put("a2", 101);
+ assertEquals(expected.toString(), values.toString());
+ return uri.buildUpon().appendPath("19").build();
+ }
+ }, previousResults, previousResults.length);
+ assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+ }
+
+ public void testUpdate() throws OperationApplicationException {
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .withValues(sTestValues1)
+ .build();
+ ContentProviderResult[] backRefs = new ContentProviderResult[2];
+ ContentProviderResult result = op1.apply(new TestContentProvider() {
+ public Uri insert(Uri uri, ContentValues values) {
+ assertEquals(sTestUri1.toString(), uri.toString());
+ assertEquals(sTestValues1.toString(), values.toString());
+ return uri.buildUpon().appendPath("19").build();
+ }
+ }, backRefs, 1);
+ assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+ }
+
+ public void testValueBackRefs() {
+ ContentValues values = new ContentValues();
+ values.put("a", "in1");
+ values.put("a2", "in2");
+ values.put("b", "in3");
+ values.put("c", "in4");
+
+ ContentProviderResult[] previousResults = new ContentProviderResult[4];
+ previousResults[0] = new ContentProviderResult(100);
+ previousResults[1] = new ContentProviderResult(101);
+ previousResults[2] = new ContentProviderResult(102);
+ previousResults[3] = new ContentProviderResult(103);
+
+ ContentValues valuesBackRefs = new ContentValues();
+ valuesBackRefs.put("a1", 3); // a1 -> 103
+ valuesBackRefs.put("a2", 1); // a2 -> 101
+ valuesBackRefs.put("a3", 2); // a3 -> 102
+
+ ContentValues expectedValues = new ContentValues(values);
+ expectedValues.put("a1", "103");
+ expectedValues.put("a2", "101");
+ expectedValues.put("a3", "102");
+
+ ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+ .withValues(values)
+ .withValueBackReferences(valuesBackRefs)
+ .build();
+ ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length);
+ assertEquals(expectedValues, v2);
+ }
+
+ public void testSelectionBackRefs() {
+ Map<Integer, Integer> selectionBackRefs = new Hashtable<Integer, Integer>();
+ selectionBackRefs.put(1, 3);
+ selectionBackRefs.put(2, 1);
+ selectionBackRefs.put(4, 2);
+
+ ContentProviderResult[] previousResults = new ContentProviderResult[4];
+ previousResults[0] = new ContentProviderResult(100);
+ previousResults[1] = new ContentProviderResult(101);
+ previousResults[2] = new ContentProviderResult(102);
+ previousResults[3] = new ContentProviderResult(103);
+
+ String[] selectionArgs = new String[]{"a", null, null, "b", null};
+
+ ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1)
+ .withSelectionBackReferences(selectionBackRefs)
+ .withSelection("unused", selectionArgs)
+ .build();
+ String[] s2 = op1.resolveSelectionArgsBackReferences(
+ previousResults, previousResults.length);
+ assertEquals("a,103,101,b,102", TextUtils.join(",", s2));
+ }
+
+ static class TestContentProvider extends ContentProvider {
+ public boolean onCreate() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/CoreTests/android/location/LocationManagerProximityTest.java b/tests/CoreTests/android/location/LocationManagerProximityTest.java
index 3f43bcf..e82d878 100644
--- a/tests/CoreTests/android/location/LocationManagerProximityTest.java
+++ b/tests/CoreTests/android/location/LocationManagerProximityTest.java
@@ -26,6 +26,7 @@
import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
/**
@@ -37,9 +38,11 @@
* adb shell am instrument -e class android.location.LocationManagerProximityTest \
* -w android.core/android.test.InstrumentationTestRunner
*
- * This test requires that the "Allow mock locations" setting be enabled
+ * This test requires that the "Allow mock locations" setting be enabled.
+ * To ensure reliable results, all location providers should be disabled.
*
*/
+@Suppress
@MediumTest
public class LocationManagerProximityTest extends AndroidTestCase {
diff --git a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
index 5df8991..e2336f8 100644
--- a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
@@ -28,18 +28,20 @@
@SmallTest
public void test7bitWithHeader() throws Exception {
- byte[] data = new byte[3];
- data[0] = (byte) 1;
- data[1] = (byte) 2;
- data[2] = (byte) 2;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = 1;
+ concatRef.seqNumber = 2;
+ concatRef.msgCount = 2;
+ concatRef.isEightBits = true;
SmsHeader header = new SmsHeader();
- header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+ header.concatRef = concatRef;
- String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
- byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header.toByteArray());
+ String message = "aaaaaaaaaabbbbbbbbbbcccccccccc";
+ byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message,
+ SmsHeader.toByteArray(header));
int septetCount = GsmAlphabet.countGsmSeptets(message, false);
String parsedMessage = GsmAlphabet.gsm7BitPackedToString(
- userData, header.toByteArray().length+1, septetCount, 1);
+ userData, SmsHeader.toByteArray(header).length+1, septetCount, 1);
assertEquals(message, parsedMessage);
}
@@ -306,4 +308,3 @@
GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1));
}
}
-
diff --git a/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
index 5d5d1f9..8a66614 100644
--- a/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
@@ -34,35 +34,38 @@
public void testCMT1() throws Exception {
SmsMessage sms;
SmsHeader header;
- Iterator<SmsHeader.Element> elements;
String[] lines = new String[2];
-
- lines[0] = "+CMT: ,158";
+
+ lines[0] = "+CMT: ,158";
lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
+ "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
+ "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
+ "7547514D4141424C3641414141536741415A4B554141414141008D908918"
+ "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
+ "88058103093A8083687474703A2F2F36";
-
+
sms = SmsMessage.newFromCMT(lines);
header = sms.getUserDataHeader();
assertNotNull(header);
assertNotNull(sms.getUserData());
-
- elements = header.getElements().iterator();
- assertNotNull(elements);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 1);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
}
-
+
@MediumTest
public void testCMT2() throws Exception {
SmsMessage sms;
SmsHeader header;
- Iterator<SmsHeader.Element> elements;
String[] lines = new String[2];
-
lines[0] = "+CMT: ,77";
lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
@@ -71,12 +74,17 @@
sms = SmsMessage.newFromCMT(lines);
header = sms.getUserDataHeader();
- System.out.println("header = " + header);
assertNotNull(header);
assertNotNull(sms.getUserData());
-
- elements = header.getElements().iterator();
- assertNotNull(elements);
+ assertNotNull(header.concatRef);
+ assertEquals(header.concatRef.refNumber, 85);
+ assertEquals(header.concatRef.msgCount, 2);
+ assertEquals(header.concatRef.seqNumber, 2);
+ assertEquals(header.concatRef.isEightBits, true);
+ assertNotNull(header.portAddrs);
+ assertEquals(header.portAddrs.destPort, 2948);
+ assertEquals(header.portAddrs.origPort, 9200);
+ assertEquals(header.portAddrs.areEightBits, false);
}
@MediumTest
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 0e33d62..5442ec9 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -31,5 +31,6 @@
android:targetPackage="com.android.dumprendertree"
android:label="Layout test automation runner"
/>
- <uses-permission android:name="android.permission.INTERNET"></uses-permission>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WRITE_SDCARD" />
</manifest>
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index caef861..f169a26 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -223,7 +223,10 @@
}
private String getExpectedResultFile(String test) {
- String shortName = test.substring(0, test.lastIndexOf('.'));
+ int pos = test.lastIndexOf('.');
+ if(pos == -1)
+ return null;
+ String shortName = test.substring(0, pos);
return shortName + "-expected.txt";
}
@@ -303,6 +306,10 @@
});
String resultFile = getResultFile(test);
+ if(resultFile == null) {
+ //simply ignore this test
+ return;
+ }
if (mRebaselineResults) {
String expectedResultFile = getExpectedResultFile(test);
File f = new File(expectedResultFile);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 81cf3a8..c792e8e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -69,11 +69,14 @@
TestShellActivity activity = (TestShellActivity) getActivity();
+ Log.v(LOGTAG, "About to run tests, calling gc first...");
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
// Run tests
runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
- // TODO(fqian): let am instrumentation pass in the command line, currently
- // am instrument does not allow spaces in the command.
dumpMemoryInfo();
// Kill activity
@@ -82,6 +85,11 @@
private void dumpMemoryInfo() {
try {
+ Log.v(LOGTAG, "About to dump meminfo, calling gc first...");
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
Log.v(LOGTAG, "Dumping memory information.");
FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true);
diff --git a/tests/backup/Android.mk b/tests/backup/Android.mk
index 2e3385f8..0813c35 100644
--- a/tests/backup/Android.mk
+++ b/tests/backup/Android.mk
@@ -21,7 +21,7 @@
LOCAL_SRC_FILES := \
backup_helper_test.cpp
-LOCAL_MODULE_TAGS := user
+LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := backup_helper_test
LOCAL_SHARED_LIBRARIES := libutils
@@ -31,7 +31,7 @@
# ========================================
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := user
+LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
diff --git a/tests/backup/backup_helper_test.cpp b/tests/backup/backup_helper_test.cpp
index 66240e3..1085909 100644
--- a/tests/backup/backup_helper_test.cpp
+++ b/tests/backup/backup_helper_test.cpp
@@ -23,6 +23,7 @@
{ "backup_helper_test_four", backup_helper_test_four, 0, false },
{ "backup_helper_test_files", backup_helper_test_files, 0, false },
{ "backup_helper_test_data_writer", backup_helper_test_data_writer, 0, false },
+ { "backup_helper_test_data_reader", backup_helper_test_data_reader, 0, false },
{ 0, NULL, 0, false}
};
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml
index c44b54e..fbf3a09b 100755
--- a/tests/sketch/AndroidManifest.xml
+++ b/tests/sketch/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2008-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.
@@ -14,17 +14,32 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.gesture"
- android:versionCode="1"
- android:versionName="1.0.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name="com.android.gesture.example.GestureEntryDemo"
- android:label="@string/app_name">
+ package="com.android.gesture.example">
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_SDCARD" />
+
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+
+ <activity
+ android:name="com.android.gesture.example.GestureEntry"
+ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
<activity android:name="com.android.gesture.example.GestureLibViewer"/>
+
+ <activity
+ android:name="com.android.gesture.example.ContactListGestureOverlay"
+ android:label="@string/overlay_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml
index e516229..8c9161a 100755
--- a/tests/sketch/res/layout/demo.xml
+++ b/tests/sketch/res/layout/demo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- 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.
@@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
@@ -24,7 +25,7 @@
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
- <com.android.gesture.GesturePad
+ <com.android.gesture.GestureOverlay
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml
index 5302d34..73d6a35 100755
--- a/tests/sketch/res/layout/gestureviewer.xml
+++ b/tests/sketch/res/layout/gestureviewer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- 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.
@@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
@@ -25,7 +26,7 @@
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
- <com.android.gesture.GesturePad
+ <com.android.gesture.GestureOverlay
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/newgesture_dialog.xml b/tests/sketch/res/layout/newgesture_dialog.xml
index 6e45d81..91e7645 100755
--- a/tests/sketch/res/layout/newgesture_dialog.xml
+++ b/tests/sketch/res/layout/newgesture_dialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- 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.
diff --git a/tests/sketch/res/layout/overlaydemo.xml b/tests/sketch/res/layout/overlaydemo.xml
new file mode 100644
index 0000000..b6bbab3
--- /dev/null
+++ b/tests/sketch/res/layout/overlaydemo.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+ <ListView
+ android:id="@+id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"/>
+</LinearLayout>
diff --git a/tests/sketch/res/values/strings.xml b/tests/sketch/res/values/strings.xml
index 4c6aa20..42f14da 100755
--- a/tests/sketch/res/values/strings.xml
+++ b/tests/sketch/res/values/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- 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.
@@ -15,6 +15,7 @@
-->
<resources>
<string name="app_name">Gesture Demo</string>
+ <string name="overlay_name">Overlay Demo</string>
<string name="recognition_result">Recognition Result</string>
<string name="clear">Clear</string>
<string name="newgesture">Add</string>
diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java
deleted file mode 100755
index 29c07ad..0000000
--- a/tests/sketch/src/com/android/gesture/Gesture.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2008-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.gesture;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.gesture.recognizer.RecognitionUtil;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-
-/**
- * A single stroke gesture.
- */
-
-public class Gesture implements Parcelable {
-
- private RectF mBBX;
- private float mLength = 0;
- private int mColor;
- private float mWidth;
- private ArrayList<PointF> mPtsBuffer = new ArrayList<PointF>();
- private long mTimestamp = 0;
- private long mID;
-
- private static final long systemStartupTime = System.currentTimeMillis();
- private static int instanceCount = 0;
-
- public Gesture() {
- mID = systemStartupTime + instanceCount++;
- }
-
- public void setColor(int c) {
- mColor = c;
- }
-
- public void setStrokeWidth(float w) {
- mWidth = w;
- }
-
- public int getColor() {
- return mColor;
- }
-
- public float getStrokeWidth() {
- return mWidth;
- }
-
- public ArrayList<PointF> getPoints() {
- return this.mPtsBuffer;
- }
-
- public int numOfPoints() {
- return this.mPtsBuffer.size();
- }
-
- public void addPoint(float x, float y) {
- mPtsBuffer.add(new PointF(x, y));
- if (mBBX == null) {
- mBBX = new RectF();
- mBBX.top = y;
- mBBX.left = x;
- mBBX.right = x;
- mBBX.bottom = y;
- mLength = 0;
- }
- else {
- PointF lst = mPtsBuffer.get(mPtsBuffer.size()-2);
- mLength += Math.sqrt(Math.pow(x-lst.x, 2)+Math.pow(y-lst.y, 2));
- mBBX.union(x, y);
- }
- mTimestamp = System.currentTimeMillis();
- }
-
- /**
- * @return the length of the gesture
- */
- public float getLength() {
- return this.mLength;
- }
-
- public RectF getBBX() {
- return mBBX;
- }
-
- public void setID(long id) {
- mID = id;
- }
-
- public long getID() {
- return mID;
- }
-
- public long getTimeStamp() {
- return mTimestamp;
- }
-
- public void setTimestamp(long t) {
- this.mTimestamp = t;
- }
-
- /**
- * draw the gesture
- * @param canvas
- */
- public void draw(Canvas canvas) {
- Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setDither(true);
- paint.setColor(mColor);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeJoin(Paint.Join.ROUND);
- paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(mWidth);
-
- Path path = null;
- float mX = 0, mY = 0;
- Iterator<PointF> it = mPtsBuffer.iterator();
- while (it.hasNext()) {
- PointF p = it.next();
- float x = p.x;
- float y = p.y;
- if (path == null) {
- path = new Path();
- path.moveTo(x, y);
- mX = x;
- mY = y;
- } else {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= 3 || dy >= 3) {
- path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
- mX = x;
- mY = y;
- }
- }
- }
-
- canvas.drawPath(path, paint);
- }
-
- /**
- * convert the gesture to a Path
- * @param width the width of the bounding box of the target path
- * @param height the height of the bounding box of the target path
- * @param numSample the num of points needed
- * @return the path
- */
- public Path toPath(float width, float height, int numSample) {
- float[] pts = RecognitionUtil.resample(this, numSample);
- RectF rect = this.getBBX();
- float scale = height / rect.height();
- Matrix matrix = new Matrix();
- matrix.setTranslate(-rect.left, -rect.top);
- Matrix scalem = new Matrix();
- scalem.setScale(scale, scale);
- matrix.postConcat(scalem);
- Matrix translate = new Matrix();
- matrix.postConcat(translate);
- matrix.mapPoints(pts);
-
- Path path = null;
- float mX = 0, mY = 0;
- for (int i=0; i<pts.length-1; i+=2) {
- float x = pts[i];
- float y = pts[i+1];
- if (path == null) {
- path = new Path();
- path.moveTo(x, y);
- mX = x;
- mY = y;
- } else {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= 3 || dy >= 3) {
- path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
- mX = x;
- mY = y;
- }
- }
- }
- return path;
- }
-
- /**
- * get a bitmap thumbnail of the gesture with a transparent background
- * @param w
- * @param h
- * @param edge
- * @param numSample
- * @param foreground
- * @return
- */
- public Bitmap toBitmap(int w, int h,
- int edge, int numSample) {
- RectF bbx = this.getBBX();
- Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- Path path = this.toPath(w - 2 * edge, h - 2 * edge, numSample);
- Canvas c = new Canvas(bitmap);
- //c.drawColor(background);
- c.translate(edge, edge);
- Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setDither(true);
- paint.setColor(mColor);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeJoin(Paint.Join.ROUND);
- paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(2);
- c.drawPath(path, paint);
- return bitmap;
- }
-
- /**
- * save the gesture as XML
- * @param namespace
- * @param serializer
- * @throws IOException
- */
- public void toXML(String namespace, XmlSerializer serializer) throws IOException {
- serializer.startTag(namespace, "stroke");
- serializer.attribute(namespace, "timestamp", Long.toString(mTimestamp));
- serializer.attribute(namespace, "id", Long.toString(mID));
- serializer.attribute(namespace, "color", Integer.toString(mColor));
- serializer.attribute(namespace, "width", Float.toString(mWidth));
- Iterator it = this.mPtsBuffer.iterator();
- String pts = "";
- while (it.hasNext()) {
- PointF fp = (PointF)it.next();
- if (pts.length() > 0)
- pts += ",";
- pts += fp.x + "," + fp.y;
- }
- serializer.text(pts);
- serializer.endTag(namespace, "stroke");
- }
-
-
- public void createFromString(String str) {
- StringTokenizer st = new StringTokenizer(str, "#");
-
- String para = st.nextToken();
- StringTokenizer innerst = new StringTokenizer(para, ",");
- this.mBBX = new RectF();
- this.mBBX.left = Float.parseFloat(innerst.nextToken());
- this.mBBX.top = Float.parseFloat(innerst.nextToken());
- this.mBBX.right = Float.parseFloat(innerst.nextToken());
- this.mBBX.bottom = Float.parseFloat(innerst.nextToken());
-
- para = st.nextToken();
- innerst = new StringTokenizer(para, ",");
- while (innerst.hasMoreTokens()) {
- String s = innerst.nextToken().trim();
- if (s.length()==0)
- break;
- float x = Float.parseFloat(s);
- float y = Float.parseFloat(innerst.nextToken());
- this.mPtsBuffer.add(new PointF(x, y));
- }
-
- para = st.nextToken();
- this.mColor = Integer.parseInt(para);
-
- para = st.nextToken();
- this.mWidth = Float.parseFloat(para);
-
- para = st.nextToken();
- this.mLength = Float.parseFloat(para);
-
- para = st.nextToken();
- this.mTimestamp = Long.parseLong(para);
- }
-
- @Override
- public String toString() {
- String str = "";
-
- str += "#" + this.mBBX.left + "," + this.mBBX.top + "," +
- this.mBBX.right + "," + this.mBBX.bottom;
-
- str += "#";
- Iterator<PointF> it = this.mPtsBuffer.iterator();
- while (it.hasNext()) {
- PointF fp = it.next();
- str += fp.x + "," + fp.y + ",";
- }
-
- str += "#";
- str += this.mColor;
-
- str += "#";
- str += this.mWidth;
-
- str += "#";
- str += this.mLength;
-
- str += "#";
- str += this.mTimestamp;
-
- return str;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public Gesture createFromParcel(Parcel in) {
- String str = in.readString();
- Gesture stk = new Gesture();
- stk.createFromString(str);
- return stk;
- }
-
- public Gesture[] newArray(int size) {
- return new Gesture[size];
- }
- };
-
- public static Gesture buildFromArray(byte[] bytes) {
- String str = new String(bytes);
- Gesture stk = new Gesture();
- stk.createFromString(str);
- return stk;
- }
-
- public static byte[] saveToArray(Gesture stk) {
- String str = stk.toString();
- return str.getBytes();
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(this.toString());
- }
-
- public int describeContents() {
- return CONTENTS_FILE_DESCRIPTOR;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureLib.java b/tests/sketch/src/com/android/gesture/GestureLib.java
deleted file mode 100755
index d0a25f2..0000000
--- a/tests/sketch/src/com/android/gesture/GestureLib.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2008-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.gesture;
-
-import android.util.Log;
-import android.util.Xml;
-import android.util.Xml.Encoding;
-
-import com.android.gesture.recognizer.Classifier;
-import com.android.gesture.recognizer.Instance;
-import com.android.gesture.recognizer.NearestNeighbor;
-import com.android.gesture.recognizer.Prediction;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-public class GestureLib {
-
- private static final String LOGTAG = "GestureLib";
- private static String namespace = "ink";
- private final String datapath;
- private HashMap<String, ArrayList<Gesture>> name2gestures =
- new HashMap<String, ArrayList<Gesture>>();
- private Classifier mClassifier;
-
- public GestureLib(String path) {
- datapath = path;
- mClassifier = new NearestNeighbor();
- }
-
- public Classifier getClassifier() {
- return mClassifier;
- }
-
- /**
- * get all the labels in the library
- * @return a set of strings
- */
- public Set<String> getLabels() {
- return name2gestures.keySet();
- }
-
- public ArrayList<Prediction> recognize(Gesture gesture) {
- Instance instance = Instance.createInstance(gesture, null);
- return mClassifier.classify(instance);
- }
-
- public void addGesture(String name, Gesture gesture) {
- Log.v(LOGTAG, "add an example for gesture: " + name);
- ArrayList<Gesture> gestures = name2gestures.get(name);
- if (gestures == null) {
- gestures = new ArrayList<Gesture>();
- name2gestures.put(name, gestures);
- }
- gestures.add(gesture);
- mClassifier.addInstance(
- Instance.createInstance(gesture, name));
- }
-
- public void removeGesture(String name, Gesture gesture) {
- ArrayList<Gesture> gestures = name2gestures.get(name);
- if (gestures == null) {
- return;
- }
-
- gestures.remove(gesture);
-
- // if there are no more samples, remove the entry automatically
- if (gestures.isEmpty()) {
- name2gestures.remove(name);
- }
-
- mClassifier.removeInstance(gesture.getID());
- }
-
- public ArrayList<Gesture> getGestures(String label) {
- ArrayList<Gesture> gestures = name2gestures.get(label);
- if (gestures != null)
- return (ArrayList<Gesture>)gestures.clone();
- else
- return null;
- }
-
- public void load() {
- String filename = datapath
- + File.separator + "gestures.xml";
- File f = new File(filename);
- if (f.exists()) {
- try {
- loadInk(filename, null);
- }
- catch (SAXException ex) {
- ex.printStackTrace();
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
-
- public void save() {
- try {
- compactSave();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- private void compactSave() throws IOException {
- File f = new File(datapath);
- if (f.exists() == false) {
- f.mkdirs();
- }
- String filename = datapath + File.separator + "gestures.xml";
- Log.v(LOGTAG, "save to " + filename);
- BufferedOutputStream fos = new BufferedOutputStream(
- new FileOutputStream(filename));
-
- PrintWriter writer = new PrintWriter(fos);
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(writer);
- serializer.startDocument(Encoding.ISO_8859_1.name(), null);
- serializer.startTag(namespace, "gestures");
- Iterator<String> it = name2gestures.keySet().iterator();
- while (it.hasNext()) {
- String key = it.next();
- ArrayList<Gesture> gestures = name2gestures.get(key);
- saveGestures(serializer, key, gestures);
- }
-
- serializer.endTag(namespace, "gestures");
- serializer.endDocument();
- serializer.flush();
- writer.close();
- fos.close();
- }
-
- private static void saveGestures(XmlSerializer serializer,
- String name, ArrayList<Gesture> strokes) throws IOException {
- serializer.startTag(namespace, "gesture");
- serializer.startTag(namespace, "name");
- serializer.text(name);
- serializer.endTag(namespace, "name");
- Iterator<Gesture> it = strokes.iterator();
- while (it.hasNext()) {
- Gesture stk = it.next();
- stk.toXML(namespace, serializer);
- }
- serializer.endTag(namespace, "gesture");
- }
-
- private void loadInk(String filename, String label) throws SAXException, IOException {
- Log.v(LOGTAG, "load from " + filename);
- BufferedInputStream in = new BufferedInputStream(
- new FileInputStream(filename));
- Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
- in.close();
- }
-
- class CompactInkHandler implements ContentHandler {
-
- Gesture currentGesture = null;
- StringBuffer buffer = null;
- String gestureName;
- ArrayList<Gesture> gestures;
-
- CompactInkHandler() {
- }
-
- // Receive notification of character data.
- public void characters(char[] ch, int start, int length) {
- buffer.append(ch, start, length);
- }
-
- //Receive notification of the end of a document.
- public void endDocument() {
- }
-
- // Receive notification of the end of an element.
- public void endElement(String uri, String localName, String qName) {
- if (localName.equals("gesture")) {
- name2gestures.put(gestureName, gestures);
- gestures = null;
- } else if (localName.equals("name")) {
- gestureName = buffer.toString();
- } else if (localName.equals("stroke")) {
- StringTokenizer tokenizer = new StringTokenizer(buffer.toString(), ",");
- while (tokenizer.hasMoreTokens()) {
- String str = tokenizer.nextToken();
- float x = Float.parseFloat(str);
- str = tokenizer.nextToken();
- float y = Float.parseFloat(str);
- try
- {
- currentGesture.addPoint(x, y);
- }
- catch(Exception ex) {
- ex.printStackTrace();
- }
- }
- gestures.add(currentGesture);
- mClassifier.addInstance(
- Instance.createInstance(currentGesture, gestureName));
- currentGesture = null;
- }
- }
-
- // End the scope of a prefix-URI mapping.
- public void endPrefixMapping(String prefix) {
- }
-
- //Receive notification of ignorable whitespace in element content.
- public void ignorableWhitespace(char[] ch, int start, int length) {
- }
-
- //Receive notification of a processing instruction.
- public void processingInstruction(String target, String data) {
- }
-
- // Receive an object for locating the origin of SAX document events.
- public void setDocumentLocator(Locator locator) {
- }
-
- // Receive notification of a skipped entity.
- public void skippedEntity(String name) {
- }
-
- // Receive notification of the beginning of a document.
- public void startDocument() {
- }
-
- // Receive notification of the beginning of an element.
- public void startElement(String uri, String localName, String qName, Attributes atts) {
- if (localName.equals("gesture")) {
- gestures = new ArrayList<Gesture>();
- } else if (localName.equals("name")) {
- buffer = new StringBuffer();
- } else if (localName.equals("stroke")) {
- currentGesture = new Gesture();
- currentGesture.setTimestamp(Long.parseLong(atts.getValue(namespace, "timestamp")));
- currentGesture.setColor(Integer.parseInt(atts.getValue(namespace, "color")));
- currentGesture.setStrokeWidth(Float.parseFloat(atts.getValue(namespace, "width")));
- buffer = new StringBuffer();
- }
- }
-
- public void startPrefixMapping(String prefix, String uri) {
- }
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GesturePad.java b/tests/sketch/src/com/android/gesture/GesturePad.java
deleted file mode 100755
index 45a09e6..0000000
--- a/tests/sketch/src/com/android/gesture/GesturePad.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * A view for rendering and processing gestures
- */
-
-public class GesturePad extends View {
-
- public static final float TOUCH_TOLERANCE = 4;
- public static final int default_foreground = Color.argb(255, 255, 255, 0);
- private int background = Color.argb(0, 0, 0, 0);
- private int foreground = default_foreground;
- private int uncertain_foreground = Color.argb(55, 255, 255, 0);
- private Bitmap mBitmap;
- private Canvas mCanvas;
- private Path mPath;
- private Paint mBitmapPaint;
- private Paint mPaint;
- private Paint mDebugPaint;
- private float mX, mY;
- private boolean mEnableInput = true;
- private boolean mEnableRendering = true;
- private boolean mCacheGesture = true;
- private Gesture mCurrentGesture = null;
- ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
-
- private boolean mShouldFadingOut = true;
- private boolean mIsFadingOut = false;
- private float mFadingAlpha = 1;
-
- private boolean reconstruct = false;
-
- private ArrayList<Path> debug = new ArrayList<Path>();
- private Handler mHandler = new Handler();
-
- private Runnable mFadingOut = new Runnable() {
- public void run() {
- mFadingAlpha -= 0.03f;
- if (mFadingAlpha <= 0) {
- mIsFadingOut = false;
- mPath.reset();
- } else {
- mHandler.postDelayed(this, 100);
- }
- invalidate();
- }
- };
-
- public GesturePad(Context context) {
- super(context);
- init();
- }
-
- public GesturePad(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public boolean isEnableRendering() {
- return this.mEnableRendering;
- }
-
- public Gesture getCurrentGesture() {
- return mCurrentGesture;
- }
-
- public Paint getPaint() {
- return mPaint;
- }
-
- public void setColor(int c) {
- this.foreground = c;
- }
-
- public void setFadingAlpha(float f) {
- mFadingAlpha = f;
- }
-
- public void setCurrentGesture(Gesture stk) {
- this.mCurrentGesture = stk;
- reconstruct = true;
- }
-
- private void init() {
- mDebugPaint = new Paint();
- mDebugPaint.setColor(Color.WHITE);
- mDebugPaint.setStrokeWidth(4);
- mDebugPaint.setAntiAlias(true);
- mDebugPaint.setStyle(Paint.Style.STROKE);
-
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setDither(true);
- mPaint.setColor(foreground);
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setStrokeJoin(Paint.Join.ROUND);
- mPaint.setStrokeCap(Paint.Cap.ROUND);
- mPaint.setStrokeWidth(12);
-
- mBitmapPaint = new Paint(Paint.DITHER_FLAG);
- mPath = new Path();
-
- reconstruct = false;
- }
-
- public void cacheGesture(boolean b) {
- mCacheGesture = b;
- }
-
- public void enableRendering(boolean b) {
- mEnableRendering = b;
- }
-
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // TODO Auto-generated method stub
- super.onSizeChanged(w, h, oldw, oldh);
-
- if (w <=0 || h <=0)
- return;
-
- int width = w>oldw? w : oldw;
- int height = h>oldh? h : oldh;
- Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- mCanvas = new Canvas(newBitmap);
-
- if (mBitmap != null) {
- mCanvas.drawColor(background);
- mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
- mCanvas.drawPath(mPath, mPaint);
- }
-
- mBitmap = newBitmap;
- }
-
- public void addGestureListener(GestureListener l) {
- this.mGestureListeners.add(l);
- }
-
- public void removeGestureListener(GestureListener l) {
- this.mGestureListeners.remove(l);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawColor(background);
-
- if (mCacheGesture)
- canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
-
- if (mIsFadingOut) {
- int color = foreground;
- int alpha = (int)(Color.alpha(color) * mFadingAlpha);
- mPaint.setColor(Color.argb(alpha,
- Color.red(color),
- Color.green(color),
- Color.blue(color)));
- } else if (mEnableRendering == false) {
- mPaint.setColor(uncertain_foreground);
- } else {
- mPaint.setColor(foreground);
- }
-
- if (reconstruct) {
-
- if (this.mCurrentGesture != null) {
- float xedge = 30;
- float yedge = 30;
- float w = this.getWidth() - 2 * xedge;
- float h = this.getHeight() - 2 * yedge;
- float sx = w / this.mCurrentGesture.getBBX().width();
- float sy = h / mCurrentGesture.getBBX().height();
- float scale = sx>sy?sy:sx;
- convertFromStroke(mCurrentGesture);
- Matrix matrix = new Matrix();
- matrix.preTranslate(-mCurrentGesture.getBBX().centerX(), -mCurrentGesture.getBBX().centerY());
- matrix.postScale(scale, scale);
- matrix.postTranslate(this.getWidth()/2, this.getHeight()/2);
- this.mPath.transform(matrix);
- } else {
- mPath.reset();
- }
-
- reconstruct = false;
- }
-
- canvas.drawPath(mPath, mPaint);
-
- Iterator<Path> it = debug.iterator();
- while (it.hasNext()) {
- Path path = it.next();
- canvas.drawPath(path, mDebugPaint);
- }
- }
-
- public void clearDebugPath() {
- debug.clear();
- }
-
- public void addDebugPath(Path path) {
- debug.add(path);
- }
-
- public void addDebugPath(ArrayList<Path> paths) {
- debug.addAll(paths);
- }
-
- public void clear() {
- mPath = new Path();
- this.mCurrentGesture = null;
- mCanvas.drawColor(background);
- this.invalidate();
- }
-
- private void convertFromStroke(Gesture stk) {
- mPath = null;
- Iterator it = stk.getPoints().iterator();
- while (it.hasNext()) {
- PointF p = (PointF) it.next();
- if (mPath == null) {
- mPath = new Path();
- mPath.moveTo(p.x, p.y);
- mX = p.x;
- mY = p.y;
- } else {
- float dx = Math.abs(p.x - mX);
- float dy = Math.abs(p.y - mY);
- if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
- mPath.quadTo(mX, mY, (p.x + mX)/2, (p.y + mY)/2);
- mX = p.x;
- mY = p.y;
- }
- }
- }
- mPath.lineTo(mX, mY);
- }
-
- public void setEnableInput(boolean b) {
- mEnableInput = b;
- }
-
- public boolean isEnableInput() {
- return mEnableInput;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- if(mEnableInput == false)
- return true;
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- touch_start(event);
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- touch_move(event);
- invalidate();
- break;
- case MotionEvent.ACTION_UP:
- touch_up(event);
- invalidate();
- break;
- }
- return true;
- }
-
- private void touch_start(MotionEvent event) {
- mIsFadingOut = false;
- mHandler.removeCallbacks(mFadingOut);
-
- float x = event.getX();
- float y = event.getY();
-
- mCurrentGesture = new Gesture();
- mCurrentGesture.addPoint(x, y);
-
- mPath.reset();
- mPath.moveTo(x, y);
- mX = x;
- mY = y;
-
- Iterator<GestureListener> it = mGestureListeners.iterator();
- while (it.hasNext()) {
- it.next().onStartGesture(this, event);
- }
- }
-
- private void touch_move(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
-
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
- mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
- mX = x;
- mY = y;
- }
-
- mCurrentGesture.addPoint(x, y);
-
- Iterator<GestureListener> it = mGestureListeners.iterator();
- while (it.hasNext()) {
- it.next().onGesture(this, event);
- }
- }
-
- public void setFadingOut(boolean b) {
- mShouldFadingOut = b;
- mIsFadingOut = false;
- }
-
- public boolean shouldFadingOut() {
- return mShouldFadingOut;
- }
-
- private void touch_up(MotionEvent event) {
- mPath.lineTo(mX, mY);
-
- if (mCacheGesture)
- mCanvas.drawPath(mPath, mPaint);
-
- // kill this so we don't double draw
- if (shouldFadingOut()) {
- mFadingAlpha = 1;
- mIsFadingOut = true;
- mHandler.removeCallbacks(mFadingOut);
- mHandler.postDelayed(mFadingOut, 100);
- }
-
- Iterator<GestureListener> it = mGestureListeners.iterator();
- while (it.hasNext()) {
- it.next().onFinishGesture(this, event);
- }
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactAdapter.java b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
new file mode 100644
index 0000000..008a972
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008-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.gesture.example;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+class ContactAdapter extends ArrayAdapter<ContactItem> {
+
+ private LayoutInflater mInflater;
+
+ public ContactAdapter(Activity activity, ArrayList<ContactItem> contacts) {
+ super(activity, 0, contacts);
+ mInflater = activity.getLayoutInflater();
+ }
+
+ @Override
+ public ContactItem getItem(int position) {
+ return super.getItem(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return getItem(position).itemID;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final ContactItem info = getItem(position);
+
+ View view = convertView;
+ if (view == null) {
+ view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+ view.setTag(view.findViewById(android.R.id.text1));
+ }
+
+ final TextView textView = (TextView)view.getTag();
+ textView.setText(info.toString());
+
+ return view;
+ }
+
+ public int search(String query) {
+ if (query != null && query.length() > 0) {
+ int start = 0;
+ int end = getCount() - 1;
+ int index = binarySearch(query, start, end);
+ for (index = index - 1; index >= 0; index--) {
+ String str = getItem(index).toString().toLowerCase();
+ if (!str.startsWith(query)) {
+ return index + 1;
+ }
+ if (index == 0) {
+ return 0;
+ }
+ }
+ return -1;
+ } else {
+ return -1;
+ }
+ }
+
+ private int binarySearch(String prefix, int start, int end) {
+ if (start > end) {
+ return -1;
+ }
+ int mid = (start + end) / 2;
+ String str = getItem(mid).toString().toLowerCase();
+ if (prefix.compareTo(str) <= 0) {
+ if (str.startsWith(prefix)) {
+ return mid;
+ } else {
+ return binarySearch(prefix, start, mid - 1);
+ }
+ } else {
+ return binarySearch(prefix, mid + 1, end);
+ }
+ }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/example/ContactItem.java
old mode 100755
new mode 100644
similarity index 67%
copy from tests/sketch/src/com/android/gesture/GestureListener.java
copy to tests/sketch/src/com/android/gesture/example/ContactItem.java
index ebb4149..557c4d9
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/tests/sketch/src/com/android/gesture/example/ContactItem.java
@@ -14,12 +14,21 @@
* limitations under the License.
*/
-package com.android.gesture;
+package com.android.gesture.example;
-import android.view.MotionEvent;
-public interface GestureListener {
- public void onStartGesture(GesturePad pad, MotionEvent event);
- public void onGesture(GesturePad pad, MotionEvent event);
- public void onFinishGesture(GesturePad pad, MotionEvent event);
+class ContactItem {
+ final String itemName;
+
+ final long itemID;
+
+ public ContactItem(long id, String name) {
+ itemID = id;
+ itemName = name;
+ }
+
+ @Override
+ public String toString() {
+ return itemName;
+ }
}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
new file mode 100644
index 0000000..eda4224
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2008-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.gesture.example;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts.People;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import android.gesture.Gesture;
+import android.gesture.GestureOverlayView;
+import android.gesture.LetterRecognizer;
+import android.gesture.Prediction;
+import android.gesture.TouchThroughGestureListener;
+
+import java.util.ArrayList;
+
+public class ContactListGestureOverlay extends Activity {
+
+ private static final String LOGTAG = "ContactListGestureOverlay";
+
+ private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
+
+ private static final String[] CONTACTS_PROJECTION = new String[] {
+ People._ID, // 0
+ People.DISPLAY_NAME, // 1
+ };
+
+ private ContactAdapter mContactAdapter;
+
+ private TouchThroughGestureListener mGestureProcessor;
+
+ private LetterRecognizer mRecognizer;
+
+ private ListView mContactList;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.overlaydemo);
+
+ setProgressBarIndeterminateVisibility(true);
+
+ // create a letter recognizer
+ mRecognizer = LetterRecognizer.getLetterRecognizer(this, LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
+
+ // load the contact list
+ mContactList = (ListView) findViewById(R.id.list);
+ registerForContextMenu(mContactList);
+ mContactList.setTextFilterEnabled(true);
+ mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+ if (!mGestureProcessor.isGesturing()) {
+ Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(
+ People.CONTENT_URI, id));
+ startActivity(intent);
+ }
+ }
+ });
+ ContentResolver resolver = getContentResolver();
+ Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null,
+ SORT_ORDER);
+ ArrayList<ContactItem> list = new ArrayList<ContactItem>();
+ while (cursor.moveToNext()) {
+ list.add(new ContactItem(cursor.getLong(0), cursor.getString(1)));
+ }
+ mContactAdapter = new ContactAdapter(this, list);
+ mContactList.setAdapter(mContactAdapter);
+
+ setProgressBarIndeterminateVisibility(false);
+
+ // add a gesture overlay on top of the ListView
+ GestureOverlayView overlay = new GestureOverlayView(this);
+ mGestureProcessor = new TouchThroughGestureListener(mContactList);
+ mGestureProcessor.setGestureType(TouchThroughGestureListener.MULTIPLE_STROKE);
+ mGestureProcessor.addOnGestureActionListener(new TouchThroughGestureListener.OnGesturePerformedListener() {
+ public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList<Prediction> predictions = mRecognizer.recognize(gesture);
+ if (!predictions.isEmpty()) {
+ Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name);
+ Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name);
+ Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name);
+ int index = mContactAdapter.search(predictions.get(0).name);
+ if (index != -1) {
+ mContactList.setSelection(index);
+ }
+ }
+ }
+ });
+ overlay.addOnGestureListener(mGestureProcessor);
+ ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
+ this.addContentView(overlay, params);
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
new file mode 100644
index 0000000..200f89f
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2008-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.gesture.example;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.gesture.Gesture;
+
+import android.gesture.GestureLibrary;
+import android.gesture.GestureOverlayView;
+import android.gesture.Prediction;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class GestureEntry extends Activity {
+
+ private static final String PARCEL_KEY = "gesture";
+
+ static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
+ + File.separator + "demo_library.gestures";
+
+ private static final int DIALOG_NEW_ENTRY = 1;
+
+ private static final int NEW_ID = Menu.FIRST;
+
+ private static final int VIEW_ID = Menu.FIRST + 1;
+
+ private GestureOverlayView mGesturePad;
+
+ private Spinner mRecognitionResult;
+
+ private GestureLibrary mGestureLibrary;
+
+ private boolean mChangedByRecognizer = false;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.demo);
+
+ // init the gesture library
+ mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
+ mGestureLibrary.load();
+
+ // create the spinner for showing the recognition results
+ // the spinner also allows a user to correct a prediction
+ mRecognitionResult = (Spinner) findViewById(R.id.spinner);
+ mRecognitionResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ // correct the recognition result by adding the new example
+ if (!mChangedByRecognizer) {
+ mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad
+ .getCurrentGesture());
+ } else {
+ mChangedByRecognizer = false;
+ }
+ }
+
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+
+ });
+
+ // create the area for drawing a gesture
+ mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
+ mGesturePad.setBackgroundColor(Color.BLACK);
+ mGesturePad.addOnGestureListener(new GestureOverlayView.OnGestureListener() {
+ public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
+ recognize(overlay.getCurrentGesture());
+ }
+
+ public void onGesture(GestureOverlayView overlay, MotionEvent event) {
+ }
+
+ public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
+ overlay.clear(false);
+ }
+ });
+
+ if (savedInstanceState != null) {
+ Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
+ if (gesture != null) {
+ mGesturePad.setCurrentGesture(gesture);
+ }
+ }
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ LayoutInflater factory = LayoutInflater.from(this);
+ final View textEntryView = factory.inflate(R.layout.newgesture_dialog, null);
+ return new AlertDialog.Builder(GestureEntry.this).setTitle(
+ R.string.newgesture_text_entry).setView(textEntryView).setPositiveButton(
+ R.string.newgesture_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ EditText edittext = (EditText) ((AlertDialog) dialog)
+ .findViewById(R.id.gesturename_edit);
+ String text = edittext.getText().toString().trim();
+ if (text.length() > 0) {
+ mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture());
+ }
+ }
+ }).setNegativeButton(R.string.newgesture_dialog_cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ }
+ }).create();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, NEW_ID, 0, R.string.newgesture).setShortcut('0', 'n').setIcon(
+ android.R.drawable.ic_menu_add);
+ menu.add(0, VIEW_ID, 0, R.string.viewgesture).setShortcut('1', 'v').setIcon(
+ android.R.drawable.ic_menu_view);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case NEW_ID:
+ if (mGesturePad.getCurrentGesture() != null) {
+ showDialog(DIALOG_NEW_ENTRY);
+ }
+ break;
+
+ case VIEW_ID:
+ startActivityForResult(new Intent(this, GestureLibViewer.class), VIEW_ID);
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mGestureLibrary.load();
+ mGesturePad.clear(false);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGestureLibrary.save();
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ Gesture gesture = mGesturePad.getCurrentGesture();
+ if (gesture != null) {
+ outState.putParcelable(PARCEL_KEY, gesture);
+ }
+ mGestureLibrary.save();
+ }
+
+ private void recognize(Gesture gesture) {
+ mChangedByRecognizer = true;
+ ArrayList<Prediction> predictions = mGestureLibrary.recognize(gesture);
+ ArrayAdapter<Prediction> adapter = new ArrayAdapter<Prediction>(this,
+ android.R.layout.simple_spinner_item, predictions);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mRecognitionResult.setAdapter(adapter);
+ }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
deleted file mode 100755
index 8fee21a..0000000
--- a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture.example;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.AdapterView.OnItemSelectedListener;
-
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureLib;
-import com.android.gesture.GestureListener;
-import com.android.gesture.GesturePad;
-import com.android.gesture.R;
-import com.android.gesture.recognizer.Prediction;
-
-import java.util.ArrayList;
-
-/**
- * The demo shows how to construct a gesture-based user interface on Android.
- */
-
-public class GestureEntryDemo extends Activity {
-
- private static final int DIALOG_NEW_ENTRY = 1;
- private static final int NEW_ID = Menu.FIRST;
- private static final int VIEW_ID = Menu.FIRST + 1;
-
- GesturePad mView;
- Spinner mResult;
- GestureLib mRecognizer;
- boolean mChangedByRecognizer = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.demo);
-
- // init the recognizer
- mRecognizer = new GestureLib("/sdcard/gestureentry");
- mRecognizer.load();
-
- // create the spinner for showing the recognition results
- // the spinner also allows a user to correct a prediction
- mResult = (Spinner) findViewById(R.id.spinner);
- mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
-
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- // TODO Auto-generated method stub
- // correct the recognition result by adding the new example
- if (mChangedByRecognizer == false) {
- mRecognizer.addGesture(parent.getSelectedItem().toString(),
- mView.getCurrentGesture());
- } else {
- mChangedByRecognizer = false;
- }
- }
-
- public void onNothingSelected(AdapterView<?> parent) {
- // TODO Auto-generated method stub
-
- }
-
- });
-
- // create the area for drawing a gesture
- mView = (GesturePad)this.findViewById(R.id.drawingpad);
- mView.cacheGesture(false);
- mView.setFadingOut(false);
- mView.addGestureListener(new GestureListener() {
- public void onFinishGesture(GesturePad patch, MotionEvent event) {
- // TODO Auto-generated method stub
- recognize(patch.getCurrentGesture());
- }
- public void onGesture(GesturePad patch, MotionEvent event) {
- // TODO Auto-generated method stub
-
- }
- public void onStartGesture(GesturePad patch, MotionEvent event) {
- // TODO Auto-generated method stub
-
- }
- });
-
-
- if (savedInstanceState != null) {
- mView.setCurrentGesture(
- (Gesture)savedInstanceState.getParcelable("gesture"));
- }
- }
-
- @Override
- protected Dialog onCreateDialog(int id) {
- // create the dialog for adding a new entry
- LayoutInflater factory = LayoutInflater.from(this);
- final View textEntryView =
- factory.inflate(R.layout.newgesture_dialog, null);
- return new AlertDialog.Builder(GestureEntryDemo.this)
- .setTitle(R.string.newgesture_text_entry)
- .setView(textEntryView)
- .setPositiveButton(R.string.newgesture_dialog_ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- /* User clicked OK so do some stuff */
- EditText edittext =
- (EditText)((AlertDialog)dialog).findViewById(R.id.gesturename_edit);
- String text = edittext.getText().toString().trim();
- if (text.length() > 0) {
- mRecognizer.addGesture(text, mView.getCurrentGesture());
- }
- }
- })
- .setNegativeButton(R.string.newgesture_dialog_cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- /* User clicked cancel so do some stuff */
- }
- })
- .create();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // TODO Auto-generated method stub
- super.onCreateOptionsMenu(menu);
- menu.add(0, NEW_ID, 0, R.string.newgesture)
- .setShortcut('0', 'n')
- .setIcon(android.R.drawable.ic_menu_add);
- menu.add(0, VIEW_ID, 0, R.string.viewgesture)
- .setShortcut('1', 'v')
- .setIcon(android.R.drawable.ic_menu_view);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle all of the possible menu actions.
- switch (item.getItemId()) {
- case NEW_ID:
- // if there has been a gesture on the canvas
- if (mView.getCurrentGesture() != null) {
- showDialog(DIALOG_NEW_ENTRY);
- }
- break;
-
- case VIEW_ID:
- startActivityForResult(
- new Intent(this, GestureLibViewer.class), VIEW_ID);
- break;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- mRecognizer.load();
- mView.clear();
- }
-
- @Override
- protected void onPause() {
- // TODO Auto-generated method stub
- super.onPause();
- mRecognizer.save();
- }
-
-
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- // TODO Auto-generated method stub
- super.onPrepareDialog(id, dialog);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- // TODO Auto-generated method stub
- super.onSaveInstanceState(outState);
- outState.putParcelable("gesture", mView.getCurrentGesture());
- mRecognizer.save();
- }
-
- public void recognize(Gesture ink) {
- mChangedByRecognizer = true;
- ArrayList<Prediction> predictions = mRecognizer.recognize(ink);
- ArrayAdapter adapter = new ArrayAdapter(this,
- android.R.layout.simple_spinner_item, predictions);
- adapter.setDropDownViewResource(
- android.R.layout.simple_spinner_dropdown_item);
- mResult.setAdapter(adapter);
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
index 7ae7fc5..aa07e7b 100755
--- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-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.
@@ -17,8 +17,6 @@
package com.android.gesture.example;
import android.app.Activity;
-import android.graphics.Matrix;
-import android.graphics.Path;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
@@ -28,230 +26,158 @@
import android.widget.Button;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;
+import android.gesture.Gesture;
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureLib;
-import com.android.gesture.GesturePad;
-import com.android.gesture.R;
-import com.android.gesture.recognizer.Instance;
+import android.gesture.GestureLibrary;
+import android.gesture.GestureOverlayView;
import java.util.ArrayList;
import java.util.Collections;
/**
- * GestureLibViewer is for viewing existing gestures and
+ * GestureLibViewer gives an example on how to browse existing gestures and
* removing unwanted gestures.
*/
-public class GestureLibViewer extends Activity {
-
- GesturePad mView;
- Spinner mResult;
- GestureLib mRecognizer;
- ArrayList<Gesture> mSamples;
- int mCurrentGestureIndex;
+public class GestureLibViewer extends Activity {
+
+ private GestureOverlayView mGesturePad;
+
+ private Spinner mGestureCategory;
+
+ private GestureLibrary mGesureLibrary;
+
+ private ArrayList<Gesture> mGestures;
+
+ private int mCurrentGestureIndex;
+
+ private class RemoveGestureListener implements OnClickListener {
+ public void onClick(View v) {
+ if (mGestures.isEmpty()) {
+ return;
+ }
+
+ String name = (String) mGestureCategory.getSelectedItem();
+ Gesture gesture = mGestures.get(mCurrentGestureIndex);
+ mGesureLibrary.removeGesture(name, gesture);
+
+ mGestures = mGesureLibrary.getGestures(name);
+
+ if (mGestures == null) {
+ // delete the entire entry
+ mCurrentGestureIndex = 0;
+ ArrayList<String> list = new ArrayList<String>();
+ list.addAll(mGesureLibrary.getGestureEntries());
+ Collections.sort(list);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(GestureLibViewer.this,
+ android.R.layout.simple_spinner_item, list);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mGestureCategory.setAdapter(adapter);
+ } else {
+ if (mCurrentGestureIndex > mGestures.size() - 1) {
+ mCurrentGestureIndex--;
+ }
+ gesture = mGestures.get(mCurrentGestureIndex);
+ mGesturePad.setCurrentGesture(gesture);
+ mGesturePad.invalidate();
+ }
+ }
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gestureviewer);
-
- // create the area for drawing a glyph
- mView = (GesturePad)this.findViewById(R.id.drawingpad);
- mView.cacheGesture(false);
- mView.setFadingOut(false);
- mView.setEnableInput(false);
-
- // init the recognizer
- mRecognizer = new GestureLib("/sdcard/gestureentry");
- mRecognizer.load();
- mResult = (Spinner) findViewById(R.id.spinner);
+ // create the area for drawing a gesture
+ mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
+ mGesturePad.setEnabled(false);
+
+ // init the gesture library
+ mGesureLibrary = new GestureLibrary(GestureEntry.GESTURE_FILE_NAME);
+ mGesureLibrary.load();
+
+ mGestureCategory = (Spinner) findViewById(R.id.spinner);
ArrayList<String> list = new ArrayList<String>();
- list.addAll(mRecognizer.getLabels());
- Collections.sort(list);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_spinner_item,
- list);
- adapter.setDropDownViewResource(
- android.R.layout.simple_spinner_dropdown_item);
- mResult.setAdapter(adapter);
- mSamples = mRecognizer.getGestures(list.get(0));
- if (mSamples.isEmpty() == false) {
+ if (!mGesureLibrary.getGestureEntries().isEmpty()) {
+ list.addAll(mGesureLibrary.getGestureEntries());
+ Collections.sort(list);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, list);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mGestureCategory.setAdapter(adapter);
+ mGestures = mGesureLibrary.getGestures(list.get(0));
mCurrentGestureIndex = 0;
- Gesture gesture = mSamples.get(mCurrentGestureIndex);
- mView.setCurrentGesture(gesture);
- mView.clearDebugPath();
- mView.addDebugPath(
- toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+ Gesture gesture = mGestures.get(mCurrentGestureIndex);
+ mGesturePad.setCurrentGesture(gesture);
}
-
- mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+ mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- // TODO Auto-generated method stub
- mSamples = mRecognizer.getGestures(
- (String)mResult.getSelectedItem());
- if (mSamples.isEmpty() == false) {
+ mGestures = mGesureLibrary.getGestures((String) mGestureCategory.getSelectedItem());
+ if (!mGestures.isEmpty()) {
mCurrentGestureIndex = 0;
- Gesture gesture = mSamples.get(mCurrentGestureIndex);
- mView.setCurrentGesture(gesture);
- mView.clearDebugPath();
- mView.addDebugPath(
- toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+ Gesture gesture = mGestures.get(mCurrentGestureIndex);
+ mGesturePad.setCurrentGesture(gesture);
}
- mView.invalidate();
+ mGesturePad.invalidate();
}
-
+
public void onNothingSelected(AdapterView<?> parent) {
- // TODO Auto-generated method stub
-
}
-
+
});
-
- Button remove = (Button)this.findViewById(R.id.remove);
- remove.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- // TODO Auto-generated method stub
- if (mSamples.isEmpty())
- return;
-
- String name = (String)mResult.getSelectedItem();
- Gesture gesture = mSamples.get(mCurrentGestureIndex);
- mRecognizer.removeGesture(name, gesture);
-
- mSamples = mRecognizer.getGestures(name);
-
- if (mSamples == null) {
- // delete the entire entry
- mCurrentGestureIndex = 0;
- ArrayList<String> list = new ArrayList<String>();
- list.addAll(mRecognizer.getLabels());
- Collections.sort(list);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(
- GestureLibViewer.this,
- android.R.layout.simple_spinner_item,
- list);
- adapter.setDropDownViewResource(
- android.R.layout.simple_spinner_dropdown_item);
- mResult.setAdapter(adapter);
- } else {
- if (mCurrentGestureIndex > mSamples.size()-1) {
- mCurrentGestureIndex--;
- }
- gesture = mSamples.get(mCurrentGestureIndex);
- mView.setCurrentGesture(gesture);
- mView.clearDebugPath();
- mView.addDebugPath(
- toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
- mView.invalidate();
- }
- }
- });
-
- Button next = (Button)this.findViewById(R.id.next);
+
+ Button remove = (Button) findViewById(R.id.remove);
+ remove.setOnClickListener(new RemoveGestureListener());
+
+ Button next = (Button) findViewById(R.id.next);
next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- // TODO Auto-generated method stub
- if (mCurrentGestureIndex >= mSamples.size()-1)
+ if (mCurrentGestureIndex >= mGestures.size() - 1) {
return;
-
+ }
mCurrentGestureIndex++;
- Gesture gesture = mSamples.get(mCurrentGestureIndex);
- mView.setCurrentGesture(gesture);
- mView.clearDebugPath();
- mView.addDebugPath(
- toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
- mView.invalidate();
+ Gesture gesture = mGestures.get(mCurrentGestureIndex);
+ mGesturePad.setCurrentGesture(gesture);
+ mGesturePad.invalidate();
}
});
- Button previous = (Button)this.findViewById(R.id.previous);
+ Button previous = (Button) findViewById(R.id.previous);
previous.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- // TODO Auto-generated method stub
- if (mCurrentGestureIndex >= 1 &&
- mSamples.isEmpty() == false) {
+ if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
mCurrentGestureIndex--;
- Gesture gesture = mSamples.get(mCurrentGestureIndex);
- mView.setCurrentGesture(gesture);
- mView.clearDebugPath();
- mView.addDebugPath(
- toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
- mView.invalidate();
+ Gesture gesture = mGestures.get(mCurrentGestureIndex);
+ mGesturePad.setCurrentGesture(gesture);
+ mGesturePad.invalidate();
}
}
});
}
-
- public static ArrayList<Path> toPath(Instance instance) {
- ArrayList<Path> paths = new ArrayList();
- Path path = null;
- float minx = 0, miny = 0;
- float mX = 0, mY = 0;
- for (int i=0; i<instance.vector.length; i+=2) {
- float x = instance.vector[i];
- float y = instance.vector[i+1];
- if (x < minx)
- minx = x;
- if (y < miny)
- miny = y;
- if (path == null) {
- path = new Path();
- path.moveTo(x, y);
- mX = x;
- mY = y;
- } else {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= 3 || dy >= 3) {
- path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
- mX = x;
- mY = y;
- }
- }
- }
- Matrix matrix = new Matrix();
- matrix.setTranslate(-minx + 10, -miny + 10);
- path.transform(matrix);
- paths.add(path);
-
- path = new Path();
- path.moveTo(instance.vector[0]-5, instance.vector[1]-5);
- path.lineTo(instance.vector[0]-5, instance.vector[1]+5);
- path.lineTo(instance.vector[0]+5, instance.vector[1]+5);
- path.lineTo(instance.vector[0]+5, instance.vector[1]-5);
- path.close();
- path.transform(matrix);
- paths.add(path);
-
- return paths;
- }
-
+
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
- // TODO Auto-generated method stub
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- mRecognizer.save();
- this.setResult(RESULT_OK);
- finish();
- return true;
- }
- else
- return false;
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ mGesureLibrary.save();
+ setResult(RESULT_OK);
+ finish();
+ return true;
+ } else {
+ return false;
+ }
}
-
+
@Override
protected void onPause() {
- // TODO Auto-generated method stub
super.onPause();
- mRecognizer.save();
+ mGesureLibrary.save();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
- // TODO Auto-generated method stub
super.onSaveInstanceState(outState);
- mRecognizer.save();
+ mGesureLibrary.save();
}
}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java b/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
deleted file mode 100755
index 584e0a5..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture.recognizer;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * The abstract class of Classifier
- */
-public abstract class Classifier {
-
- HashMap<Long, Instance> mInstances = new HashMap<Long, Instance>();
-
- public void addInstance(Instance instance) {
- mInstances.put(instance.id, instance);
- }
-
- public Instance getInstance(long id) {
- return mInstances.get(id);
- }
-
- public void removeInstance(long id) {
- mInstances.remove(id);
- }
-
- public abstract ArrayList<Prediction> classify(Instance instance);
-}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Instance.java b/tests/sketch/src/com/android/gesture/recognizer/Instance.java
deleted file mode 100755
index 2eaa1c2..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/Instance.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture.recognizer;
-
-import android.graphics.PointF;
-
-import com.android.gesture.Gesture;
-
-/**
- * An instance represents a sample if the label is available or a query if
- * the label is null.
- */
-public class Instance {
-
- private final static float[] targetOrientations = {
- 0, 45, 90, 135, 180, -0, -45, -90, -135, -180
- };
-
- // the feature vector
- public final float[] vector;
- // the label can be null
- public final String label;
- // the length of the vector
- public final float length;
- // the id of the instance
- public final long id;
-
- Instance(long d, float[] v, String l) {
- id = d;
- vector = v;
- label = l;
- float sum = 0;
- for (int i = 0; i < vector.length; i++) {
- sum += vector[i] * vector[i];
- }
- length = (float)Math.sqrt(sum);
- }
-
- public static Instance createInstance(Gesture gesture, String label) {
- float[] pts = RecognitionUtil.resample(gesture, 64);
- PointF center = RecognitionUtil.computeCentroid(pts);
- float inductiveOrientation = (float)Math.atan2(pts[1] - center.y,
- pts[0] - center.x);
- inductiveOrientation *= 180 / Math.PI;
-
- float minDeviation = Float.MAX_VALUE;
- for (int i=0; i<targetOrientations.length; i++) {
- float delta = targetOrientations[i] - inductiveOrientation;
- if (Math.abs(delta) < Math.abs(minDeviation)) {
- minDeviation = delta;
- }
- }
-
- android.graphics.Matrix m = new android.graphics.Matrix();
- m.setTranslate(-center.x, -center.y);
- android.graphics.Matrix rotation = new android.graphics.Matrix();
- rotation.setRotate(minDeviation);
- m.postConcat(rotation);
- m.mapPoints(pts);
-
- return new Instance(gesture.getID(), pts, label);
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java b/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java
deleted file mode 100755
index cb8a9d3..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture.recognizer;
-
-import android.util.Log;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.TreeMap;
-
-public class NearestNeighbor extends Classifier {
-
- private static final String LOGTAG = "NearestNeighbor";
- private static final double variance = 0.25; // std = 0.5
-
- public ArrayList<Prediction> classify(Instance instance) {
-
- ArrayList<Prediction> list = new ArrayList<Prediction>();
- Iterator<Instance> it = mInstances.values().iterator();
- Log.v(LOGTAG, mInstances.size() + " instances found");
- TreeMap<String, Double> label2score = new TreeMap<String, Double>();
- while (it.hasNext()) {
- Instance sample = it.next();
- double dis = RecognitionUtil.cosineDistance(sample, instance);
- double weight = Math.exp(-dis*dis/(2 * variance));
- Log.v(LOGTAG, sample.label + " = " + dis + " weight = " + weight);
- Double score = label2score.get(sample.label);
- if (score == null) {
- score = weight;
- }
- else {
- score += weight;
- }
- label2score.put(sample.label, score);
- }
-
- double sum = 0;
- Iterator it2 = label2score.keySet().iterator();
- while (it2.hasNext()) {
- String name = (String)it2.next();
- double score = label2score.get(name);
- sum += score;
- list.add(new Prediction(name, score));
- }
-
- it2 = list.iterator();
- while (it2.hasNext()) {
- Prediction name = (Prediction)it2.next();
- name.score /= sum;
- }
-
-
- Collections.sort(list, new Comparator<Prediction>() {
- public int compare(Prediction object1, Prediction object2) {
- // TODO Auto-generated method stub
- double score1 = object1.score;
- double score2 = object2.score;
- if (score1 > score2)
- return -1;
- else if (score1 < score2)
- return 1;
- else
- return 0;
- }
- });
-
- it2 = list.iterator();
- while (it2.hasNext()) {
- Prediction name = (Prediction)it2.next();
- Log.v(LOGTAG, "prediction [" + name.label + " = " + name.score + "]");
- }
-
- return list;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
deleted file mode 100755
index c318754..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.gesture.recognizer;
-
-/**
- *
- * A recognition result that includes the label and its score
- */
-public class Prediction {
- public final String label;
- public double score;
-
- public Prediction(String l, double s) {
- label = l;
- score = s;
- }
-
- @Override
- public String toString() {
- return label;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java b/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
deleted file mode 100755
index 9146b95..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2008-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.gesture.recognizer;
-
-import android.graphics.PointF;
-
-import com.android.gesture.Gesture;
-
-import java.util.Iterator;
-
-/**
- *
- * Utilities for recognition.
- */
-
-public class RecognitionUtil {
-
- /**
- * Re-sample a list of points to a given number
- * @param stk
- * @param num
- * @return
- */
- public static float[] resample(Gesture gesture, int num) {
- final float increment = gesture.getLength()/(num - 1);
- float[] newstk = new float[num*2];
- float distanceSoFar = 0;
- Iterator<PointF> it = gesture.getPoints().iterator();
- PointF lstPoint = it.next();
- int index = 0;
- PointF currentPoint = null;
- try
- {
- newstk[index] = lstPoint.x;
- index++;
- newstk[index] = lstPoint.y;
- index++;
- while (it.hasNext()) {
- if (currentPoint == null)
- currentPoint = it.next();
- float deltaX = currentPoint.x - lstPoint.x;
- float deltaY = currentPoint.y - lstPoint.y;
- float distance = (float)Math.sqrt(deltaX*deltaX+deltaY*deltaY);
- if (distanceSoFar+distance >= increment) {
- float ratio = (increment - distanceSoFar) / distance;
- float nx = lstPoint.x + ratio * deltaX;
- float ny = lstPoint.y + ratio * deltaY;
- newstk[index] = nx;
- index++;
- newstk[index] = ny;
- index++;
- lstPoint = new PointF(nx, ny);
- distanceSoFar = 0;
- }
- else {
- lstPoint = currentPoint;
- currentPoint = null;
- distanceSoFar += distance;
- }
- }
- }
- catch(Exception ex) {
- ex.printStackTrace();
- }
-
- for(int i = index; i < newstk.length -1; i+=2) {
- newstk[i] = lstPoint.x;
- newstk[i+1] = lstPoint.y;
- }
- return newstk;
- }
-
- /**
- * Calculate the centroid of a list of points
- * @param points
- * @return the centroid
- */
- public static PointF computeCentroid(float[] points) {
- float centerX = 0;
- float centerY = 0;
- for(int i=0; i<points.length; i++)
- {
- centerX += points[i];
- i++;
- centerY += points[i];
- }
- centerX = 2 * centerX/points.length;
- centerY = 2 * centerY/points.length;
- return new PointF(centerX, centerY);
- }
-
- /**
- * calculate the variance-covariance matrix, treat each point as a sample
- * @param points
- * @return
- */
- public static double[][] computeCoVariance(float[] points) {
- double[][] array = new double[2][2];
- array[0][0] = 0;
- array[0][1] = 0;
- array[1][0] = 0;
- array[1][1] = 0;
- for(int i=0; i<points.length; i++)
- {
- float x = points[i];
- i++;
- float y = points[i];
- array[0][0] += x * x;
- array[0][1] += x * y;
- array[1][0] = array[0][1];
- array[1][1] += y * y;
- }
- array[0][0] /= (points.length/2);
- array[0][1] /= (points.length/2);
- array[1][0] /= (points.length/2);
- array[1][1] /= (points.length/2);
-
- return array;
- }
-
-
- public static float computeTotalLength(float[] points) {
- float sum = 0;
- for (int i=0; i<points.length - 4; i+=2) {
- float dx = points[i+2] - points[i];
- float dy = points[i+3] - points[i+1];
- sum += Math.sqrt(dx*dx + dy*dy);
- }
- return sum;
- }
-
- public static double computeStraightness(float[] points) {
- float totalLen = computeTotalLength(points);
- float dx = points[2] - points[0];
- float dy = points[3] - points[1];
- return Math.sqrt(dx*dx + dy*dy) / totalLen;
- }
-
- public static double computeStraightness(float[] points, float totalLen) {
- float dx = points[2] - points[0];
- float dy = points[3] - points[1];
- return Math.sqrt(dx*dx + dy*dy) / totalLen;
- }
-
- public static double averageEuclidDistance(float[] stk1, float[] stk2) {
- double distance = 0;
- for (int i = 0; i < stk1.length; i += 2) {
- distance += PointF.length(stk1[i] - stk2[i], stk1[i+1] - stk2[i+1]);
- }
- return distance/stk1.length;
- }
-
- public static double squaredEuclidDistance(float[] stk1, float[] stk2) {
- double squaredDistance = 0;
- for (int i = 0; i < stk1.length; i++) {
- float difference = stk1[i] - stk2[i];
- squaredDistance += difference * difference;
- }
- return squaredDistance/stk1.length;
- }
-
- /**
- * Calculate the cosine distance between two instances
- * @param in1
- * @param in2
- * @return the angle between 0 and Math.PI
- */
- public static double cosineDistance(Instance in1, Instance in2) {
- float sum = 0;
- for (int i = 0; i < in1.vector.length; i++) {
- sum += in1.vector[i] * in2.vector[i];
- }
- return Math.acos(sum / (in1.length * in2.length));
- }
-
-}
diff --git a/tests/sketch/tools/Converter.java b/tests/sketch/tools/Converter.java
new file mode 100644
index 0000000..c0391d8
--- /dev/null
+++ b/tests/sketch/tools/Converter.java
@@ -0,0 +1,224 @@
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Closeable;
+import java.io.DataOutputStream;
+import java.io.FileOutputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+
+/**
+ * Converts text-based letter stores to binary-based stores.
+ */
+public class Converter {
+ private final File mFile;
+ private static final short VERSION_NUMBER = 1;
+
+ Converter(File file) {
+ mFile = file;
+ }
+
+ private void convert() {
+ boolean read = false;
+
+ String[] classes = null;
+ int iCount = 0;
+ int hCount = 0;
+ int oCount = 0;
+ float[][] iWeights = null;
+ float[][] oWeights = null;
+
+ BufferedReader reader = null;
+
+ try {
+ reader = new BufferedReader(new FileReader(mFile));
+
+ long start = System.nanoTime();
+
+ String line = reader.readLine();
+ int startIndex = 0;
+ int endIndex;
+ endIndex = line.indexOf(" ", startIndex);
+ iCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ startIndex = endIndex + 1;
+ endIndex = line.indexOf(" ", startIndex);
+ hCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ startIndex = endIndex + 1;
+ endIndex = line.length();
+ oCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ classes = new String[oCount];
+ line = reader.readLine();
+ startIndex = 0;
+
+ for (int i = 0; i < oCount; i++) {
+ endIndex = line.indexOf(" ", startIndex);
+ classes[i] = line.substring(startIndex, endIndex);
+ startIndex = endIndex + 1;
+ }
+
+ iWeights = new float[hCount][];
+ for (int i = 0; i < hCount; i++) {
+ iWeights[i] = new float[iCount + 1];
+ line = reader.readLine();
+ startIndex = 0;
+ for (int j = 0; j <= iCount; j++) {
+ endIndex = line.indexOf(" ", startIndex);
+ iWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+ }
+
+ oWeights = new float[oCount][];
+ for (int i = 0; i < oCount; i++) {
+ oWeights[i] = new float[hCount + 1];
+ line = reader.readLine();
+ startIndex = 0;
+ for (int j = 0; j <= hCount; j++) {
+ endIndex = line.indexOf(" ", startIndex);
+ oWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+ }
+
+ long end = System.nanoTime();
+ System.out.println("time to read text file = " +
+ ((end - start) / 1000.0f / 1000.0f) + " ms");
+
+ read = true;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ close(reader);
+ }
+
+ if (read) {
+ boolean wrote = false;
+ DataOutputStream out = null;
+
+ try {
+ out = new DataOutputStream(new FileOutputStream(mFile));
+
+ out.writeShort(VERSION_NUMBER);
+ out.writeInt(iCount);
+ out.writeInt(hCount);
+ out.writeInt(oCount);
+
+ for (String aClass : classes) {
+ out.writeUTF(aClass);
+ }
+
+ for (float[] weights : iWeights) {
+ for (float weight : weights) {
+ out.writeFloat(weight);
+ }
+ }
+
+ for (float[] weights : oWeights) {
+ for (float weight : weights) {
+ out.writeFloat(weight);
+ }
+ }
+
+ out.flush();
+
+ wrote = true;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ close(out);
+ }
+
+ if (wrote) {
+ DataInputStream in = null;
+
+ try {
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(mFile)));
+
+ long start = System.nanoTime();
+
+ iCount = in.readInt();
+ hCount = in.readInt();
+ oCount = in.readInt();
+
+ classes = new String[oCount];
+ for (int i = 0; i < classes.length; i++) {
+ classes[i] = in.readUTF();
+ }
+
+ iWeights = new float[hCount][];
+ for (int i = 0; i < iWeights.length; i++) {
+ iWeights[i] = new float[iCount];
+ for (int j = 0; j < iCount; j++) {
+ iWeights[i][j] = in.readFloat();
+ }
+ }
+
+ oWeights = new float[oCount][];
+ for (int i = 0; i < oWeights.length; i++) {
+ oWeights[i] = new float[hCount];
+ for (int j = 0; j < hCount; j++) {
+ oWeights[i][j] = in.readFloat();
+ }
+ }
+
+ long end = System.nanoTime();
+ System.out.println("time to read binary file = " +
+ ((end - start) / 1000.0f / 1000.0f) + " ms");
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ close(in);
+ }
+ }
+ }
+ }
+
+ private static void close(Closeable reader) {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ String fileName = args[0];
+ if (fileName != null) {
+ File file = new File(fileName);
+ if (!file.exists()) {
+ printHelp(fileName);
+ } else {
+ new Converter(file).convert();
+ }
+ } else {
+ printHelp(null);
+ }
+ }
+
+ private static void printHelp(String name) {
+ if (name == null) {
+ System.out.println("You must specify the name of the file to convert:");
+ } else {
+ System.out.println("The specified file does not exist: " + name);
+ }
+ System.out.println("java Converter [filename]");
+ System.out.println("");
+ System.out.println("\t[filename]\tPath to the file to convert. The file is replaced by "
+ + "the conversion result.");
+ }
+}
\ No newline at end of file
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 2d8471b..2eb7a1d 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -38,6 +38,8 @@
mAssetSourceDir(NULL),
mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
mRClassDir(NULL), mResourceIntermediatesDir(NULL),
+ mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
+ mVersionCode(NULL), mVersionName(NULL),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
@@ -99,6 +101,17 @@
const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; }
void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); }
+ const char* getMinSdkVersion() const { return mMinSdkVersion; }
+ void setMinSdkVersion(const char* val) { mMinSdkVersion = val; }
+ const char* getTargetSdkVersion() const { return mTargetSdkVersion; }
+ void setTargetSdkVersion(const char* val) { mTargetSdkVersion = val; }
+ const char* getMaxSdkVersion() const { return mMaxSdkVersion; }
+ void setMaxSdkVersion(const char* val) { mMaxSdkVersion = val; }
+ const char* getVersionCode() const { return mVersionCode; }
+ void setVersionCode(const char* val) { mVersionCode = val; }
+ const char* getVersionName() const { return mVersionName; }
+ void setVersionName(const char* val) { mVersionName = val; }
+
/*
* Set and get the file specification.
*
@@ -151,6 +164,12 @@
android::Vector<const char*> mNoCompressExtensions;
android::Vector<const char*> mResourceSourceDirs;
+ const char* mMinSdkVersion;
+ const char* mTargetSdkVersion;
+ const char* mMaxSdkVersion;
+ const char* mVersionCode;
+ const char* mVersionName;
+
/* file specification */
int mArgc;
char* const* mArgv;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 6f3461d..dc91a48 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -268,17 +268,19 @@
return str ? String8(str, len) : String8();
}
-static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
+static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
+ String8* outError, int32_t defValue = -1)
{
ssize_t idx = indexOfAttribute(tree, attrRes);
if (idx < 0) {
- return -1;
+ return defValue;
}
Res_value value;
if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType != Res_value::TYPE_INT_DEC) {
+ if (value.dataType < Res_value::TYPE_FIRST_INT
+ || value.dataType > Res_value::TYPE_LAST_INT) {
if (outError != NULL) *outError = "attribute is not an integer value";
- return -1;
+ return defValue;
}
}
return value.data;
@@ -318,7 +320,15 @@
VERSION_NAME_ATTR = 0x0101021c,
LABEL_ATTR = 0x01010001,
ICON_ATTR = 0x01010002,
- MIN_SDK_VERSION_ATTR = 0x0101020c
+ MIN_SDK_VERSION_ATTR = 0x0101020c,
+ REQ_TOUCH_SCREEN_ATTR = 0x01010227,
+ REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
+ REQ_HARD_KEYBOARD_ATTR = 0x01010229,
+ REQ_NAVIGATION_ATTR = 0x0101022a,
+ REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
+ TARGET_SDK_VERSION_ATTR = 0x01010270,
+ TEST_ONLY_ATTR = 0x01010272,
+ DENSITY_ATTR = 0x0101026c,
};
const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -357,7 +367,8 @@
const char* filename = bundle->getFileSpecEntry(1);
AssetManager assets;
- if (!assets.addAssetPath(String8(filename), NULL)) {
+ void* assetsCookie;
+ if (!assets.addAssetPath(String8(filename), &assetsCookie)) {
fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n");
return 1;
}
@@ -543,15 +554,77 @@
goto bail;
}
printf("icon='%s'\n", icon.string());
- } else if (tag == "uses-sdk") {
- int32_t sdkVersion = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
+ int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
goto bail;
}
- if (sdkVersion != -1) {
- printf("sdkVersion:'%d'\n", sdkVersion);
+ if (testOnly != 0) {
+ printf("testOnly='%d'\n", testOnly);
}
+ } else if (tag == "uses-sdk") {
+ int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
+ if (error != "") {
+ error = "";
+ String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
+ printf("sdkVersion:'%s'\n", name.string());
+ } else if (code != -1) {
+ printf("sdkVersion:'%d'\n", code);
+ }
+ code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
+ if (error != "") {
+ error = "";
+ String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
+ printf("targetSdkVersion:'%s'\n", name.string());
+ } else if (code != -1) {
+ printf("targetSdkVersion:'%d'\n", code);
+ }
+ } else if (tag == "uses-configuration") {
+ int32_t reqTouchScreen = getIntegerAttribute(tree,
+ REQ_TOUCH_SCREEN_ATTR, NULL, 0);
+ int32_t reqKeyboardType = getIntegerAttribute(tree,
+ REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
+ int32_t reqHardKeyboard = getIntegerAttribute(tree,
+ REQ_HARD_KEYBOARD_ATTR, NULL, 0);
+ int32_t reqNavigation = getIntegerAttribute(tree,
+ REQ_NAVIGATION_ATTR, NULL, 0);
+ int32_t reqFiveWayNav = getIntegerAttribute(tree,
+ REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
+ printf("uses-configuation:");
+ if (reqTouchScreen != 0) {
+ printf(" reqTouchScreen='%d'", reqTouchScreen);
+ }
+ if (reqKeyboardType != 0) {
+ printf(" reqKeyboardType='%d'", reqKeyboardType);
+ }
+ if (reqHardKeyboard != 0) {
+ printf(" reqHardKeyboard='%d'", reqHardKeyboard);
+ }
+ if (reqNavigation != 0) {
+ printf(" reqNavigation='%d'", reqNavigation);
+ }
+ if (reqFiveWayNav != 0) {
+ printf(" reqFiveWayNav='%d'", reqFiveWayNav);
+ }
+ printf("\n");
+ } else if (tag == "supports-density") {
+ int32_t dens = getIntegerAttribute(tree, DENSITY_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:density' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
+ printf("supports-density:'%d'\n", dens);
}
} else if (depth == 3 && withinApplication) {
withinActivity = false;
@@ -592,18 +665,18 @@
}
}
} else if (depth == 5) {
- if (withinActivity) {
- if (tag == "action") {
- //printf("LOG: action tag\n");
- String8 action = getAttribute(tree, NAME_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
- goto bail;
- }
- if (action == "android.intent.action.MAIN") {
- isMainActivity = true;
- //printf("LOG: isMainActivity==true\n");
- }
+ if (withinActivity) {
+ if (tag == "action") {
+ //printf("LOG: action tag\n");
+ String8 action = getAttribute(tree, NAME_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
+ goto bail;
+ }
+ if (action == "android.intent.action.MAIN") {
+ isMainActivity = true;
+ //printf("LOG: isMainActivity==true\n");
+ }
} else if (tag == "category") {
String8 category = getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
@@ -671,6 +744,17 @@
printf(" '%s'", localeStr);
}
printf("\n");
+ AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib");
+ if (dir != NULL) {
+ if (dir->getFileCount() > 0) {
+ printf("native-code:");
+ for (size_t i=0; i<dir->getFileCount(); i++) {
+ printf(" '%s'", dir->getFileName(i).string());
+ }
+ printf("\n");
+ }
+ delete dir;
+ }
} else if (strcmp("configurations", option) == 0) {
Vector<ResTable_config> configs;
res.getConfigurations(&configs);
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 71b1a3c..8bf2b07 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -54,9 +54,10 @@
" xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName);
fprintf(stderr,
" %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n"
- " [-0 extension [-0 extension ...]] \\\n"
- " [-g tolerance] \\\n"
- " [-j jarfile] \\\n"
+ " [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n"
+ " [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n"
+ " [--max-sdk-version VAL] [--app-version VAL] \\\n"
+ " [--app-version-name TEXT] \\\n"
" [-I base-package [-I base-package ...]] \\\n"
" [-A asset-source-dir] [-P public-definitions-file] \\\n"
" [-S resource-sources [-S resource-sources ...]] "
@@ -115,7 +116,17 @@
" and the first match found (left to right) will take precedence."
" -0 specifies an additional extension for which such files will not\n"
" be stored compressed in the .apk. An empty string means to not\n"
- " compress any files at all.\n");
+ " compress any files at all.\n"
+ " --min-sdk-version\n"
+ " inserts android:minSdkVersion in to manifest.\n"
+ " --target-sdk-version\n"
+ " inserts android:targetSdkVersion in to manifest.\n"
+ " --max-sdk-version\n"
+ " inserts android:maxSdkVersion in to manifest.\n"
+ " --version-code\n"
+ " inserts android:versionCode in to manifest.\n"
+ " --version-name\n"
+ " inserts android:versionName in to manifest.\n");
}
/*
@@ -339,6 +350,59 @@
bundle.setCompressionMethod(ZipEntry::kCompressStored);
}
break;
+ case '-':
+ if (strcmp(cp, "-min-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--min-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setMinSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-target-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--target-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setTargetSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-max-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--max-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setMaxSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-version-code") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--version-code' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setVersionCode(argv[0]);
+ } else if (strcmp(cp, "-version-name") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--version-name' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setVersionName(argv[0]);
+ } else {
+ fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
+ wantUsage = true;
+ goto bail;
+ }
+ cp += strlen(cp) - 1;
+ break;
default:
fprintf(stderr, "ERROR: Unknown flag '-%c'\n", *cp);
wantUsage = true;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2e4d0a4..76b9d0a 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -488,6 +488,58 @@
return;
}
+void addTagAttribute(const sp<XMLNode>& node, const char* ns8,
+ const char* attr8, const char* value)
+{
+ if (value == NULL) {
+ return;
+ }
+
+ const String16 ns(ns8);
+ const String16 attr(attr8);
+
+ if (node->getAttribute(ns, attr) != NULL) {
+ fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s)\n",
+ String8(attr).string(), String8(ns).string());
+ return;
+ }
+
+ node->addAttribute(ns, attr, String16(value));
+}
+
+status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
+{
+ root = root->searchElement(String16(), String16("manifest"));
+ if (root == NULL) {
+ fprintf(stderr, "No <manifest> tag.\n");
+ return UNKNOWN_ERROR;
+ }
+
+ addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
+ bundle->getVersionCode());
+ addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
+ bundle->getVersionName());
+
+ if (bundle->getMinSdkVersion() != NULL
+ || bundle->getTargetSdkVersion() != NULL
+ || bundle->getMaxSdkVersion() != NULL) {
+ sp<XMLNode> vers = root->getChildElement(String16(), String16("uses-sdk"));
+ if (vers == NULL) {
+ vers = XMLNode::newElement(root->getFilename(), String16(), String16("uses-sdk"));
+ root->insertChildAt(vers, 0);
+ }
+
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion",
+ bundle->getMinSdkVersion());
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion",
+ bundle->getTargetSdkVersion());
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
+ bundle->getMaxSdkVersion());
+ }
+
+ return NO_ERROR;
+}
+
#define ASSIGN_IT(n) \
do { \
ssize_t index = resources->indexOfKey(String8(#n)); \
@@ -1006,7 +1058,15 @@
// Generate final compiled manifest file.
manifestFile->clearData();
- err = compileXmlFile(assets, manifestFile, &table);
+ sp<XMLNode> manifestTree = XMLNode::parse(manifestFile);
+ if (manifestTree == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ err = massageManifest(bundle, manifestTree);
+ if (err < NO_ERROR) {
+ return err;
+ }
+ err = compileXmlFile(assets, manifestTree, manifestFile, &table);
if (err < NO_ERROR) {
return err;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ef11a83..66607a3 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -23,6 +23,16 @@
if (root == NULL) {
return UNKNOWN_ERROR;
}
+
+ return compileXmlFile(assets, root, target, table, options);
+}
+
+status_t compileXmlFile(const sp<AaptAssets>& assets,
+ const sp<XMLNode>& root,
+ const sp<AaptFile>& target,
+ ResourceTable* table,
+ int options)
+{
if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
root->removeWhitespace(true, NULL);
} else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
@@ -651,6 +661,7 @@
const String16 string_array16("string-array");
const String16 integer_array16("integer-array");
const String16 public16("public");
+ const String16 public_padding16("public-padding");
const String16 private_symbols16("private-symbols");
const String16 skip16("skip");
const String16 eat_comment16("eat-comment");
@@ -685,7 +696,7 @@
bool hasErrors = false;
- uint32_t nextPublicId = 0;
+ DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
ResXMLTree::event_code_t code;
do {
@@ -774,15 +785,15 @@
hasErrors = localHasErrors = true;
} else {
ident = identValue.data;
- nextPublicId = ident+1;
+ nextPublicId.replaceValueFor(type, ident+1);
}
- } else if (nextPublicId == 0) {
+ } else if (nextPublicId.indexOfKey(type) < 0) {
srcPos.error("No 'id' attribute supplied <public>,"
" and no previous id defined in this file.\n");
hasErrors = localHasErrors = true;
} else if (!localHasErrors) {
- ident = nextPublicId;
- nextPublicId++;
+ ident = nextPublicId.valueFor(type);
+ nextPublicId.replaceValueFor(type, ident+1);
}
if (!localHasErrors) {
@@ -816,6 +827,116 @@
}
continue;
+ } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
+ SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+
+ String16 type;
+ ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
+ if (typeIdx < 0) {
+ srcPos.error("A 'type' attribute is required for <public-padding>\n");
+ hasErrors = localHasErrors = true;
+ }
+ type = String16(block.getAttributeStringValue(typeIdx, &len));
+
+ String16 name;
+ ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+ if (nameIdx < 0) {
+ srcPos.error("A 'name' attribute is required for <public-padding>\n");
+ hasErrors = localHasErrors = true;
+ }
+ name = String16(block.getAttributeStringValue(nameIdx, &len));
+
+ uint32_t start = 0;
+ ssize_t startIdx = block.indexOfAttribute(NULL, "start");
+ if (startIdx >= 0) {
+ const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
+ Res_value startValue;
+ if (!ResTable::stringToInt(startStr, len, &startValue)) {
+ srcPos.error("Given 'start' attribute is not an integer: %s\n",
+ String8(block.getAttributeStringValue(startIdx, &len)).string());
+ hasErrors = localHasErrors = true;
+ } else {
+ start = startValue.data;
+ }
+ } else if (nextPublicId.indexOfKey(type) < 0) {
+ srcPos.error("No 'start' attribute supplied <public-padding>,"
+ " and no previous id defined in this file.\n");
+ hasErrors = localHasErrors = true;
+ } else if (!localHasErrors) {
+ start = nextPublicId.valueFor(type);
+ }
+
+ uint32_t end = 0;
+ ssize_t endIdx = block.indexOfAttribute(NULL, "end");
+ if (endIdx >= 0) {
+ const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
+ Res_value endValue;
+ if (!ResTable::stringToInt(endStr, len, &endValue)) {
+ srcPos.error("Given 'end' attribute is not an integer: %s\n",
+ String8(block.getAttributeStringValue(endIdx, &len)).string());
+ hasErrors = localHasErrors = true;
+ } else {
+ end = endValue.data;
+ }
+ } else {
+ srcPos.error("No 'end' attribute supplied <public-padding>\n");
+ hasErrors = localHasErrors = true;
+ }
+
+ if (end >= start) {
+ nextPublicId.replaceValueFor(type, end+1);
+ } else {
+ srcPos.error("Padding start '%ul' is after end '%ul'\n",
+ start, end);
+ hasErrors = localHasErrors = true;
+ }
+
+ String16 comment(
+ block.getComment(&len) ? block.getComment(&len) : nulStr);
+ for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
+ if (localHasErrors) {
+ break;
+ }
+ String16 curName(name);
+ char buf[64];
+ sprintf(buf, "%d", (int)(end-curIdent+1));
+ curName.append(String16(buf));
+
+ err = outTable->addEntry(srcPos, myPackage, type, curName,
+ String16("padding"), NULL, &curParams, false,
+ ResTable_map::TYPE_STRING, overwrite);
+ if (err < NO_ERROR) {
+ hasErrors = localHasErrors = true;
+ break;
+ }
+ err = outTable->addPublic(srcPos, myPackage, type,
+ curName, curIdent);
+ if (err < NO_ERROR) {
+ hasErrors = localHasErrors = true;
+ break;
+ }
+ sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
+ if (symbols != NULL) {
+ symbols = symbols->addNestedSymbol(String8(type), srcPos);
+ }
+ if (symbols != NULL) {
+ symbols->makeSymbolPublic(String8(curName), srcPos);
+ symbols->appendComment(String8(curName), comment, srcPos);
+ } else {
+ srcPos.error("Unable to create symbols!\n");
+ hasErrors = localHasErrors = true;
+ }
+ }
+
+ while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code == ResXMLTree::END_TAG) {
+ if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
+ break;
+ }
+ }
+ }
+ continue;
+
} else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
String16 pkg;
ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
@@ -1307,7 +1428,7 @@
} else if (id != 0) {
if (id == 127) {
if (mHaveAppPackage) {
- fprintf(stderr, "Included resource have two application packages!\n");
+ fprintf(stderr, "Included resources have two application packages!\n");
return UNKNOWN_ERROR;
}
mHaveAppPackage = true;
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 74ba326..665232b 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -15,6 +15,7 @@
using namespace std;
+class XMLNode;
class ResourceTable;
enum {
@@ -34,6 +35,12 @@
ResourceTable* table,
int options = XML_COMPILE_STANDARD_RESOURCE);
+status_t compileXmlFile(const sp<AaptAssets>& assets,
+ const sp<XMLNode>& xmlTree,
+ const sp<AaptFile>& target,
+ ResourceTable* table,
+ int options = XML_COMPILE_STANDARD_RESOURCE);
+
status_t compileResourceFile(Bundle* bundle,
const sp<AaptAssets>& assets,
const sp<AaptFile>& in,
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 50a2185..832ba6c 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -525,12 +525,30 @@
return mChildren;
}
+const String8& XMLNode::getFilename() const
+{
+ return mFilename;
+}
+
const Vector<XMLNode::attribute_entry>&
XMLNode::getAttributes() const
{
return mAttributes;
}
+const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
+ const String16& name) const
+{
+ for (size_t i=0; i<mAttributes.size(); i++) {
+ const attribute_entry& ae(mAttributes.itemAt(i));
+ if (ae.ns == ns && ae.name == name) {
+ return &ae;
+ }
+ }
+
+ return NULL;
+}
+
const String16& XMLNode::getCData() const
{
return mChars;
@@ -551,6 +569,38 @@
return mEndLineNumber;
}
+sp<XMLNode> XMLNode::searchElement(const String16& tagNamespace, const String16& tagName)
+{
+ if (getType() == XMLNode::TYPE_ELEMENT
+ && mNamespaceUri == tagNamespace
+ && mElementName == tagName) {
+ return this;
+ }
+
+ for (size_t i=0; i<mChildren.size(); i++) {
+ sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
+ if (found != NULL) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+sp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName)
+{
+ for (size_t i=0; i<mChildren.size(); i++) {
+ sp<XMLNode> child = mChildren.itemAt(i);
+ if (child->getType() == XMLNode::TYPE_ELEMENT
+ && child->mNamespaceUri == tagNamespace
+ && child->mElementName == tagName) {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
status_t XMLNode::addChild(const sp<XMLNode>& child)
{
if (getType() == TYPE_CDATA) {
@@ -562,6 +612,17 @@
return NO_ERROR;
}
+status_t XMLNode::insertChildAt(const sp<XMLNode>& child, size_t index)
+{
+ if (getType() == TYPE_CDATA) {
+ SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node.");
+ return UNKNOWN_ERROR;
+ }
+ //printf("Adding child %p to parent %p\n", child.get(), this);
+ mChildren.insertAt(child, index);
+ return NO_ERROR;
+}
+
status_t XMLNode::addAttribute(const String16& ns, const String16& name,
const String16& value)
{
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 86548a2..a9bea43 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -68,6 +68,8 @@
const String16& getElementName() const;
const Vector<sp<XMLNode> >& getChildren() const;
+ const String8& getFilename() const;
+
struct attribute_entry {
attribute_entry() : index(~(uint32_t)0), nameResId(0)
{
@@ -91,6 +93,8 @@
const Vector<attribute_entry>& getAttributes() const;
+ const attribute_entry* getAttribute(const String16& ns, const String16& name) const;
+
const String16& getCData() const;
const String16& getComment() const;
@@ -98,8 +102,14 @@
int32_t getStartLineNumber() const;
int32_t getEndLineNumber() const;
+ sp<XMLNode> searchElement(const String16& tagNamespace, const String16& tagName);
+
+ sp<XMLNode> getChildElement(const String16& tagNamespace, const String16& tagName);
+
status_t addChild(const sp<XMLNode>& child);
+ status_t insertChildAt(const sp<XMLNode>& child, size_t index);
+
status_t addAttribute(const String16& ns, const String16& name,
const String16& value);
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 00829d6..7c3af69 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -70,10 +70,10 @@
boolean releaseWifiLock(IBinder lock);
- boolean isWifiMulticastEnabled();
+ boolean isMulticastEnabled();
- void enableWifiMulticast(IBinder binder, String tag);
+ void enableMulticast(IBinder binder, String tag);
- void disableWifiMulticast();
+ void disableMulticast();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 658a7b2..1a7caef 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -831,9 +831,9 @@
*
* @hide pending API council approval
*/
- public boolean isWifiMulticastEnabled() {
+ public boolean isMulticastEnabled() {
try {
- return mService.isWifiMulticastEnabled();
+ return mService.isMulticastEnabled();
} catch (RemoteException e) {
return false;
}
@@ -851,13 +851,13 @@
*
* @return true on success
*
- * @see #disableWifiMulticast
+ * @see #disableMulticast
*
* @hide pending API council approval
*/
- public boolean enableWifiMulticast(String tag) {
+ public boolean enableMulticast(String tag) {
try {
- mService.enableWifiMulticast(new Binder(), tag);
+ mService.enableMulticast(new Binder(), tag);
return true;
} catch (RemoteException e) {
return false;
@@ -872,13 +872,13 @@
*
* @return true on success
*
- * @see #enableWifiMulticast
+ * @see #enableMulticast
*
* @hide pending API council approval
*/
- public boolean disableWifiMulticast() {
+ public boolean disableMulticast() {
try {
- mService.disableWifiMulticast();
+ mService.disableMulticast();
return true;
} catch (RemoteException e) {
return false;
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 64084cf..6771136 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -161,8 +161,8 @@
private WifiInfo mWifiInfo;
private List<ScanResult> mScanResults;
private WifiManager mWM;
- private boolean mHaveIPAddress;
- private boolean mObtainingIPAddress;
+ private boolean mHaveIpAddress;
+ private boolean mObtainingIpAddress;
private boolean mTornDownByConnMgr;
/**
* A DISCONNECT event has been received, but processing it
@@ -303,8 +303,8 @@
mWifiInfo = new WifiInfo();
mWifiMonitor = new WifiMonitor(this);
- mHaveIPAddress = false;
- mObtainingIPAddress = false;
+ mHaveIpAddress = false;
+ mObtainingIpAddress = false;
setTornDownByConnMgr(false);
mDisconnectPending = false;
mScanResults = new ArrayList<ScanResult>();
@@ -444,6 +444,14 @@
}
/**
+ * Report whether the Wi-Fi connection has successfully acquired an IP address.
+ * @return {@code true} if the Wi-Fi connection has been assigned an IP address.
+ */
+ public boolean hasIpAddress() {
+ return mHaveIpAddress;
+ }
+
+ /**
* Send the tracker a notification that a user-entered password key
* may be incorrect (i.e., caused authentication to fail).
*/
@@ -724,7 +732,7 @@
intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, true);
mContext.sendBroadcast(intent);
}
- if (supplState == SupplicantState.COMPLETED && mHaveIPAddress) {
+ if (supplState == SupplicantState.COMPLETED && mHaveIpAddress) {
setDetailedState(DetailedState.CONNECTED);
} else {
setDetailedState(WifiInfo.getDetailedStateOf(supplState));
@@ -739,8 +747,8 @@
* first and then off.. if nobody else wants it on it'll be
* off then and it's all synchronized within the API.
*/
- mWM.enableWifiMulticast("WifiStateTracker");
- mWM.disableWifiMulticast();
+ mWM.enableMulticast("WifiStateTracker");
+ mWM.disableMulticast();
if (mBluetoothA2dp == null) {
mBluetoothA2dp = new BluetoothA2dp(mContext);
@@ -783,8 +791,8 @@
}
setDetailedState(DetailedState.DISCONNECTED);
setSupplicantState(SupplicantState.UNINITIALIZED);
- mHaveIPAddress = false;
- mObtainingIPAddress = false;
+ mHaveIpAddress = false;
+ mObtainingIpAddress = false;
if (died) {
mWM.setWifiEnabled(false);
}
@@ -954,7 +962,7 @@
}
requestConnectionStatus(mWifiInfo);
if (!(result.state == DetailedState.CONNECTED &&
- (!mHaveIPAddress || mDisconnectPending))) {
+ (!mHaveIpAddress || mDisconnectPending))) {
setDetailedState(result.state);
}
@@ -983,7 +991,7 @@
mLastBssid = result.BSSID;
mLastSsid = mWifiInfo.getSSID();
mLastNetworkId = result.networkId;
- if (mHaveIPAddress) {
+ if (mHaveIpAddress) {
setDetailedState(DetailedState.CONNECTED);
} else {
setDetailedState(DetailedState.OBTAINING_IPADDR);
@@ -1051,8 +1059,8 @@
break;
}
mReconnectCount = 0;
- mHaveIPAddress = true;
- mObtainingIPAddress = false;
+ mHaveIpAddress = true;
+ mObtainingIpAddress = false;
mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
mLastSignalLevel = -1; // force update of signal strength
if (mNetworkInfo.getDetailedState() != DetailedState.CONNECTED) {
@@ -1078,9 +1086,9 @@
// [ 0- 0] Interface configuration succeeded (1) or failed (0)
EventLog.writeEvent(EVENTLOG_INTERFACE_CONFIGURATION_STATE_CHANGED, 0);
- mHaveIPAddress = false;
+ mHaveIpAddress = false;
mWifiInfo.setIpAddress(0);
- mObtainingIPAddress = false;
+ mObtainingIpAddress = false;
synchronized(this) {
WifiNative.disconnectCommand();
}
@@ -1156,18 +1164,18 @@
setPollTimer();
mLastSignalLevel = -1;
if (!mUseStaticIp) {
- if (!mHaveIPAddress && !mObtainingIPAddress) {
- mObtainingIPAddress = true;
+ if (!mHaveIpAddress && !mObtainingIpAddress) {
+ mObtainingIpAddress = true;
mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
}
} else {
int event;
if (NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) {
- mHaveIPAddress = true;
+ mHaveIpAddress = true;
event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
if (LOCAL_LOGD) Log.v(TAG, "Static IP configuration succeeded");
} else {
- mHaveIPAddress = false;
+ mHaveIpAddress = false;
event = EVENT_INTERFACE_CONFIGURATION_FAILED;
if (LOCAL_LOGD) Log.v(TAG, "Static IP configuration failed");
}
@@ -1200,8 +1208,8 @@
* using the interface, stopping DHCP, and disabling the interface.
*/
public void resetInterface() {
- mHaveIPAddress = false;
- mObtainingIPAddress = false;
+ mHaveIpAddress = false;
+ mObtainingIpAddress = false;
mWifiInfo.setIpAddress(0);
/*
@@ -1612,8 +1620,8 @@
}
sb.append(LS).append(mWifiInfo).append(LS);
sb.append(mDhcpInfo).append(LS);
- sb.append("haveIpAddress=").append(mHaveIPAddress).
- append(", obtainingIpAddress=").append(mObtainingIPAddress).
+ sb.append("haveIpAddress=").append(mHaveIpAddress).
+ append(", obtainingIpAddress=").append(mObtainingIpAddress).
append(", scanModeActive=").append(mIsScanModeActive).append(LS).
append("lastSignalLevel=").append(mLastSignalLevel).
append(", explicitlyDisabled=").append(mTornDownByConnMgr);