Merge change 1804 into donut
* changes:
Additional logging in buildSearchableList().
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 7d55a7d..6fe382d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -870,17 +870,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 +1035,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 +1167,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"
@@ -1471,6 +1482,17 @@
visibility="public"
>
</field>
+<field name="linear_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432587"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="overshoot_interpolator"
type="int"
transient="false"
@@ -31999,22 +32021,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"
@@ -32154,6 +32165,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"
@@ -86002,6 +86023,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/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/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/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/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index ce6501c..249d9ba 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -147,7 +147,8 @@
@Override
public boolean onCreate() {
if (isTemporary()) throw new IllegalStateException("onCreate() called for temp provider");
- mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(), mDatabaseName);
+ mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(),
+ mDatabaseName);
mSyncState = new SyncStateContentProviderHelper(mOpenHelper);
AccountMonitorListener listener = new AccountMonitorListener() {
@@ -235,76 +236,147 @@
return Collections.emptyList();
}
+ /**
+ * <p>
+ * Call mOpenHelper.getWritableDatabase() and mDb.beginTransaction().
+ * {@link #endTransaction} MUST be called after calling this method.
+ * Those methods should be used like this:
+ * </p>
+ *
+ * <pre class="prettyprint">
+ * boolean successful = false;
+ * beginTransaction();
+ * try {
+ * // Do something related to mDb
+ * successful = true;
+ * return ret;
+ * } finally {
+ * endTransaction(successful);
+ * }
+ * </pre>
+ *
+ * @hide This method is dangerous from the view of database manipulation, though using
+ * this makes batch insertion/update/delete much faster.
+ */
+ public final void beginTransaction() {
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransaction();
+ }
+
+ /**
+ * <p>
+ * Call mDb.endTransaction(). If successful is true, try to call
+ * mDb.setTransactionSuccessful() before calling mDb.endTransaction().
+ * This method MUST be used with {@link #beginTransaction()}.
+ * </p>
+ *
+ * @hide This method is dangerous from the view of database manipulation, though using
+ * this makes batch insertion/update/delete much faster.
+ */
+ public final void endTransaction(boolean successful) {
+ try {
+ if (successful) {
+ // setTransactionSuccessful() must be called just once during opening the
+ // transaction.
+ mDb.setTransactionSuccessful();
+ }
+ } finally {
+ mDb.endTransaction();
+ }
+ }
+
@Override
- public final int update(final Uri url, final ContentValues values,
+ public final int update(final Uri uri, final ContentValues values,
final String selection, final String[] selectionArgs) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
+ boolean successful = false;
+ beginTransaction();
try {
- if (isTemporary() && mSyncState.matches(url)) {
- int numRows = mSyncState.asContentProvider().update(
- url, values, selection, selectionArgs);
- 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));
- }
-
- return result;
+ int ret = nonTransactionalUpdate(uri, values, selection, selectionArgs);
+ successful = true;
+ return ret;
} finally {
- mDb.endTransaction();
+ endTransaction(successful);
}
}
+ /**
+ * @hide
+ */
+ public final int nonTransactionalUpdate(final Uri uri, final ContentValues values,
+ final String selection, final String[] selectionArgs) {
+ if (isTemporary() && mSyncState.matches(uri)) {
+ int numRows = mSyncState.asContentProvider().update(
+ uri, values, selection, selectionArgs);
+ return numRows;
+ }
+
+ int result = updateInternal(uri, values, selection, selectionArgs);
+ if (!isTemporary() && result > 0) {
+ getContext().getContentResolver().notifyChange(uri, null /* observer */,
+ changeRequiresLocalSync(uri));
+ }
+
+ return result;
+ }
+
@Override
- public final int delete(final Uri url, final String selection,
+ public final int delete(final Uri uri, final String selection,
final String[] selectionArgs) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
+ boolean successful = false;
+ beginTransaction();
try {
- if (isTemporary() && mSyncState.matches(url)) {
- int numRows = mSyncState.asContentProvider().delete(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
- return numRows;
- }
- int result = deleteInternal(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
- if (!isTemporary() && result > 0) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
- }
- return result;
+ int ret = nonTransactionalDelete(uri, selection, selectionArgs);
+ successful = true;
+ return ret;
} finally {
- mDb.endTransaction();
+ endTransaction(successful);
}
}
- @Override
- public final Uri insert(final Uri url, final ContentValues values) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
- try {
- if (isTemporary() && mSyncState.matches(url)) {
- Uri result = mSyncState.asContentProvider().insert(url, values);
- mDb.setTransactionSuccessful();
- return result;
- }
- Uri result = insertInternal(url, values);
- mDb.setTransactionSuccessful();
- if (!isTemporary() && result != null) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
- }
- return result;
- } finally {
- mDb.endTransaction();
+ /**
+ * @hide
+ */
+ public final int nonTransactionalDelete(final Uri uri, final String selection,
+ final String[] selectionArgs) {
+ if (isTemporary() && mSyncState.matches(uri)) {
+ int numRows = mSyncState.asContentProvider().delete(uri, selection, selectionArgs);
+ return numRows;
}
+ int result = deleteInternal(uri, selection, selectionArgs);
+ if (!isTemporary() && result > 0) {
+ getContext().getContentResolver().notifyChange(uri, null /* observer */,
+ changeRequiresLocalSync(uri));
+ }
+ return result;
+ }
+
+ @Override
+ public final Uri insert(final Uri uri, final ContentValues values) {
+ boolean successful = false;
+ beginTransaction();
+ try {
+ Uri ret = nonTransactionalInsert(uri, values);
+ successful = true;
+ return ret;
+ } finally {
+ endTransaction(successful);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public final Uri nonTransactionalInsert(final Uri uri, final ContentValues values) {
+ if (isTemporary() && mSyncState.matches(uri)) {
+ Uri result = mSyncState.asContentProvider().insert(uri, values);
+ return result;
+ }
+ Uri result = insertInternal(uri, values);
+ if (!isTemporary() && result != null) {
+ getContext().getContentResolver().notifyChange(uri, null /* observer */,
+ changeRequiresLocalSync(uri));
+ }
+ return result;
}
@Override
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/os/Build.java b/core/java/android/os/Build.java
index 5487c54..4a4285e 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -87,6 +87,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 +104,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/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 3141f1a..84fe184 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -340,27 +340,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");
}
@@ -869,6 +875,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>
*/
@@ -1005,7 +1022,13 @@
}
} else {
if (!TextUtils.isEmpty(label)) {
- display = label;
+ if (label.toString().equals(MOBILE_EMAIL_TYPE_NAME)) {
+ display =
+ context.getString(
+ com.android.internal.R.string.mobileEmailTypeName);
+ } else {
+ display = label;
+ }
}
}
break;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 14ef810..56a0104 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.
*/
@@ -1188,7 +1188,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
*/
@@ -1270,13 +1270,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
/**
@@ -1321,7 +1321,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
@@ -1334,7 +1334,7 @@
*/
@Deprecated
public static final String LOGGING_ID = Secure.LOGGING_ID;
-
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#NETWORK_PREFERENCE} instead
*/
@@ -1374,7 +1374,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
*/
@@ -1412,7 +1412,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
@@ -1448,7 +1448,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
@@ -1824,19 +1824,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).
@@ -1845,12 +1845,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.
@@ -1872,19 +1872,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
@@ -1892,18 +1892,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.
*/
@@ -1926,64 +1926,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
@@ -1992,7 +1992,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
@@ -2000,7 +2000,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.
*/
@@ -2015,24 +2015,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.
@@ -2062,22 +2062,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
@@ -2126,7 +2135,7 @@
allowedProviders.startsWith(provider + ",") ||
allowedProviders.endsWith("," + provider));
}
- return false;
+ return false;
}
/**
@@ -2150,7 +2159,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.
@@ -2171,6 +2180,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();
@@ -2271,7 +2287,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.
*/
@@ -2961,7 +2977,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.
*/
@@ -3105,7 +3121,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
@@ -3170,7 +3186,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}
@@ -3185,24 +3201,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) : "";
@@ -3258,4 +3274,3 @@
return "android-" + Long.toHexString(androidId);
}
}
-
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..afeb5cd 100644
--- a/core/java/android/syncml/pim/vcard/ContactStruct.java
+++ b/core/java/android/syncml/pim/vcard/ContactStruct.java
@@ -16,45 +16,102 @@
package android.syncml.pim.vcard;
-import java.util.List;
+import android.content.AbstractSyncableContentProvider;
+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 +120,841 @@
* @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.nonTransactionalInsert(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.nonTransactionalInsert(
+ GroupMembership.CONTENT_URI, values);
+ if (resultUri == null) {
+ Log.e(LOG_TAG, "Faild to insert the person to MyContact.");
+ provider.nonTransactionalDelete(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.nonTransactionalInsert(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.nonTransactionalInsert(
+ 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.nonTransactionalInsert(
+ 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.nonTransactionalInsert(
+ 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.nonTransactionalInsert(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.nonTransactionalUpdate(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.beginTransaction();
+ try {
+ pushIntoContentProviderOrResolver(provider, myContactsGroupId);
+ successful = true;
+ } finally {
+ provider.endTransaction(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/recognizer/Prediction.java b/core/java/android/syncml/pim/vcard/VCardNestedException.java
old mode 100755
new mode 100644
similarity index 60%
copy from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
copy to core/java/android/syncml/pim/vcard/VCardNestedException.java
index c318754..def6f3b7
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/core/java/android/syncml/pim/vcard/VCardNestedException.java
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -14,23 +14,14 @@
* limitations under the License.
*/
-package com.android.gesture.recognizer;
+package android.syncml.pim.vcard;
/**
- *
- * A recognition result that includes the label and its score
+ * VCardException thrown when VCard is nested without VCardParser's being notified.
*/
-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;
- }
+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/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/WindowManager.java b/core/java/android/view/WindowManager.java
index c69c281..72ef0ad 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -466,6 +466,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/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index c28210d..32e5504 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -348,7 +348,12 @@
"ArrayAdapter requires the resource ID to be a TextView", e);
}
- text.setText(getItem(position).toString());
+ T item = getItem(position);
+ if (item instanceof CharSequence) {
+ text.setText((CharSequence)item);
+ } else {
+ text.setText(item.toString());
+ }
return view;
}
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..4297be0 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 {
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..edc9ec9 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;
@@ -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..25d0122 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 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,70 @@
* 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.
+ */
+ 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 +192,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 +214,37 @@
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.
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/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_Process.cpp b/core/jni/android_util_Process.cpp
index d760feb..95c38dc 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -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 bff6b9d..b5f3a0f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -389,11 +389,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 +803,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 +981,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/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/raw/lattin_lowercase b/core/res/res/raw/lattin_lowercase
new file mode 100644
index 0000000..ea15357
--- /dev/null
+++ b/core/res/res/raw/lattin_lowercase
@@ -0,0 +1,60 @@
+256 32 26
+a b c d e f g h i j k l m n o p q r s t u v w x y z
+-1.0320373 0.44948834 0.5026982 1.262901 0.023728203 0.35666424 -0.3011761 -0.29305357 -1.2141068 0.7408129 0.3580437 -0.57449627 0.089328125 -0.2748898 0.24193475 0.34128588 -0.17308189 -0.026935482 -0.14250056 -0.5399076 -0.5752277 -1.4722083 -0.5954861 -0.22238986 -2.6316617 -0.615307 -0.7596958 -0.9375199 -0.6210034 0.22707939 -0.025550082 -0.12134152 -0.56391954 -1.0288627 -0.2084017 -1.3599188 0.3679564 -0.94063354 -0.27841672 -0.7137886 -1.0174123 -0.26217672 -0.77808744 -0.94122726 0.079729855 -0.8499919 0.33966482 -0.2227484 -0.5293933 -0.18848658 -0.18806252 0.04655085 1.2125677 -0.5123718 -0.63121176 -0.6841088 0.2854664 -0.47106475 -0.2914258 -0.24383987 0.58822995 0.1848862 -0.08414658 -0.84331983 0.28089076 0.8338416 0.64424884 -0.08822638 0.6026292 0.3966598 0.5018676 -1.6556886 -0.030652374 0.06030074 -0.03885972 0.48495716 0.30927324 0.65247893 -0.23975888 0.3126487 0.12552232 -0.40606382 -0.24021025 0.2239085 0.17895736 -0.2752283 -0.07477209 0.36556083 -0.5580003 0.22353698 0.58177936 -0.52982306 -0.24412508 0.6671521 -0.59883493 0.2713756 -0.34448382 -0.5513394 0.1283845 -0.9786675 -0.62606144 -2.0965924 0.06479836 -0.37276036 1.2126547 0.9212107 0.44119748 1.0288627 0.034679867 1.1907843 0.75170547 0.35206679 0.7273997 0.45056993 0.9378007 -1.5369866 -0.17309512 -1.2507765 1.0952296 1.5189886 1.5939811 0.25394422 0.66708034 0.69421405 0.39794734 0.29738182 0.8495444 0.6583927 0.7242627 0.14712924 -0.20420945 -0.32778937 -0.1488928 -1.7449872 -0.47115076 1.4096025 3.3539834 0.93653834 1.889615 0.034595147 0.85133743 0.888768 0.8602395 0.19983679 -0.2646315 0.34296927 0.16271558 -1.0446007 -0.28894347 -1.4071596 -1.1821536 1.761192 0.7683237 0.34883177 1.2127637 0.960367 0.49257267 -0.12317568 0.87162894 -0.10094326 0.083965614 -0.95773655 -1.4323143 -0.17024235 0.94067466 0.5178371 -1.7006843 1.0176337 0.98305815 1.044752 -0.4755929 1.0607079 0.95405406 0.0037732746 0.39355248 -0.6359591 -0.93546396 -0.43886432 -0.26785922 0.40323904 0.37780532 -0.282651 1.0897744 -0.076653205 0.8621501 0.52201897 -0.47145545 -0.08639464 0.24826962 -0.5449552 -0.70446354 -0.35573912 -0.116620034 -0.3555207 -0.87672955 -0.8332148 0.032643896 -1.4711387 -0.07666701 -0.41090423 -1.7450113 -0.7125798 0.588236 1.011962 -0.10906482 -0.049713787 0.21974635 -0.5164017 0.45955366 -0.21865442 0.054675397 -1.643716 0.0869121 0.33518708 0.7350744 -0.35638383 -0.5359705 -1.1251022 0.6354905 0.014285822 0.07969646 -0.01224353 0.3956445 0.41475978 0.21799022 -0.24329978 -0.18884242 -0.61439615 0.22055328 0.57163405 0.5219093 0.43035847 -0.10191071 -0.47637305 0.07277042 0.5151729 0.26946694 -0.7489405 0.40340453 1.9628311 0.1358872 0.23183657 -0.5884934 0.46311405 0.9058562 0.15964781 -0.2011342 0.7970426 0.72013247 -0.6099858 1.3816767 1.332009 0.44028193 0.5621748 0.86960286 1.4065886 0.047132853
+-0.5876459 -0.49861982 0.10776312 0.21296671 -0.33432215 0.6860717 -1.0144031 -0.34735164 -0.1619369 -0.29697385 0.23474793 -0.03802241 0.6555007 -0.05209993 0.33327565 0.32580897 0.023576869 -0.30506077 -0.5729418 0.2563657 1.1094613 -0.44860962 0.09360653 0.54840297 0.4260575 -0.6992373 -0.20520735 0.71440935 -0.9723347 0.8040045 0.63410026 0.58063257 0.0136224255 -0.6925302 0.44188362 -0.7033653 0.5922983 0.35525048 -0.53687984 0.1797763 0.9169536 -0.7691884 -0.60692513 0.26153398 -0.069532506 -0.538867 -0.8859806 0.38015127 -0.92498 -0.48258197 -0.88898116 0.19742773 -0.48234966 0.41349337 0.21274965 -0.98993015 -0.47080618 1.105701 -0.08140514 -0.1572882 0.30675626 -0.933662 -0.24383947 -0.42028394 -0.17814463 -1.3032701 0.9004051 -0.87253183 1.115192 0.12463315 1.2909203 -0.0733367 -0.40072724 -1.0145737 -0.39735577 -0.47220743 0.41327307 -0.28179047 -0.043861967 0.055796742 -0.05651231 -0.07193288 0.48533636 1.1923914 0.025903484 0.38037747 1.4659939 0.08858928 -0.2389544 0.2729484 -0.27963135 0.13005349 -1.1585696 -0.7126106 0.36186382 0.33154425 1.2340155 0.7118002 0.7473359 0.006837656 0.09851849 -0.42307237 1.4577137 0.58804166 -0.6891303 -0.40587357 1.0740286 0.03683702 -0.29733622 0.9951917 0.86343867 0.88644445 2.182068 0.5716775 1.0376911 -0.08141223 0.5662745 -0.54189956 -0.6177993 -0.33114722 -0.8763973 0.33553421 -0.82770103 0.2069794 1.5816944 1.1606182 2.2737305 1.127369 1.2190173 2.2908351 -0.16844165 -0.74434006 -1.1939615 -0.7338548 -0.6030772 1.2044704 0.27758908 0.04341341 0.1763783 0.77722347 1.2800475 1.0819324 0.60104007 0.31573844 1.7553719 1.3475811 -0.8430969 -0.92384106 -0.9509633 -0.18090925 -0.62012523 0.32144892 -0.11040283 0.035557035 1.1098006 1.8863741 1.534876 1.8720753 0.91152793 0.22508813 1.0451688 1.1840922 -0.78783786 0.8897153 0.27138832 0.26466617 0.42849094 -2.1830962 -0.043503325 0.35566506 1.2814229 1.0061014 1.4608265 0.22734466 0.19427025 -0.29217315 0.84439886 -0.4345544 -0.10515358 -0.47235605 -0.3699708 -1.1436845 0.55321467 -1.1847504 -0.1958594 0.14161305 -0.049251057 -0.8083699 -0.35083675 -0.04412858 0.1290029 -0.83500767 0.3726739 0.15749925 -0.64612883 0.6160278 0.41822785 0.20624 -0.8318465 1.033156 0.033572674 -1.2793441 0.11257877 -0.4348593 0.17882615 0.12986831 0.57957596 -0.54833245 -0.29726908 -0.35211858 0.104037285 1.2497333 0.41274184 0.43120015 0.5675716 -0.4202907 -0.32985362 -1.142256 -0.4488625 -0.14350273 -0.20391443 -0.5083643 -0.55823666 0.74031174 -0.43515426 0.30245942 0.18587282 0.2055401 0.75232697 0.26275596 -0.07702634 1.410873 0.6440989 -0.90422094 -1.5420893 -0.7410849 0.35951835 -0.89543074 -0.48307157 -0.13803153 0.10946857 -0.8220215 -0.4019354 -1.2127689 -0.43956572 0.9073772 1.0947679 1.035815 1.5543823 -0.025296837 -2.48436 -1.2636491 -0.7632876 -0.6784003 0.24657041 -0.03576962 0.046560217
+0.16219118 -0.4426603 -0.600031 0.18258785 -0.22529073 -0.65151876 -0.6258459 0.802893 -1.0839835 -0.17222537 -0.65083605 -1.5175898 0.18215714 -0.36140135 -0.49675673 -0.3622017 -0.8149667 -1.6608212 -0.6388111 -1.4454705 -1.1541909 -0.61790717 -0.28906113 -0.35366306 -1.2543796 -0.7093829 -0.98888534 -0.9181567 -0.63943064 0.12450104 -0.09578552 -0.7538275 -0.93561816 -0.5891333 0.15560862 -0.66441643 1.0577961 -0.07506256 0.08393138 0.17169975 1.0148748 -0.06925079 -0.68809485 -0.5896944 -0.1996866 -0.67327726 -0.5468578 -0.37417012 -0.7947043 -0.7525708 0.28118336 0.9260421 0.3027611 0.9822964 0.6237638 0.8722198 0.022905791 -0.037577298 -0.5827326 0.48818904 1.1342663 -0.20865044 -0.04710247 -0.010654767 -0.7887384 0.31152782 0.79465914 -0.0048791366 0.50807536 -0.26687565 -0.9507433 0.4608591 1.0266969 -1.4705683 -0.061186083 -0.21109411 0.99001426 0.78452045 -0.6222921 0.10510122 -0.42242125 0.20869707 0.6328383 0.9256842 0.6576888 2.0937 0.7611171 -0.70748687 0.037744936 -1.4124163 -0.0843527 0.4915949 -0.83560425 -0.38328716 0.15288664 0.30524924 0.57254124 0.41256082 0.23704594 0.69178927 -0.69596875 0.544245 0.06849858 -0.8949961 -0.37929693 -0.9599314 0.23557587 0.07470506 0.36212632 0.8158679 -0.23767526 -0.026285637 -0.0599318 0.59204084 0.12959881 0.1400853 -0.5906369 -0.016372161 -0.8160715 -0.29036832 -1.0383385 0.8936524 0.22328083 1.1923993 0.5806411 0.6526409 0.63405204 -0.19770753 0.23216254 -0.8464065 0.05448277 -0.42121163 0.09593496 -0.3940919 -1.3036078 -0.42130777 -1.5108993 -0.7380616 1.5854365 0.83480376 -0.13829987 -0.16158567 0.37549603 0.10953091 0.39026895 -0.26774323 -1.0740238 -0.3012103 -1.3277439 -0.52309877 -0.15750808 -1.396249 -1.8065764 -0.70957196 -0.2701284 0.80136764 -0.55877876 1.1693957 -0.023915604 0.6109688 0.26837918 0.3847679 -1.0180675 -1.6800753 -0.17039482 -1.9280031 0.14020222 -1.6825341 -0.6809575 0.73719066 1.4824125 1.0057563 0.38886833 0.41541937 0.86456496 0.3738373 0.25312418 -0.49311206 -0.5448705 -0.19806409 0.03642095 -1.2165587 -0.5488742 -1.0539055 -1.383237 0.91086125 2.0450864 0.40860626 -0.4115251 0.77019817 0.41150022 -0.6942789 -0.2623275 -0.3564064 0.71422654 -0.110816024 -0.24622679 -1.6485498 -0.93887424 0.3545291 0.3893998 0.505052 0.81602067 -0.13229635 -0.1546229 0.5264243 0.07832468 -0.8087632 0.3644968 0.4432914 -0.2709118 -0.41903403 0.75777215 -0.29312503 1.0305605 0.68167573 0.84435254 -0.08526038 0.49609768 -0.14810072 -0.20223649 -0.16442187 1.0925809 -0.42481133 -0.20465627 0.4510143 0.1474519 -0.45746815 -0.028668247 0.37599435 2.2844088 1.8621339 1.7369909 1.8354855 1.2473161 0.28396165 -0.08997915 1.6469697 1.3783201 0.91929704 0.4862938 0.34556144 0.44629437 0.2890028 1.2533419 0.09651396 1.3923194 0.60770035 0.976285 0.29779458 1.3238846 0.1512996 -0.051096678 0.64230007 0.2520603 0.20745353 -0.033866037
+-0.9928002 -0.65029335 -0.32707617 -0.63213104 0.047495916 1.0467823 1.2627105 0.41369182 0.43423036 -0.31745973 -0.10303828 -0.4490784 -1.1289506 -0.12982605 -0.09015896 -0.41713923 -0.9552456 -0.41601163 0.033094466 0.11061575 0.03034314 1.0085478 0.42413545 0.6370122 -0.80927914 1.3770676 0.3047822 -1.092244 -0.63284695 -0.1039884 -0.5155913 -0.2916848 -1.1730976 -1.3406764 -0.4014016 -0.22628841 -0.99272746 -1.2915963 -0.43317 0.6375122 0.14244819 0.3385207 0.1259358 -0.021841656 -0.15069425 -0.14160752 -0.40258723 -0.1944997 -1.4997909 -0.3928863 -0.37465528 -0.53800166 1.0240898 0.52819 1.275291 0.112462245 1.2243528 0.090886466 -1.2444159 -0.829214 -0.56068057 0.08047258 -0.042596154 0.017601306 -0.32116365 -0.112104 0.25719127 0.61710596 0.25098404 -0.18310636 0.19171125 -0.5027974 0.6398731 0.22911249 -0.17384402 -0.40915674 0.6308226 -0.06107232 -1.5945159 -0.26162186 0.48523346 1.2052262 0.6816709 1.3541994 0.5940264 -0.42618665 1.0377761 1.5695388 0.56560785 -2.0908725 -1.3393115 -0.0966352 0.21853672 0.18688229 -1.3811437 -0.7189748 -0.20374478 0.41381744 -0.80065614 0.505686 -0.017379532 0.68715656 -0.1268051 1.3514202 -0.046522304 0.44051644 -1.6699985 -0.18163794 -0.37923735 -0.9181768 -1.5454658 -1.369637 0.1987025 1.4891511 -0.04077638 -0.9291818 0.8886401 0.40813708 0.24677886 0.3432359 0.35186812 -1.1587802 -0.42391884 -0.24800682 -1.2837564 -0.7404945 -2.6592689 -0.2994962 1.1631987 1.9922501 -0.3564703 0.387615 0.38653976 1.7939503 0.24637452 -0.5122606 0.7369326 0.33232284 -2.5826666 -1.6953781 -1.034394 -1.9987204 -1.3348261 -0.97745264 0.7279928 1.3903489 -0.17743021 0.71841097 0.6860481 0.59116197 0.40241712 1.6308252 -0.41697022 -1.7863052 -3.174945 -1.2819895 -2.1388152 -1.9280391 -2.1472805 -1.4430648 -0.3548682 0.2089911 1.3924816 0.9638301 0.46611738 1.244214 -0.080808155 0.98346466 -1.071935 -1.411514 -4.6242075 -3.9676464 -2.158492 -1.143991 -2.724027 -0.3730388 0.5443135 1.1468557 0.7640059 0.29976603 0.013265 -0.2000091 -0.9881151 -0.13313034 -0.85124576 -1.4047194 -3.1513608 -1.59114 -0.48440665 -1.2347834 -1.5911614 -0.66515714 0.19321048 1.1618471 -0.21929866 0.37943915 -0.5288679 -0.8446482 0.4516073 1.559307 -0.7751308 0.1352856 -0.7948278 0.5544108 1.5591183 -0.34893557 -0.58530706 -1.2028453 -0.15346713 0.48009244 0.2714317 -0.21216361 0.79691285 0.18238634 0.033441454 0.9847478 2.6799603 0.04519922 -0.39819828 -0.56808174 -0.5608276 -0.5621788 -0.23777194 -0.4576924 0.09079646 -0.58780473 0.3989908 -1.5877905 0.6298423 0.8041579 -1.615472 -0.04399715 0.645193 0.93147075 -0.9793776 -0.43839702 0.6700141 0.8992372 0.96656436 0.42896184 0.06799507 -0.121551305 0.03643667 0.5107995 1.2391013 0.20313375 -0.8901323 -0.11926519 -0.018502166 1.2909812 0.21382728 -0.2109217 0.3447241 0.09436148 0.07683945 0.33333707 0.0073161237
+-0.18363933 0.48743215 0.9734924 0.82300645 1.1365234 1.3104441 -1.0992749 -0.43311545 -0.35092866 -0.035903934 -0.6433543 -0.056928437 0.50812507 1.2388171 -0.3643605 -0.008841951 0.43816802 0.4549297 1.7472706 2.4208047 2.3252141 0.9372224 0.58785486 -0.14330845 -0.013962021 -0.17999677 -0.51957333 0.53184605 0.3530506 0.9935447 0.90848666 0.52409446 0.7318021 0.46253845 0.57282305 0.13758732 1.2198166 1.995053 1.7632414 -0.019195529 0.09019049 -0.49321592 -0.35048074 0.7887149 -1.3604357 -0.11380006 -0.2492828 0.48950064 0.94204026 0.89088166 0.62689316 1.2040389 1.5950793 -0.19379832 2.037751 0.55023944 0.10160493 0.5160332 -0.95978534 0.18341489 -0.72510695 0.49078816 -0.68670774 -0.23842214 0.7935416 0.46988228 1.1646838 1.4694536 -0.48905516 0.28097233 0.04768517 -1.4034481 0.76640594 0.061519478 0.2392991 -1.0311254 -0.71537673 -0.6825493 0.20515685 -0.31145504 1.3132821 0.48301062 0.9326164 -0.10253975 -0.550522 0.20858018 -0.64940214 -0.2901015 -0.2658784 0.5320008 -0.89019006 -0.2251651 -1.0973288 -0.48251343 -0.23194161 0.34232897 0.46460086 1.2053684 0.37144804 1.0120065 -0.87289697 -0.19781584 -0.70588326 -0.43817925 -0.24095063 -0.5148169 0.3499117 -0.5846331 -0.34835428 0.70133203 0.07190903 0.6244331 0.7937318 0.8530495 -0.283671 -0.29489642 -0.20501985 -0.15467195 -0.77982306 0.4515451 -0.2610175 -0.40279686 1.1797135 0.4087195 -0.20622212 -1.1451014 0.18354966 -0.0061676195 0.25439322 0.22244005 -0.077419914 0.27753034 -0.06819225 -1.0458517 0.3270537 -0.6740566 -0.07237265 0.10929287 -0.7878886 -0.04869395 -1.0487218 0.42578617 0.33093584 0.3234661 -0.19412623 -0.41848716 -0.0350828 -1.0023264 -0.012715773 0.053522155 -0.2866792 -0.5961487 0.09559097 -0.34835342 -0.09524932 -0.49118337 0.56957 0.42196232 1.2921919 0.8131441 -0.064788125 -1.7430549 -0.62558156 0.97213 -1.3765856 -0.8128312 0.7381559 -0.43193838 0.076701336 0.23626271 1.0206754 0.70695513 1.4030601 0.7459599 1.7041987 0.17755316 -0.85486144 -0.43017942 -0.90989125 -0.8591359 0.06385963 0.8856635 0.58149767 0.2500926 -0.23051058 0.23404106 -0.6145896 0.33282027 0.41465953 0.73938537 0.75265735 0.79452324 0.5817997 -0.57481563 -0.61316687 -0.46185386 -0.35781226 -0.028490746 0.09927312 0.26162767 -0.20475222 0.024335561 0.05881939 -1.2323732 -0.373608 0.13963772 -0.50954455 0.9564329 -0.37169278 -0.8616271 -0.43996695 -0.51271695 0.13569131 0.16073285 0.21087371 -0.7338531 1.3449446 0.5731957 0.320499 0.8503369 -0.17713861 1.3689593 -0.11775142 0.9302247 -0.30367264 -0.31072423 0.2961095 0.4146177 0.5528695 -0.05913442 -1.2418368 0.9448847 -0.30547222 0.06529417 0.413268 1.005242 1.0679544 0.63431513 -0.043095257 0.7806826 -0.31520507 -0.79243994 -1.1498984 0.89927524 0.25603995 -0.44269514 0.34776005 0.6654551 -0.05665421 -0.36200863 -0.62900645 0.010842223 -0.05459169 0.25011125 0.29936904 0.08170453 0.04509235
+0.009690465 -0.19900858 0.23695074 -0.8527833 0.7951504 0.44841623 -0.6546095 0.9330005 -0.0022787398 0.5766652 -0.2875641 -0.047964577 0.8209985 -0.7325829 -0.2145783 -0.7067027 0.21113175 -0.19916743 1.0258273 0.3416977 -0.20105757 0.09809456 0.45001507 1.1358036 2.2607532 0.95336705 -0.5534635 0.3905341 0.40341926 1.1624514 -1.2155701 -0.625963 0.68108374 -0.98660916 -1.1137917 -0.8787478 1.0133651 -1.1719929 -0.9368648 0.078257546 -1.1073941 0.92955774 -0.05955402 -0.5972838 1.4500264 -0.70287913 -1.183681 0.3724696 0.23585089 -0.3679381 -0.9335203 -1.5331664 -1.5893548 -1.6938283 -1.0725771 -0.49542084 0.031462796 -0.22506425 -0.43936366 -0.044947095 1.0578681 -1.1291034 -0.60197777 -0.8803757 0.4164687 -0.912827 -2.007975 -0.8814496 -0.030242303 -1.3217716 -0.043043572 -1.7046866 -2.070672 -0.58450365 -1.0318846 -1.0900327 0.55438864 -2.3942473 -0.8075006 -0.7958753 -0.13948639 -1.2660352 -1.6287287 -2.5816212 -0.8111587 -1.334735 -0.23634812 -0.5197122 0.06045255 -1.7208738 -0.6113437 0.23798361 0.58538324 -0.37566698 -0.52596563 0.4443061 -0.36761546 -1.0858792 0.21615133 -0.7929561 -0.82223725 -1.3558347 -0.2844464 -0.6494999 0.23790598 -1.4047889 -0.8010049 -1.5404593 -0.9938851 0.30828804 -0.29141438 0.869884 -0.7351973 0.013261275 -0.3938976 0.057773232 -0.89324254 -0.80985504 0.26294863 0.16494235 0.3263755 -1.6506147 -1.2927015 -1.4647912 -0.79118234 0.069916435 0.54857516 0.3988809 0.054044567 0.26490587 -0.46596298 -0.47880006 -0.6702248 -1.1204683 -0.3225188 -0.8432376 0.3759092 0.3213979 0.5734244 0.61776024 -0.8779473 -0.17280982 0.6847301 0.77520096 0.4914681 0.43213725 0.57792497 1.7109307 -0.044153735 0.012072292 -0.39937335 1.5812209 -0.6565631 0.047942918 0.85521436 1.6743236 0.9959537 1.2512233 0.6205493 0.2763869 1.6925939 0.9292307 0.73578787 0.874885 -0.2565264 0.7997615 0.8303917 -0.22887366 -1.1243706 1.8007994 1.2534605 1.6140722 1.9897671 1.5488573 1.893067 -0.20607288 0.49793032 -0.80511737 -0.064834505 1.8497901 -0.16560401 0.94808793 -1.0030471 -1.1840563 -0.84223664 0.5787038 0.7948008 1.1510955 1.3819356 1.7602245 0.9985033 1.3209784 1.2775407 0.31016925 -0.8043905 -0.27551657 0.20225684 0.94588584 0.84695953 0.7840746 0.2983594 0.27549255 0.62448597 -0.004683344 1.5032496 2.1142802 2.1788297 1.1571127 -0.41761285 0.7774305 0.9450229 0.3211568 1.0166515 -0.4663387 0.5738035 -0.018564438 -0.4230945 -0.14041527 0.84957993 -0.18399918 0.4216098 1.5661583 1.4007261 1.6007679 -0.78876674 0.24864393 1.2816767 -0.055437032 0.4390081 1.0154836 -0.5457875 1.003273 -0.56712645 0.106146365 1.2956294 0.8318372 1.7971948 -0.08846512 1.3584287 1.2667234 -0.6410277 -0.5653042 1.2627145 -1.6668738 0.42066106 -0.17088719 0.043896466 -0.32893133 -0.11164542 -0.35801277 1.1171858 -0.18187432 1.9043331 -0.1668761 1.0862815 1.0449603 -0.015431015
+-0.3056758 0.25940558 0.7462129 0.6350956 0.13632914 -0.6396078 -1.3155322 -1.1040087 -0.33752787 -0.5156164 -1.0465763 -0.6093787 0.40685326 0.6225921 0.2603992 0.5766357 -0.196098 0.12923256 -0.4686261 0.1616566 -0.09910341 -1.0306734 -2.8552198 -1.3635082 -2.2417154 -1.0593598 -2.25758 -1.7030687 1.0617595 -0.49334893 1.1791846 1.4512513 -0.29734978 0.94855225 -0.46216106 -0.84778666 -1.0374062 0.618209 -0.66212726 -0.8803104 -1.7780716 -0.12256134 0.15470175 -0.3464273 0.29547867 0.12165469 1.2727495 0.39479995 -0.7625371 -0.20114647 -1.2006118 -1.1517173 -1.1964978 -1.4148062 -0.46452382 -0.5205421 0.16397645 -0.17937872 0.5736514 -0.52443856 0.69845504 0.4109248 -0.058535002 1.298824 -0.8562251 -0.98890615 -0.031535268 -1.2605784 -1.1179094 -0.18717435 -0.11599437 0.6173255 0.14189507 -1.2777259 -0.04803176 0.39857316 0.8027302 1.2948868 0.52208924 0.2645492 -1.2658685 -0.8756467 -0.45752195 -0.97305286 -1.5142272 -1.969767 0.3244166 0.51413476 -0.85355717 -0.8695191 -0.8742606 -0.5169369 0.2865398 0.7508257 0.79960376 -0.009278044 -0.06197672 -1.7657316 -0.8860684 -0.79440594 -0.24384162 1.7983671 1.3935467 0.474142 1.6855668 1.1444408 -0.9310947 -0.627045 0.10238985 -0.5065145 1.1745216 0.47753122 -1.1510589 -2.0019302 -0.06895789 -0.06828326 0.17690478 1.4180086 0.11025326 0.8729383 1.1315805 0.6586152 -0.21401715 -0.58937716 -1.6295915 0.39105797 -0.4515472 0.46060345 -0.89025563 0.021532096 0.18438768 -0.42909762 -0.1940233 0.6401258 1.670736 1.7877042 1.2986554 0.7997993 0.3297447 -0.5486301 -1.6006788 -0.9164205 -0.26550475 0.12474314 -1.793439 0.11662513 0.06986861 1.0181683 0.08266954 0.2936881 1.6487124 0.1888507 1.9809109 0.78182936 -0.6988833 -0.2592984 -0.3227243 -1.0615262 -0.51933414 -0.7083367 -2.0349166 -0.26193583 -0.86091 0.61426985 2.016055 1.6646006 0.706299 0.4725853 0.41314667 1.5074375 -0.11225649 -1.0601313 -0.59183747 -0.64454836 -0.7303756 -0.2832947 -0.6696172 -0.47461566 0.31139702 -0.08330062 0.14640611 0.8126043 0.52173156 1.4778396 0.12661216 1.2422513 0.4288451 0.5531205 -0.023675961 -0.14848314 0.02674082 -1.5317159 -0.574406 -0.853897 0.77010936 -0.19107993 0.96163034 -0.176591 0.8431422 0.55805457 1.116219 0.644643 0.70558536 -0.6006952 -0.4873829 -0.8154713 -0.7676224 -2.1247323 -0.351832 0.05434874 0.38014942 -0.6010489 0.8107947 0.9159046 0.35858768 0.27016485 -0.3714305 -0.22837786 0.70969987 -1.4209629 -0.19527832 -0.46893156 -1.3820373 -1.2373483 0.6183272 0.4452219 -0.32178953 0.22441939 0.35401177 -1.4855298 -0.44066197 -0.9876982 -1.1699355 1.3939236 0.28869763 -0.39844346 -0.02343711 -0.5377412 -0.7804297 -1.4320343 0.40880522 0.52334285 -0.7213707 1.30111 0.48715797 1.275198 -0.35304925 1.1126703 0.15359367 0.8108517 1.6651682 1.3762898 -0.67302686 -1.4279181 -0.7531475 -0.9934748 0.030440476
+-0.49390033 -0.31292793 -0.14341341 -1.0862973 -0.3706214 -0.917729 1.2503732 -0.6372911 0.19587392 0.90320843 -0.055828877 0.79066217 0.2321678 0.38464406 0.3701561 -0.37617594 -0.2071116 -0.60444653 0.39481458 0.062365945 -0.99447286 -3.0213697 0.5060912 1.2738554 -0.5925375 -1.5181644 0.09778448 0.2697953 -0.19267328 0.20407742 0.14081734 -0.6437068 0.18408099 -0.6053021 -0.27723262 -0.35750344 -0.44576487 -0.48438174 -0.8467316 2.5810733 0.7299506 0.25862694 -0.308035 0.69809544 1.5615593 -0.0020368996 1.0226985 0.26628277 0.34337828 0.015593567 -0.039158896 0.014295919 0.37394795 -0.61859065 -0.28448352 0.6835833 1.7214603 0.7194885 0.91025305 0.32992917 0.842497 1.210814 0.5381061 -0.6795007 0.7845244 0.9563886 0.34939256 0.102710076 0.13012233 -0.9352901 0.04461366 1.0472523 1.1965214 2.619828 1.3711878 0.5000333 1.1733594 0.64382607 1.0558048 0.25913066 0.04962416 0.08333992 -0.16223904 0.073243335 -0.48345485 -0.28375646 -0.77007437 0.38270566 0.29095805 1.593175 0.08686384 0.24688224 1.3434625 1.3385944 1.7315071 0.9330822 0.8523125 1.2978957 0.8403788 0.5358833 -0.9594337 -1.1224754 -0.40075207 -0.03686821 0.34805986 1.3147393 0.23303686 0.45272878 1.4855192 -1.0431982 0.80949146 0.58750105 1.1060905 1.8840538 -0.16496608 -0.2918124 -0.18584184 -0.7047573 -0.5947921 -0.68926984 -0.31440905 1.4112293 0.66576505 0.19974902 -1.2273028 0.24356414 0.7594955 0.4915143 1.1537526 2.0208123 1.1919701 -0.8120755 -1.118012 -0.8039033 -1.4170723 -0.028158484 -0.7736337 0.77594894 -0.039391574 -0.910505 -0.39012077 -0.048952788 -1.739914 -0.02056478 0.6659631 1.9231532 0.51970273 0.10191216 0.6564516 -0.3903447 0.16854532 -1.8610507 -0.014599784 0.40145606 -0.5709755 -0.017843587 -0.2976934 -1.335705 -1.8860589 -0.43249878 0.24911645 0.45743987 0.71512437 -0.47702938 1.8037142 -2.1761549 0.83217275 -1.0765857 -1.8977274 0.13179322 -0.7804813 -0.41208547 0.1565798 -0.71843237 -2.1171758 -0.007908233 0.15673447 0.5592433 0.037603054 -0.8093797 0.39406008 0.015069545 -0.05856205 -0.10243643 0.9708028 -0.041003425 0.027858358 -0.22732769 0.58554256 -0.6045427 -0.96937007 -0.29179788 0.012901342 0.36039814 0.08429996 0.47153482 1.2750409 -0.2402197 -0.8129474 1.9780393 0.87216604 -0.055099644 -0.26628324 0.4730997 0.85863024 1.052321 -0.36233073 0.21802545 -0.29807645 -0.28770325 0.55728453 -0.8058594 -0.27457213 0.4208236 -0.57195336 -0.5677294 -0.6943857 1.7388229 0.4189239 0.29352695 0.6725497 0.41584912 0.040885866 -0.14428978 -0.019623658 -0.21657433 0.37488264 -0.1699314 -1.6765525 0.70977646 0.18749376 -0.14470248 0.16572474 -0.21837525 0.12511916 0.12277298 1.1531436 0.5886546 1.0130509 0.3537823 -0.29226875 -0.23626257 -0.27147204 -1.4844809 0.19797511 1.1109104 -0.85468996 -0.63044196 0.19030863 -0.7126896 0.5692362 0.53858006 1.1847824 1.1505647 1.1090219 0.6805172 -0.03212272
+0.007913814 0.84936315 0.63343155 0.48953503 0.8738088 -0.4334685 -0.14249201 0.7003963 0.2841137 -0.27431172 -0.53888065 -0.63378334 -0.5270509 -0.7281488 -0.330037 0.089221716 0.17856309 1.3921409 0.8178016 0.6422645 -0.7251879 -0.4485757 -0.88254017 -0.49093044 0.6509648 -0.90422493 -1.6174037 -1.1409576 -0.036735248 0.5309393 -0.109900385 0.439644 0.63446856 0.410373 -0.90041375 0.062723264 0.33060318 -0.6515516 -0.88883173 -1.1007831 -1.9034175 -1.9359412 -1.3992747 -0.0390991 0.8219576 0.19731815 0.22928527 0.5886194 0.056047425 0.7632858 -0.15625094 1.0565184 0.29244414 1.058512 0.0874988 -0.5009893 -0.9407323 1.1736679 0.17764659 1.1541831 0.22366141 -0.30309552 1.2416975 0.04490746 -0.029892161 0.71131754 0.4629471 0.881109 0.9240799 0.34414068 0.77068406 1.0031897 1.0112455 1.7385699 2.3840353 0.600025 1.4742049 0.7489345 0.6141411 -0.43403733 0.045874253 -0.36916918 0.11485867 -0.3103994 -0.1629431 0.018570876 0.11262723 0.5963563 1.2677126 0.35677487 2.0030365 0.8637655 0.6233087 0.82007927 1.3723211 0.17605686 -0.33698437 -0.27816886 -0.76384985 -0.3091189 0.18557747 -0.14822364 0.18078609 0.13555793 -0.05057325 0.20787439 0.7429149 1.079982 0.8646369 0.5100897 0.45059288 0.4834545 0.57227355 -1.1267767 -0.8606389 0.35562646 0.09668132 0.5387092 1.4743203 0.5479121 0.7318596 -0.06911307 1.2062231 1.72351 1.3589555 0.4896279 1.3801821 1.4991754 0.12980393 -1.6155373 -0.57706094 1.1976542 -0.34902748 0.8213724 0.22475588 0.9260272 -1.2658701 -0.53761715 1.4153898 1.6866657 1.1313872 1.2918012 0.8839073 0.9833983 0.5871293 -0.80093753 -0.62092346 -0.52962863 0.28122553 0.12704062 -1.1872511 0.01250865 -0.5645048 0.33070102 -0.20425741 0.6895397 0.69107914 1.1354426 0.8302134 0.8465539 0.16281489 -0.91153187 -0.24986205 -0.45047536 0.3462041 0.23288007 -0.26083583 0.29257187 0.3154308 0.38851783 0.07364158 0.3200862 0.9290182 1.5276837 1.1016738 0.7413585 0.40556517 0.29947633 -0.37793833 -0.02723981 -0.49036378 -0.15536614 -0.39699948 -1.5078661 -0.30469513 -0.76891875 -0.22209261 0.15049215 2.007306 1.1701336 0.850127 1.2411462 0.1110765 0.08573646 -0.9114614 -0.28927976 -0.35270628 -0.27452227 -1.0484018 -1.8414426 -0.5044207 0.009931684 0.9059458 -0.66148 1.6383811 1.1635393 0.34223107 0.7345541 0.48553008 -0.46975157 -0.09771621 0.2064373 -0.40831178 0.05613608 -1.246291 -0.4791135 0.55562866 0.07447494 0.11813989 0.24122539 -0.14471632 1.1217656 1.1817559 0.41578862 -0.35332623 -0.40995073 0.7061573 0.39384288 -0.70971155 -1.1331282 -0.72592103 -0.23988575 0.41926327 0.9996532 1.0239495 0.06184188 0.40644673 1.127063 2.1828098 1.2488902 -0.3756218 0.11579426 0.38751152 -1.0403051 0.26015887 -0.56934285 -1.308806 -0.93549794 0.34472388 -0.40398064 0.6122497 0.5413968 9.335384E-4 0.43945858 0.5171869 1.150537 -0.03982428
+-0.04281589 0.17912555 0.11177546 -2.0277448 -1.4380498 -1.069754 -0.05795294 -0.17515501 -0.31269628 0.6461627 0.84028554 -0.11439531 0.8669193 0.4983045 0.38870463 0.5398491 0.40811387 -0.72014225 -0.04690787 -0.70719135 -0.7859748 -0.45783734 -0.28954315 -0.4341929 -0.29108164 0.8021854 0.7936661 1.667713 1.7576307 0.51405644 1.3474803 0.89713615 1.1219721 1.5815213 -0.016587775 -0.70052147 -0.60824466 -1.709584 -1.548762 -0.7955246 0.86813146 -0.9881199 0.8349693 -0.018966123 -0.48228493 -0.88708204 0.48435837 0.88126624 1.1777681 0.7224193 -0.34067193 0.7646806 -1.1690882 -1.1381481 -0.94679874 -1.3690518 0.15539666 0.017479178 -0.38322052 1.2516212 0.57649493 0.89022964 0.22998145 0.33812472 0.21320777 0.5504985 0.24522413 0.2725687 -0.80555964 -1.9190593 0.2469766 -1.0213759 -0.08498454 -0.21052626 -0.2919244 0.71429795 1.3046838 0.73324263 -0.1323501 0.5456764 0.37613457 -0.41410646 -0.13755764 -0.4427845 0.075990655 0.24214323 0.7412368 1.3617707 0.9235044 0.80781204 -0.57678825 -0.59548736 0.5458388 0.32595652 1.1016321 1.5231254 0.5683946 0.43541458 0.27369964 -0.21420872 0.49975133 -0.0069489833 -1.2673442 1.822833 0.6931983 0.77370846 1.1021963 0.6184182 0.09663729 0.05592214 0.3638725 0.94571024 -1.406409 -0.14825377 0.685629 -1.0011239 0.8936033 -0.28291816 -0.9199512 1.1993608 1.6154714 2.0402064 0.8901225 -0.14405484 -0.86432874 0.016678674 0.22340502 0.63215655 -0.72312725 -1.040376 0.88803804 -0.5325414 0.30930457 -0.588593 -0.23722246 -0.009356655 0.4895676 1.4351209 0.5523746 0.16222364 0.45906654 0.17166479 -0.13946642 -0.47695014 0.081548445 -1.5239928 -1.1357517 0.041473724 -2.521038 -0.970511 -2.648776 -0.8162378 0.48254058 0.12578504 0.49402663 0.5303266 0.8569477 -0.078966185 -0.1645747 -0.74802035 0.111712515 -1.1455841 -0.26743686 -0.9942576 -0.4058236 -0.5978243 0.12336995 -0.5690238 0.6451159 1.759227 0.75726664 1.3419937 -0.10753999 -0.4237677 0.42327794 0.87131035 0.075764775 -0.11074565 -1.3602282 -0.48256463 -0.89028 -0.990067 -1.1086117 -0.31196082 0.29917133 1.1849035 0.024827337 0.55807734 -0.015603728 -0.05655328 -0.044300962 -0.29314893 0.65040857 0.28893572 0.10002833 -0.11081047 -0.71215445 -1.162132 -0.6658492 -0.9143596 2.076631 0.80227375 0.3736755 -0.5485538 0.23545386 -0.32170165 0.1741775 0.5634534 0.29092404 0.13463305 -1.2165961 0.040883813 0.23773977 -2.0329037 0.24258971 -0.3299688 0.32317114 -1.0514628 0.6816223 -0.9881947 -1.1202257 0.6430709 0.30352065 -0.45097122 0.31564176 -0.25969523 -1.4737687 -0.51500976 -0.16261342 0.53883386 0.40403664 -0.56394994 1.6383234 1.4451194 1.7861046 0.8720495 0.07647258 0.044152033 -0.3975399 0.35173842 -0.2162056 -0.27966955 0.50301033 -0.7261986 0.2533885 -0.51704 1.6557823 0.41112977 -0.8675332 0.57285154 1.7248181 -1.389647 1.1385014 0.4352173 -0.9512262 -0.4919968 -0.041244067
+0.2956074 1.1182151 1.5027422 0.9412096 0.883848 0.53453207 -0.6824733 -1.7329184 0.29215556 -1.0664713 -1.3112537 0.05999732 -1.5108445 -0.9944299 -0.19323649 -0.2644091 0.871221 1.903874 1.2490755 0.26457068 0.93972003 -1.033757 -1.6153849 -2.7018385 -1.2955686 -0.65649986 -1.3044168 -1.5319792 -0.53235793 -0.37705743 -1.3550161 -0.006838113 1.1953443 1.0451767 1.1054744 1.1533349 1.1797714 0.8228182 0.23246816 -0.57367295 -0.009902226 0.8475423 0.3522334 1.0115519 0.889261 0.9158824 0.071080334 0.0015903722 0.06889787 0.91588104 0.3603213 -0.32467076 0.3569788 0.41667676 1.5429455 -0.5225634 0.70276475 0.34208706 -0.3256261 -0.9304745 0.51439357 -0.13008387 -0.1721931 -0.040590093 -0.70288885 -1.2309508 -0.021646535 0.40178463 -0.8721161 0.43319193 -0.7072422 0.060357485 -1.0494094 0.6060205 0.565944 2.037301 -0.3067864 -0.3919013 -0.019933827 -0.43662125 0.23015678 -0.8767219 0.021707444 0.53235036 0.5483282 -1.398721 0.56313354 0.7013444 -0.036190342 -0.1335313 -0.62517303 0.9862966 -0.2146825 -0.3448236 0.48634183 0.444159 0.13444614 0.2501853 0.749166 -0.05493052 0.042306706 -1.0368966 -0.852935 0.48688915 0.8865013 0.4484552 0.22393593 0.10352872 0.528977 0.14777796 1.353433 0.21616362 -0.12107844 -0.70821464 -0.06689949 0.33613014 0.8655569 -0.13048056 -0.80289 0.1093693 0.3497498 0.6966498 0.54158914 0.5267601 0.5840491 -0.5716022 0.51759744 0.279121 0.6469175 0.018721526 -0.9165588 -0.33129644 -0.2989738 0.27105504 -0.17189798 0.12768358 -0.07935707 0.5591444 -0.3446024 0.08523511 -0.50029874 -0.21616723 -0.38449705 0.4656421 0.5477522 -0.77020764 -0.48832417 0.9411289 0.7267459 -0.3092057 0.12268404 -0.6119454 0.22670318 0.74831957 0.8180572 0.08070001 1.5556079 -0.25473902 -0.095364235 0.4292261 0.2130632 0.13387963 0.23336355 0.012259077 0.0886926 -0.0803512 -0.013202782 -1.2690494 0.48126858 0.21502548 0.6063719 -1.0522778 0.32099938 -0.31443718 -0.19103038 -0.18454869 1.6542068 1.7123017 1.792968 1.6626309 1.7226545 0.9418823 -0.78036857 -0.6335066 -1.0364059 0.46243918 -1.0561168 0.118185595 -0.37425795 -0.21802837 -0.3570218 0.30949646 2.2207007 2.2542937 1.2781748 0.21232724 0.72611636 0.64181924 0.21380614 -1.04361 -1.3311795 -1.0288168 -0.51371026 0.081282616 -0.25049013 0.6045788 -0.16895561 0.94297117 1.2947154 0.8511928 0.5533415 0.56317186 2.4788494 1.0473653 0.7667373 -1.0910962 -0.41290006 -0.42985398 -0.30916727 0.580241 -0.15176378 0.10277087 -1.3890032 1.2639832 0.33714232 0.44618368 0.64688617 -0.13587433 1.1331939 0.033996906 0.38886765 -1.3915112 -1.4662509 -1.1142306 0.10847518 -0.3262126 0.73301446 0.25512785 0.7657714 0.80122405 -0.24669163 0.09745503 0.40052333 0.064661995 0.8879346 -0.54152143 -0.3087037 -0.84335697 -0.06292779 -0.82209426 -1.2383835 1.1356126 -1.5028735 0.66981196 0.91764796 1.0644772 0.025266688
+0.054169875 0.50416356 0.3271972 -0.9301833 0.21652839 -0.038687885 -0.5595878 -0.03514637 1.1430416 0.24386612 -0.6416631 0.36628062 0.73662543 0.42405993 0.009165506 0.38370004 0.26518244 0.27496567 1.422118 1.4138584 0.13358647 1.4575922 -0.6403374 0.9911591 1.1611058 2.4581475 2.5973039 1.4532958 2.0551422 -0.126525 -0.22332872 0.04214531 -0.522039 0.9356122 1.2305725 1.3645406 1.0643563 0.76738864 0.76453793 -1.4275064 -0.042251464 0.8838947 1.024991 0.55401087 -0.6874778 0.12775151 -0.82096285 -0.75906426 -0.6071737 -0.3310458 0.63885415 0.013006932 0.39085266 1.1321204 0.7343642 0.25019994 -0.80922425 -2.2393596 -0.6320773 -0.9479633 -1.1885047 0.21669742 0.033343628 -0.8612701 -0.79805523 -0.63473064 0.7463165 0.6222663 2.120868 -0.25640875 -0.12745436 -0.7143044 -0.21490775 -1.1913393 -2.1180048 -0.82045233 -0.863191 -1.1838536 -0.4450233 -0.6583887 0.9758031 -0.6753233 1.2905637 -0.22363187 1.0684047 1.1046281 -0.13292809 0.2180266 -0.17929195 -0.29068938 -0.96840656 -1.9030772 -2.083831 -0.18850215 -1.1153711 -0.7315609 -0.16138475 0.5192054 0.48648322 2.2374945 1.7756654 0.9843091 0.57474726 -0.4133715 -1.1144454 0.15336594 -0.135578 -1.383263 -0.8455869 -0.33583984 -0.57563514 -0.9853469 -0.16544865 1.2119457 2.0316694 -0.23017865 0.067118905 1.0316392 0.72843 0.20260336 -0.42423543 0.8247007 -1.7665085 -1.0417022 -0.10873964 -0.878114 -2.8727272 -0.54285496 0.2235938 0.8905241 0.988788 0.8426971 0.12936299 1.9893659 -0.12740451 -0.49559012 0.20899858 0.3610033 -0.6500899 -0.21658574 -0.3855381 0.88717216 0.15434073 -0.38180098 1.1274192 1.1893336 0.5116243 0.22338742 -0.44897377 0.046196185 -0.031317297 0.19096558 1.1932951 0.78069407 1.4349201 -0.05461625 0.19531511 0.5788153 0.96686244 0.02314253 0.46302533 0.9740254 0.6304072 -0.1100836 -0.44860908 0.0963544 -0.006113122 0.5541759 0.32473308 -0.60847336 -0.24356453 -0.46533066 -0.4147566 -0.5737917 0.19731645 0.17082982 0.7099622 0.5097112 -0.5313502 0.50232077 -1.3257668 -0.5073379 0.7074358 0.5728934 0.27460128 0.0137331225 1.5712615 0.80443066 -0.022655176 -1.018287 -0.10551515 -1.0699911 -0.7019115 0.37888798 0.60749656 -0.1758154 -0.53535265 -1.1967477 -0.1837569 -1.3357344 -0.06390766 -2.4429617 -0.71879315 0.21543084 -2.1522245 0.063485205 0.5525497 -0.32227346 -0.029618682 -0.3618246 -0.8985078 0.54739845 -1.4354612 -0.74116737 -1.9883678 -0.24302344 -1.8093005 -0.22701675 0.19626574 0.50726414 -0.2319044 1.2552956 1.2897125 0.27776304 0.032063443 -0.6175508 0.025687024 0.3555731 -0.2057065 -1.2351775 -1.4488586 -2.2886162 -1.8469691 -2.3295107 -0.44767937 0.1526096 -0.7218935 0.691702 0.6286389 0.31596068 -0.24116607 -0.13040815 0.2881326 -0.7614488 -1.7903879 -1.9337512 -0.05495562 -0.88051957 -1.6157012 -0.69513434 -0.19248225 -0.083010346 0.36231646 0.47790146 -0.4603498 -0.45154113 -0.045486227
+0.055106346 0.41787943 0.23518866 0.31880543 -0.38273793 -0.2682766 1.0778155 0.4042156 -0.15291376 -0.47785726 0.963963 1.4249189 0.8985458 -0.27776447 0.019896533 -0.5812438 -0.06459716 -0.19112405 -0.62946814 0.54295 0.23195721 0.9534032 0.010409565 1.3205423 0.5932145 0.32752138 1.5774543 1.9195118 -0.030376928 0.13837379 -0.050915137 -1.4262233 -1.0085161 -0.3384635 -0.49806374 -0.9370172 0.4233807 -1.2942129 0.17231672 -0.420346 -0.9430473 0.048888467 1.7149798 1.5791808 0.4654308 -0.02723585 -0.66773456 -0.23915769 -0.1339207 0.33906785 -0.7057244 -0.37358785 0.22308213 1.0703917 -0.0502394 0.53472817 1.1990625 0.34926838 3.0624006 2.2754548 0.67102796 -0.8007039 0.05337989 -0.10574753 0.18577471 -0.5415903 -0.2886772 -0.66623336 0.28378597 1.4872406 -0.103914395 0.9737243 -0.6705913 0.871308 0.8050135 1.3667684 -0.7390036 0.18377334 0.01717305 -0.6959165 -0.4878973 -0.30563766 -0.817897 -0.068907715 -1.0615374 1.2313142 -0.082176894 -1.6712805 -0.99748206 -0.72470546 1.8750712 1.02685 -0.5561742 -0.3798324 -0.41354915 -1.0601358 -0.67894614 -1.2399262 0.5474436 0.43574274 0.8962048 0.29426882 -1.7655823 0.15747674 0.06847538 0.4006593 0.6911222 1.5354555 -1.6488825 0.05324268 -0.33505258 -1.1071844 0.52386737 -0.39782038 -0.8955007 -0.9092952 -1.7802556 -0.29051393 1.1783966 0.6313073 1.3691301 -0.0047625224 1.3301716 0.02845071 -0.9081102 -0.10457654 -0.46546888 0.17082238 -0.43628228 -0.22962645 -0.60518336 0.23394063 0.41293162 0.028935418 0.8656926 -0.095399685 -0.082757115 0.6850507 -0.27329814 -0.45683128 -1.1350302 -1.0679955 -0.3914897 -0.6356563 0.07577153 -0.37803873 -0.33781064 1.0344312 0.32822278 -0.102704495 -0.1184016 0.5760505 0.7050651 -0.054313984 0.627901 0.1575818 -0.30676356 -0.41679442 -0.045143526 -0.5813571 0.35624743 -0.0076093697 0.8080288 0.4550001 0.013023173 0.534028 -1.4493763 1.0299476 1.5145833 0.17779112 -1.5489109 -0.3239421 -0.54179335 0.21931967 0.65108496 0.16176315 -0.05891119 0.20800695 -0.2345356 0.44313958 -0.48574516 -0.34544384 0.09859439 -0.5213528 -0.5245651 0.42955816 -0.23714796 -1.7517997 0.3808775 -0.22120203 0.26605538 0.86619854 0.2691596 0.8758105 -0.29716095 -0.13610734 -0.9696699 1.0143903 0.8557493 -0.6038266 -0.94745547 -0.5068528 0.22818771 0.054011684 -0.06858439 0.4866945 0.1319572 0.8615501 0.7998346 0.6828944 0.63944304 0.43657514 0.11530824 -0.33770826 0.22265 0.10937273 0.28312284 0.7666026 0.4217091 0.16744028 0.3782038 -1.3412882 1.0369437 0.5680506 -0.089417964 -0.20818134 0.32926443 -0.015186675 0.78443193 -0.13253926 -1.0512727 -2.023833 -1.579744 -1.0990884 0.9569256 0.8925721 0.008449898 0.53423846 0.7768666 0.8219754 0.4070805 0.34116495 1.1216707 -0.77431947 0.81390816 0.36757034 -1.9675751 -0.5163851 -0.049916133 -1.5264827 -0.68539524 1.4031739 1.2979785 1.4941788 1.0870292 0.32022315 -0.024885263
+0.35187542 0.47315323 0.06375262 -0.18984222 -1.2736052 -0.8999239 -0.997694 -0.8987528 -0.47804478 -0.029478105 -0.019916669 -0.4369891 -0.8980929 -0.20077878 -0.10719385 -0.35689318 0.5283762 0.69769657 0.40552226 0.006296066 0.10760209 -0.69400287 -1.461945 -2.1827114 0.29208544 0.18536006 -0.5896288 -0.8280684 0.028656635 -0.09012071 0.59518677 -0.11544407 0.31213024 0.6489615 0.4345046 -0.8844129 0.08879119 0.20575026 0.6370033 -0.13517171 -0.15904762 -0.5102168 0.23000601 0.41792092 -0.02401795 0.3064715 0.1548897 -0.14003162 0.059351787 1.0375793 0.6588556 0.21779591 -0.26621693 0.75663906 -0.19510102 -0.56742275 -1.6483148 -1.6565671 -0.33008495 -0.5709284 -0.51975924 -0.076735534 -0.5761578 -0.15903087 0.07556984 0.061870556 -0.38959303 0.22724189 0.704476 1.4744277 0.017300272 -1.3317512 -0.41149396 -0.9121826 0.12576911 0.11322144 -0.49113247 -0.3358971 -0.28124732 0.11110153 -0.31282726 0.38829947 -0.12805547 0.39773807 -0.09190816 -0.55468875 1.6523923 0.6169196 -0.5511872 -1.1888303 -0.26298913 0.21944387 0.35538852 -1.0735103 -0.17800857 0.56086457 1.3576983 0.6732071 -0.21798316 -1.1658154 -0.32856852 0.117975146 1.4003668 0.6826456 -0.5661123 -1.5624797 -1.051826 -0.9114059 -1.5130702 -0.1632518 0.10499575 -1.5723661 0.5404572 0.005381779 -0.04897828 0.76718336 0.52789724 0.38978118 1.3306682 1.1104105 0.12930803 -1.6451412 -0.11925698 -1.2220145 -1.0614527 -0.21021625 -2.121614 -1.335459 -0.31422734 1.1435674 0.6884448 0.58587325 0.65584224 1.0281944 0.6277289 -0.09816445 -0.53129905 -0.73898196 -0.031157177 -2.344916 -0.63456124 -1.3838433 -1.2652844 -0.5972534 0.4595874 0.26999906 0.7784561 0.7761631 0.5333551 0.2531194 1.0774236 1.2955647 -0.2615722 -0.033877954 -0.7787763 -1.0830741 -0.98037475 -0.64917237 -1.0393287 -0.6947423 -0.58374244 0.56825346 0.9916346 0.7712292 0.024016809 1.6023302 1.4604108 0.7091672 -0.28946757 -0.50924796 -0.08101955 -0.2756575 -0.25395638 -0.6447907 -0.63869923 -0.32539478 1.0040973 0.5129646 0.2051001 0.328489 -0.13469598 0.8387987 0.902618 -0.46215934 -2.160162 0.04436235 0.56642556 -0.09076753 -0.5633889 0.08502111 -0.12905781 -0.15343633 0.8532503 1.2933145 0.89913267 1.733953 0.5114631 1.4074614 0.2260288 -0.31312484 -0.94419056 0.31887692 0.4334419 0.46193427 1.381849 -0.31689852 0.79904824 -0.17585358 0.5734938 0.21458276 0.15711688 0.3290721 0.5831648 -0.7637334 0.57381505 -0.8630074 0.2527237 -0.33452997 1.2638513 0.5631748 -0.10063373 0.40321678 0.4776547 0.4335605 0.31184343 1.0283524 0.27802232 -0.026462551 -0.21133558 0.12532602 -0.62760663 0.055672962 -0.57888365 -0.24829793 0.33881143 1.5783504 0.29588833 1.1031828 0.35389295 -0.26125258 0.48396507 0.27806476 -0.39384633 1.256167 -0.18086882 -0.02372104 0.60454524 0.8846328 -0.3249784 -1.5743482 0.5607076 0.61278063 0.2009954 0.52299225 0.3407996 0.44030198 -0.04769305
+1.0083325 1.2563883 0.3269431 1.3078287 0.84295434 0.5550376 -1.1927786 0.105989486 1.6804359 0.6015006 0.5888955 0.28701502 0.41692483 -0.20063019 -1.0671381 -0.27044833 0.8014692 0.32928216 -0.57570696 1.7109979 0.54568565 0.51998657 -1.543865 -1.6874943 -0.3404413 0.41200396 0.56588805 0.44190428 0.61120224 0.35038418 -0.46090522 -0.031548217 -0.40125713 -0.10589522 0.5869553 -0.35756853 1.1099161 0.83907634 -0.0050030835 -0.65228534 0.7374727 0.4172007 -0.2481021 1.0330265 1.0469184 0.1658152 1.0818397 0.20922245 0.47621673 0.12936024 0.9671128 0.16733892 0.34958866 0.9867477 -0.14550248 -0.19587873 -0.15191717 1.6282445 0.5961366 1.2804437 0.35263848 -0.42777455 0.6368977 -0.11226808 -0.37632692 -1.0876255 0.18628828 -0.4346012 -0.38747993 -0.8592341 -0.64622927 -0.8564642 0.41310352 1.140438 1.808226 1.9403195 0.93217474 -0.062393554 0.7576254 0.5279841 -0.1278205 -0.42025083 -0.17936504 -1.410886 -0.28456286 0.093892656 -0.22450067 -1.295944 -1.4105871 -0.1896959 0.7412809 0.67439556 0.8382402 1.1183988 1.6613656 0.6632143 0.50252956 -1.2373469 0.03698615 -0.5835882 0.9991381 -0.54000646 -1.0260727 -1.0240809 -1.6143155 -1.2315942 -0.6885135 1.2314854 0.77991295 -0.65210646 0.79229623 0.25512183 0.59785014 -0.28666192 0.3890677 -0.4417693 -0.7320765 -0.042777985 -0.3655988 -0.57088256 -0.11965964 -0.6321418 0.7329079 -1.3911293 -0.011395408 -0.004248459 0.22809032 -0.18939714 0.19686174 -0.47076246 -0.54999363 -0.09355236 0.4728932 -1.1669586 0.4945695 -1.234374 -0.8117787 -0.4626087 -0.40752622 -1.1011096 -0.9894822 -0.20655678 -0.49239063 -0.17434435 -0.69516337 0.43387577 0.25678688 -0.27931455 -0.41186506 -1.3642126 -0.3401552 -0.48386443 -2.7799659 -0.8124723 -0.6928424 -2.5047672 -0.86536664 -1.1230178 -1.4708076 -0.4061506 -0.30349925 -1.0279816 0.0933191 -0.43973824 -0.23978963 -0.44935736 0.5380542 -0.6819385 -0.87937945 -1.4573483 -0.34697774 -1.2184066 0.04650812 -0.9736743 -1.2382468 -0.44998327 -0.14902766 0.39681593 0.091613136 0.6755874 0.36920577 0.28002608 -0.07442839 -0.9075359 -0.9322349 -0.8278291 -1.1375368 -0.086287394 -0.41305074 -0.9738125 -0.8106865 -0.2164324 0.57028687 -0.13382965 0.60434943 1.5605409 -0.094388045 2.0543072 2.0888267 -0.10730177 -0.6925979 -1.3314468 0.0711253 0.3168844 -0.5939014 -0.19559003 -0.9159245 -0.27606642 0.5296954 0.6395445 0.46625546 0.11152852 0.35515478 1.1553466 1.5679377 -0.46183625 -1.4752636 -0.8791576 -0.52207905 -0.4630108 -0.1775305 -0.6851071 -1.7448527 -0.39789253 0.31087413 0.18025494 -0.015893191 -0.17907868 -0.39021474 1.2037607 0.3530627 0.75093013 0.15558794 0.48209253 -0.39278036 -1.5341489 -0.54984134 -1.1763713 -0.865672 -0.91032666 -0.20703177 -0.5498302 0.6994787 0.27411917 -0.3102672 0.3509157 0.5413362 1.1512954 0.100788124 0.013839475 -1.8755858 -1.9471835 -1.5138106 -1.1581895 -0.9587133 -0.72408 0.039137594
+0.2655536 0.20912734 0.27780163 0.5005239 -0.3929467 -0.39073962 0.68997747 -0.28114867 -0.030789051 0.903621 1.0055568 0.91974187 0.93287635 -0.5901137 0.42117637 -0.028239178 0.4146086 0.766711 0.056175023 -0.3398499 -0.64525175 -0.1718786 0.55026054 0.21018513 -0.6887068 0.31739333 1.5857122 0.7172532 -0.17307656 -0.10687053 0.4703224 0.53016156 0.42433354 0.082219414 0.17878774 0.23113619 0.17447498 -0.46316203 -0.07414455 -0.24828774 -0.5307544 1.0175544 1.8846009 0.67129517 0.35328257 0.56131697 0.6286371 -0.16028543 -0.2774467 -0.46737266 -1.1436111 0.5555589 0.5763477 0.11904423 -0.7030402 -0.11481525 0.99209714 0.8191825 0.62821525 -0.7257333 0.2869634 -0.3806461 0.1337369 0.6016811 -0.4804894 -0.6768394 -1.2537265 -0.743884 -1.4918047 -0.98992723 -0.78323066 -0.47366065 -0.110778786 1.2892164 0.57573706 0.2780828 0.13766941 -0.4876588 -0.5572461 0.7066157 -0.5047975 -0.40421748 -0.2030826 -0.33187494 0.1385277 -0.52379984 -0.91316587 0.20564246 0.5918553 0.9112933 1.0146444 -0.9965859 -0.23677862 -0.6138128 -0.08857286 0.19125019 0.66181374 -0.36628246 -0.63745594 -0.7338011 0.41698742 -0.6396078 -0.4105091 -0.88777405 1.0319741 0.686703 0.2902494 0.7569782 -0.45875964 0.6590497 -0.1553405 0.42167228 -0.24853961 0.34718272 -0.64157826 1.0135905 0.047022697 0.15919384 0.2633392 0.34297147 1.6605926 0.67582095 -0.5358262 0.67377067 0.97797024 -0.1398138 0.8866565 0.62661964 -0.799668 -0.08852595 0.16721325 0.76941776 -0.8758998 0.2439625 -0.37579513 0.7320505 0.6033613 1.5433972 -0.6763225 -0.06245375 -0.8907042 0.0024411832 -0.5088834 -0.5299431 -0.3628758 -0.35241425 -0.28805616 0.48546484 -0.16976687 -1.1666647 0.44220084 1.089552 0.1918446 0.42428505 -0.5981872 -0.48803848 -0.8898371 0.11159187 -0.75131 -0.008072262 0.2009443 0.34911662 0.29328454 -1.1172435 -0.20877276 0.19961467 -0.25070262 0.8052392 0.82128197 -0.39540523 -0.94573385 0.50537837 -0.35292855 -1.2966717 0.13053574 -0.4465895 -0.25852188 0.04011812 -0.3923933 -0.45251283 -0.34872177 -1.2026882 0.3665214 1.0865983 1.9186187 -0.2196125 -0.58682126 -0.7149792 -0.50436866 0.5268231 -0.07194176 -0.8251468 -0.8934988 -0.45575252 0.6223951 0.4525252 -0.34964642 -0.5640666 -0.48815215 1.0133675 2.754795 0.94271356 0.30777413 -0.16325808 0.03721818 0.45958883 -0.9498606 -0.35121766 -0.17576405 0.0027354737 -0.2206376 0.64727014 -0.11570348 0.44246918 -1.0919874 1.4266452 2.78685 0.20823571 -1.0009291 -0.6590832 0.2276835 -0.50296235 -0.38560033 -0.48608172 -0.3667926 -0.36799756 0.48414785 -0.0946934 -0.70191735 0.5990522 -0.3405101 -0.064496934 5.0091662 1.8647856 0.29655224 -1.1390755 -1.8193153 -0.024291452 -0.0134355705 0.17981693 0.41047746 -0.28326282 0.62764883 0.89132804 0.3661629 0.7736536 -1.0688847 0.13118355 2.2068124 2.0853252 -0.49834332 -0.9713015 -0.34099096 -0.4104785 -0.5950208 -0.16943587 -0.034320444
+-0.019013923 -0.5593278 -0.027655426 0.15936835 1.9508231 0.4179888 0.18382347 8.7720976E-4 0.6041585 0.63353336 0.8586137 0.9861417 -0.22249241 0.23859814 1.0306393 -0.15254892 -0.45547253 -0.15946929 0.43481642 1.1844281 1.2652506 -0.9114141 0.45439672 -0.92445457 -0.51044154 -0.5980822 1.0740143 0.74273217 0.28123623 -0.25998494 0.27141112 -0.310808 0.1687816 0.36144173 0.6729226 0.9282508 1.2282875 1.4944642 2.1318598 2.2798693 0.73654747 -0.543908 0.32156757 -0.59468603 0.5413016 -0.25123644 -0.33983743 -0.5008565 -1.6281133 0.26747704 -0.070319176 0.10498055 0.26886714 0.64451206 1.7145805 -0.39584637 1.328744 0.55130684 1.5316744 -0.3752583 0.38615364 -0.6801982 -0.25383756 0.09997121 0.036812443 -1.0732667 -0.07080488 -0.8428186 -0.28777385 1.4615359 -0.17730002 1.5752655 0.2228389 0.044306032 -0.28438708 -0.8279612 -0.40542278 -0.4508227 -0.4855347 0.11733689 0.16775374 -0.011684492 0.51585674 0.1650439 -0.26230016 1.0843524 0.4377971 1.4341329 -0.40667966 -0.13527119 -1.7408396 -0.4024227 0.9420831 0.51538384 -0.70313305 0.37670416 -0.36990282 -0.29155943 0.3091867 0.4596967 -1.1465932 0.035810772 0.68450165 0.26831222 -0.0351925 1.2034165 -0.3714581 0.7181595 0.63313377 -0.91201806 0.010928747 -0.47688216 -0.7221246 0.05560097 0.82698727 -0.1156754 0.1059059 0.124218844 -0.8364793 -0.6973174 0.78952956 0.6132329 0.52379006 0.8508437 0.1850855 1.1832836 0.060986165 -0.3729964 -0.6796061 -0.97323835 0.11984108 0.09425962 2.0139968 -0.042435423 0.19492005 -0.30046394 -0.104979716 -1.1802115 0.5039797 -0.5024298 0.49689642 -0.6821288 -0.45544896 -0.37709427 -0.81473136 -0.4967065 -0.005886022 0.71667606 0.8754708 0.20909333 1.5011494 -0.87936914 0.86911553 -0.210091 0.7751902 -0.8077408 -1.0505517 -0.88030976 -0.7196946 0.41301703 -0.0031905407 -0.10821255 0.04713516 1.4041843 0.85605687 -0.19094828 -0.500073 -0.5994427 -1.0239124 -0.62293416 0.22036822 -0.24719559 -0.7257256 -0.579403 -0.68912315 -0.028055057 0.8583942 -1.0166314 0.06581372 1.5040034 1.7057898 0.97553074 0.544345 -0.90888333 -0.0058637853 0.050625477 1.0351783 -0.22018136 -0.23649438 -0.5039499 -0.3727144 -0.47446975 0.0076442356 -0.37686425 -0.18941674 0.38914767 0.51185197 0.9048605 -0.44857833 -0.61072344 -0.5234435 -1.7413638 -1.0289229 0.48657188 -0.22008747 -0.47951075 -0.09340978 -1.3659654 0.21456048 0.42270896 -0.8650083 0.20079374 1.4290963 1.2700655 0.30864012 -1.1253992 -1.6627966 -0.055490006 -0.7111064 -0.43003562 0.21568038 0.16530405 -0.17617045 -0.63811415 0.8353782 1.0249264 0.121783346 0.7416036 1.5801564 1.0942514 1.7873352 1.2845874 0.20780191 0.15106182 -1.0947957 -1.4064367 -0.7041823 0.507342 -0.312557 -0.37684336 0.7351317 0.75828403 1.0594968 0.63269114 0.38714868 1.7092388 0.45921358 1.0377389 -0.90148944 0.65743774 -0.09331646 -0.060397107 0.1864507 -0.50751346 0.4991738 0.4223295 -0.0138865085
+0.18741937 0.05844517 0.107588954 -0.8741877 -0.33464214 -0.14754 1.9017572 0.62622714 1.3705214 -0.08919245 -0.35722572 -0.7956719 -0.18739957 -0.57257545 -0.07492495 0.1490324 -0.19184431 0.20078819 -0.17834684 -0.12593341 0.53071487 2.641591 0.7416391 0.029856639 -0.52545595 0.68071944 -0.628959 0.3205509 -0.14747715 -0.67109144 0.89112246 0.53295016 -0.08654375 0.16116631 -0.7502155 0.8142805 -0.5614757 0.61262417 -0.6215157 0.36224598 0.21214853 -0.07439313 0.773532 5.6553434E-4 -0.018394843 -1.0109906 0.2953082 0.25910404 0.65029526 0.43499723 -0.60934645 0.7752299 0.004911281 0.3752516 -0.1202372 0.46082577 -0.24737115 -0.19165471 0.34166917 -0.2630121 -0.5121444 0.04343497 0.92088044 0.57845634 -0.11260352 0.40832257 -0.2519616 -0.7626336 -0.24092267 0.31800893 -0.5379481 0.32397375 0.1151144 1.1187769 0.4342471 0.41548344 0.08669351 0.5618479 0.48308378 0.48131534 1.0433762 0.72784114 0.3679485 0.75082517 0.8353672 0.57721716 1.2699949 -0.67829967 -1.555115 -0.13472863 -0.2983059 0.7487707 0.20740932 0.7476599 1.8842788 0.7028376 0.9125145 1.1639436 0.39781398 0.63401926 1.8934692 1.392644 -0.2196824 -1.1790953 0.54124874 -0.40006465 -0.36222944 -0.037199058 1.429659 1.2408478 1.2483109 1.2455537 -0.011036427 0.85180753 1.7580289 0.7956996 0.9754138 0.90732765 -0.5544313 0.8570376 -1.4113396 -0.3677924 -1.2973725 -1.269597 0.37990695 1.0051597 1.6084625 1.9070588 0.7628624 0.6392008 1.7875148 1.7688146 1.147904 -0.32483572 0.08062799 -0.6931679 -1.1542838 0.4153268 -0.44436115 -1.4188575 0.89936477 0.45710486 1.5991627 0.75049907 0.099247605 -0.055834766 0.93848056 0.76077604 1.1250112 0.20561181 -0.3244176 0.18837464 -0.9486599 -0.3582709 0.45190865 -0.4391759 -0.74608123 0.7303873 0.9377955 0.49985382 1.6315415E-4 -0.71048754 0.50759405 0.22156022 1.4022765 0.83346313 0.20095845 -0.045196187 -0.13318294 -0.7125806 -0.42979443 -0.47496998 -2.564434 -1.8641908 -0.040227607 1.4219406 0.8213356 -0.6914582 0.016733743 -0.70375407 0.13795327 -0.1936324 0.53349614 0.6583703 -1.0996759 -1.588928 -0.096093215 -0.7258583 -1.1416292 -0.9010278 -0.64513355 -0.7005376 -1.0596285 -1.3595951 -1.1782464 0.107730724 -1.3089224 -0.8516331 -0.32558545 0.3778468 0.035222515 -0.11861295 -0.63473344 -1.3811933 -1.4265987 -2.0142145 -1.6190739 -0.12815966 -1.194475 -1.6335547 -1.0203099 -0.13419607 -1.0688349 -0.7662679 -0.17951438 1.1670516 0.9053126 0.101322144 0.011870901 0.40959594 -0.55034125 -1.0703675 -0.98098046 -0.9508273 -1.6664845 -0.5509703 -0.6564642 -0.6663612 0.5168781 -0.7112692 -0.96215266 -0.06871413 1.1977731 0.64040107 0.6185867 0.14775455 -1.6525166 -1.4229093 -0.96814746 -1.5374098 -0.40503716 -0.9312733 -1.2905409 0.30373734 0.056848325 0.30997863 -0.3582716 0.7434484 -0.05940083 0.060815886 0.69049716 -0.09523203 -0.9617932 -0.98904926 -2.5074627 -1.5517025 0.039358087
+0.1306675 -0.08810504 -0.19396697 -0.29684123 0.8419081 0.07944866 1.0660057 -0.16770437 0.3305021 0.1258698 -1.336586 -2.1338668 -1.8502316 -0.66511905 -0.58402234 0.13700725 -0.36705044 0.14300336 0.35747337 0.16752508 0.3771936 -0.34320626 0.30910847 1.2654301 0.9092736 0.11327631 -1.1850528 -1.6449164 -0.2559122 -0.77889585 -0.5960517 -0.48859814 0.05034162 -0.6584938 -0.99436843 -0.3694262 -1.2503501 0.39336658 0.77176684 0.47463343 -0.935319 0.05556002 -1.3496398 -1.4228431 0.73368686 -0.34985778 -0.08608003 -0.78112626 0.5887329 -1.3421826 -0.08992101 0.14594577 -0.50157607 1.4557325 1.8198694 0.0013160317 0.60683 -0.55778193 -0.5575817 -0.09262472 1.1252712 0.58344275 -0.23745406 -0.7179646 -0.12332561 0.20693398 -0.5665966 0.518605 -0.25163898 1.3262067 0.3251829 0.3713209 -0.4640877 -0.95281464 -0.9626222 -0.07193979 -0.9993373 -0.6258432 -0.014317402 -0.6060061 1.0015337 -0.56274146 0.87612915 1.2567742 1.5766723 -1.0615394 -0.1964796 -0.12142464 0.24061316 -1.3286275 -0.9467024 0.29178062 -0.20374396 0.033070173 0.008572113 -0.51294863 -0.10878155 0.5312089 0.009669434 1.5473503 -1.3356566 0.36500567 -0.4326106 0.68197703 0.064620145 0.18814391 -0.5316942 -0.25220403 -0.2076089 0.21329527 0.7067419 0.6407575 -0.61923915 1.2894835 1.2610555 -0.08628677 -0.42339805 1.2945117 -0.38575566 -0.039782163 0.11252348 -0.5577557 -0.7909287 -0.37564313 0.13342752 0.66995835 0.7468149 1.2021754 1.6553942 1.6992449 1.8834252 0.9232681 0.37345597 0.101350404 0.3771182 -0.93183315 0.020668877 -0.5793435 -0.092787206 0.84792066 0.44711718 1.1221637 0.984094 1.2014402 0.049333956 1.951225 1.6126589 0.5021369 1.4279804 0.9476543 -0.2252602 -0.48744276 -1.3472203 -1.1088169 -0.8772582 1.1987839 0.7978504 1.5244353 0.73576343 0.48078197 0.4330286 -0.03606264 1.3125789 1.4080673 0.7606048 1.9725347 -0.3275315 -0.81802684 -1.2370794 -0.04448072 1.0570064 -1.0670487 -0.01366351 0.3491928 1.0166076 0.50396436 0.6142331 0.44755024 -1.2607465 0.88886386 -1.6459436 0.30220723 -0.39302492 0.061551835 1.0141339 0.9072057 0.32577202 0.06940849 0.3417613 -0.9067647 -0.2689841 -0.010047809 -0.016350148 -0.401158 -0.9121348 -0.9606257 -0.61177754 -0.7954506 -0.07191235 -0.63594514 -0.23767728 -0.33685645 -0.97194004 1.781143E-4 0.5901478 -0.10614153 0.6038026 0.77489203 0.14725341 0.36429745 -0.38412973 -0.8017012 -0.59188765 -0.8254027 0.32416984 -1.1293834 0.72122455 -0.89456296 1.1095755 0.7870492 0.35010624 -0.25735247 0.6429504 0.65076756 -0.8703204 -0.07841424 -0.5781882 0.1701073 0.14269476 -2.8296328 -0.37793267 -0.53420335 -0.12929243 -0.8566317 -0.8912634 -0.63812417 -0.52143586 -0.6853084 -0.14494348 0.100307934 -0.12786727 -0.24725899 -0.5108697 -0.23390871 -0.5116105 -0.92768705 1.1467588 -1.2634263 0.27012143 0.7013687 0.48235458 -0.39544111 -0.5257143 -1.0676401 -0.33533847 -0.6315007 0.049996994
+0.4210941 0.77483416 1.3594465 0.43669483 -0.3352457 -0.72765136 -1.0211859 0.42879608 -0.2534454 0.6383494 -0.6071047 -0.123940825 -0.458861 1.4483968 0.28250518 0.43770674 0.7949274 1.32611 0.44338778 0.36182818 0.42772445 -0.8841169 -2.342006 -0.8975124 -0.17597891 -0.2925875 0.022505436 0.0673628 0.33149216 1.3377577 0.39020646 0.7783739 0.9203709 1.2941694 0.25351226 0.16446339 -0.19610426 1.151762 -0.14623557 -0.40543097 -0.30726853 -0.89575356 -0.08694243 -0.02517721 0.57705283 0.8107148 0.19896336 0.772632 0.62407374 1.0977383 0.4058518 -0.27118015 0.38478938 0.04023144 -0.47299173 -0.4752893 0.11547797 -0.077342875 -0.058772583 -0.3066454 0.17875512 0.62061775 0.33977917 -0.36598167 0.77629983 1.4175409 -0.21028851 1.2956944 1.160431 0.23782459 0.11092974 0.7030824 -0.03260208 -0.14684784 -0.47262987 0.49788982 -0.33076137 0.77042115 0.8705107 -0.33558515 0.6947941 0.588054 0.19616725 -0.45370013 -0.74690586 -0.62219197 0.6539602 -1.4232413 -1.2672135 -0.41534135 -0.8763528 0.14001098 -0.055034157 1.1023037 0.96821004 0.43608975 0.40904504 0.25809816 1.5323129 -0.6495836 -0.3819064 0.5494483 0.7941229 0.19491106 0.053876277 -0.8309649 -0.4689027 -0.9852825 0.6139256 0.42964518 1.5733179 0.39989507 -0.18118137 -0.24074502 -0.18040209 -1.2791779 -1.1357889 -0.3394489 0.31559852 0.35075733 -0.9291603 0.37264585 0.9622106 -0.7675911 -0.2784752 -0.80266756 1.3543022 0.5034601 0.14490469 -0.43616825 -0.82071334 -0.5963965 -1.0204768 -0.97799283 -0.31616393 -0.35395908 -0.23198141 0.72689754 -0.7445571 -0.9527641 -0.48993194 0.6126473 0.6674658 0.060332883 4.89312E-4 0.19321942 -0.21504353 0.46539193 -0.5137827 -0.18670382 0.42881304 -1.2561538 -0.28432533 0.054970324 0.31906644 0.6543109 0.7446261 -0.33894786 0.78154474 -0.18325603 0.4521652 0.6722504 0.78073466 -0.30515453 0.13005808 0.69470745 1.5532869 0.05543797 0.2428854 0.74492663 0.82593 -0.80344 0.9540927 0.14438836 0.6988349 0.3114309 -0.15200575 0.84485173 0.14251311 0.24640386 0.7768309 1.1810362 0.93135256 -0.50187516 -0.061778985 0.59501654 0.6780112 0.81371427 0.3908225 -0.86442715 1.2047373 1.3188055 0.7961464 0.85895765 -0.18715236 -0.06702574 1.8268923 1.4873521 1.5049443 -0.043345466 -1.11349 -1.6473024 -0.22649497 -0.8012598 0.39231023 0.35135978 0.98484087 1.2620138 0.5711644 0.27800778 0.46492106 1.04483 0.2451862 0.1478414 0.27078772 -0.90838677 -2.5203257 -0.6743923 0.6178843 0.036686473 -0.82106036 0.17562672 -0.36127123 0.42664292 1.2804699 0.054801844 0.43787256 0.025435165 -0.17659584 -1.8994148 -1.4006037 -1.4436747 -3.0916028 -1.3738126 -0.39677885 -0.9717314 0.56512487 -0.2759742 -0.15146157 0.46004313 -0.06915695 -0.12653224 0.6501409 0.87865096 -0.11854227 -0.8397493 -0.5506388 -2.216401 -1.7679112 -1.7093164 -0.48267815 0.66151696 -1.1707624 -0.7387133 1.1608672 -0.23390184 0.04481526
+-0.06614741 -0.8926074 0.05276698 1.2399124 -1.4459828 -0.3377294 0.50482833 -0.9844524 -0.13597798 -0.84957665 -0.38065082 -1.1380565 -0.124213524 -1.2788005 0.1844367 0.41543773 0.7815851 -0.5048512 1.1194943 0.6624772 -0.30422455 -0.63167226 -0.3420317 0.2389154 -1.063399 -1.2762705 -0.6999134 -1.7727294 -0.74758184 -0.71677494 -0.8482182 -0.5533826 0.68549556 -0.65717685 -0.7988141 -0.5636738 -0.59556884 -0.6642837 -1.4485155 -1.3983487 -0.8643846 -0.7271305 -0.31838098 0.48474824 -0.71174 -0.32922897 0.15820013 -0.61629933 0.19805174 -0.16302434 0.82739514 -1.3442092 -0.5520568 -0.6563903 -1.4083201 -2.19293 0.026580691 -1.5793334 0.06845715 -1.1804434 -0.56006396 -0.12925798 0.20952812 0.600184 -0.45223188 -0.16853012 -0.8032871 -0.3958787 -1.2713045 -1.1402345 -1.3528425 1.171329 -0.78496253 0.024725191 -0.49281192 -0.059761062 -0.36873296 -0.32990417 0.46543545 0.84886724 0.13418995 -0.15525001 -1.739297 -0.7640571 -1.9102812 0.42043835 -1.8117547 -0.6264603 0.69193476 0.18242198 0.42873016 -0.5019057 0.056793384 0.79430294 -0.08620918 0.2815069 0.6784726 -0.34102148 -0.2875736 -1.1952902 -0.628488 -1.801299 -1.2676896 -1.8025494 -0.11287571 -1.030694 0.025024781 0.7863675 -0.625579 -0.96351177 -0.995239 -0.7757474 0.40900737 -0.56083745 -0.1608678 -0.37373102 -0.036708973 -1.813104 0.14581451 -1.6458843 -1.7676811 -0.508144 -1.2458857 -0.74957746 0.20277797 -1.3085921 -1.809385 -1.3513765 0.21405584 1.3439068 -0.08889395 -0.39016798 -1.1737773 1.6099886 -1.5271802 -0.4115741 0.5421425 -0.9341052 -0.16714327 0.468465 0.13337651 1.2134591 -1.2681372 -0.44610316 0.28835052 1.3327407 -0.26625508 0.93017167 1.5444958 0.95526314 -0.33739418 -0.99384886 -0.4981343 1.3509305 -0.6409635 0.286561 0.04807017 -0.16463104 -0.7979799 -1.1177033 1.7890214 1.8892144 0.68588984 0.51101744 0.97111213 0.20866822 0.83101887 1.9672662 1.3243285 0.6483589 1.123383 1.220378 1.3064064 0.9077638 -0.7821262 -1.6894144 0.69090945 0.86924183 0.5950807 1.3171443 1.7528026 0.67553115 2.1554809 1.4707098 2.4038281 1.6458343 1.3644614 0.9931186 0.9715952 0.42306644 -1.8463933 -0.18495426 0.56331486 0.024575418 0.30241883 1.3717574 0.62928313 0.621776 0.80487674 1.618193 1.6118346 1.1746613 1.2526987 1.6436434 0.28303456 0.46151245 -0.27341285 0.5921522 0.61520517 0.025880096 1.1226492 -0.4542963 1.1819191 1.5735483 1.1764187 0.70955795 1.1176461 1.023221 -0.49247834 -0.19491778 -0.18913862 0.060736127 -0.6310814 0.80882835 -0.48169 -1.0323639 0.42778757 -0.3811688 -0.3061145 0.07213724 1.0811404 0.51909345 1.3032093 -0.35248837 0.24872433 -0.059474163 0.21838465 -0.6043323 -0.5254696 0.77191216 -0.33008608 -0.3733788 -1.1724132 0.41638252 -1.0570074 0.8221327 -1.0082321 1.1047982 0.37184864 1.0501375 0.03284817 0.04258604 -0.8418931 0.68144476 -0.45083743 -0.049162135 -0.009801069
+0.99136937 0.09246654 0.40818566 0.6898116 1.136634 0.09465015 -0.56463534 0.75223464 -1.0390077 -0.794109 -0.17543107 -0.23912679 -0.5593342 0.49641782 0.34359542 0.35128918 0.28790897 0.7145811 0.45953587 -0.40440863 0.32557824 -0.22195394 -0.7860361 -0.7698743 0.1644437 -0.5036998 -0.16777912 0.81722176 0.79438764 0.9637863 0.1870715 -0.4959964 0.7790271 -0.3065376 0.768382 0.1646769 1.0312743 0.86403686 -0.31791478 0.4164355 -0.19857281 0.4326466 0.80954033 0.111520626 -0.0014193997 -0.55442333 -0.65743667 -0.27334628 0.98518497 0.07175062 0.7445575 1.0181185 0.76550007 0.97648156 0.09430475 -0.55809706 -7.3163904E-4 -0.31632668 -0.77268726 -1.18394 -0.4464234 -0.7718449 -0.58454543 -0.35792625 0.7643546 0.34281516 -0.15706573 0.73725224 0.06572232 -0.09317381 -0.49958158 0.2207807 0.2510782 -0.6656277 -0.36778265 -0.62175554 -0.55392456 -0.076036684 0.55512685 -0.029001923 -0.4907282 -0.14346306 -0.8095675 0.17758994 -0.42599648 -0.7750492 -0.9804896 -1.7508664 -2.0438032 -1.2802098 -0.1680486 1.0452222 0.5926337 0.012853365 0.073275864 0.46175304 -0.71636605 -0.5204106 0.044962384 -0.27308643 0.50472385 0.37090364 -0.8469607 -1.6211667 -0.8287603 -0.42990693 0.22054495 -1.1086417 -0.24006237 -0.6042538 1.2089908 -0.0017449564 -0.7170346 -1.2352537 -0.35825136 0.42084396 0.33832428 1.5152899 0.3795515 -2.108959 -2.558984 -0.79628086 -1.3921136 -0.25077218 -0.6782765 -0.073621 0.23745659 -0.50686175 -0.57528526 -1.0680438 -0.53323215 -0.89074993 0.1941403 -0.15798885 -0.3711014 -0.4342436 -1.6357392 -0.54980314 -1.3744549 -0.28576785 -0.92837 -0.045658257 0.41462237 0.6954067 -0.24008644 -0.115207106 -0.2582881 0.3740109 -0.19415247 0.821061 0.8701913 -1.3941127 -2.821885 -1.6139889 -0.44020027 -0.27241728 -0.15551184 0.04789109 -0.10775649 0.755617 -0.03876054 -0.50327694 0.016925905 1.1023417 -0.46971074 0.88026744 0.12574364 -1.5785416 -1.2478677 -0.28868246 0.22684672 0.6522745 1.3196474 0.6582475 0.14248073 0.4581836 0.12507701 -0.2655937 0.4034478 0.38806748 0.7328675 -0.18048367 -1.2674963 -1.2245164 -0.4558096 -0.5719185 0.25579906 1.830696 0.3053418 0.1671748 0.23435274 0.5492895 1.5517159 0.1227049 0.32677802 1.1780509 0.006964192 -0.53909475 -1.9572576 1.3261793 0.08825341 0.9409628 -0.10142962 0.63817495 0.6267152 -0.022781461 0.35748106 0.9751376 0.6750582 0.7796589 0.81998575 -0.2720885 -0.62825286 -0.16573223 -1.4242421 0.5944467 1.1269808 0.10636902 -0.57705986 -0.79921365 0.3948552 -0.20226131 0.4685862 0.7693531 0.24259667 1.3187951 0.317214 -0.500581 0.27402875 0.01751779 -0.39377698 1.058657 1.4036154 1.4066471 -0.05741865 -0.036457647 0.6337977 -0.28971574 0.8763883 0.15645993 0.22220317 0.07507053 0.2076764 -0.80390394 1.0592434 0.40609998 -0.43888524 -0.1763856 1.6350197 0.88246363 -1.3624909 -0.64572537 -0.028769583 -0.572493 0.9075763 0.43909055 0.03335878
+-0.039897453 -1.0473305 -1.9738395 -0.08066083 0.4563154 -0.13469718 -1.0974445 0.28575954 0.8151633 0.35870752 -0.32288024 0.038713247 0.10632907 -0.91031206 -0.7445392 0.15077108 -0.6562413 -1.6421809 -2.3477588 -1.17706 -0.6693971 -0.16072616 -0.6345176 0.19711642 -0.07223625 -0.18081397 0.17301075 -0.55957085 -0.059711598 -1.0209014 -0.43979123 0.14343801 -0.95046276 -0.86193275 -0.31555238 -0.9933889 0.15957284 0.5115487 -0.25687563 0.054727387 0.52195686 -0.64632154 -0.4230632 0.5534575 -1.2414242 -0.8522004 -0.47469336 -0.23470555 -0.52015734 -0.55574405 -0.27578256 -0.3890521 0.24994518 0.3679207 1.2684208 0.64534587 -0.24598277 0.49023935 -0.7341304 0.67510086 0.26612106 -0.11576529 -0.02725733 -0.23683588 -0.0025211372 0.02948535 0.4021133 -0.29726163 0.10534527 1.0569327 0.388026 1.9897652 1.4538614 -1.6077824 0.1329702 -1.5669914 -1.4391166 -0.32774863 -0.7142928 -0.53601605 -0.16672859 1.1276579 -0.17643255 -0.98151994 0.09354474 0.96313804 0.6437594 0.6296946 0.34994122 0.7457549 0.14358687 0.26462686 -1.3088158 0.024541581 -0.43706462 -0.6511224 -0.11883346 -0.32913604 0.29359195 -0.5068262 -1.695331 -0.7313914 -0.52220166 -0.2495566 -0.14114481 -0.13790736 0.8967666 -0.40110245 -0.36840284 -0.2969995 0.3566827 -0.72135484 -0.41681522 -0.5289749 -0.3431689 0.638472 -0.26084358 -2.1944 -1.8794001 -0.21858898 -0.15911117 0.22400767 -0.30488864 -0.086543284 -0.24934469 -0.20108935 -0.33416805 -0.48851737 0.68313515 0.023350602 -1.2734734 -0.37844938 -1.8323437 -0.16246755 -0.56913996 -0.55498374 -1.4006218 -0.74688464 -0.63984466 -0.76999414 -0.35630453 -0.7868165 -0.0064486037 0.14455482 0.19096488 0.8459263 -1.5671661 0.30203977 -0.13885438 -0.99505806 -0.78312266 -2.2602646 -0.19843014 0.19578306 -1.7278367 -1.1866204 0.373928 -0.47077668 0.51647496 0.34682763 -0.58979386 0.58315593 -0.023061303 -1.8893011 -1.1615055 -1.5630709 -0.88493294 -0.22250398 -0.10023446 0.9788492 0.6778828 -1.1908646 -0.04219563 0.39587852 0.22889104 0.73442614 0.3023371 -0.21472123 -0.057378404 -1.6932135 -1.4380265 -0.31013304 0.0071681673 -0.8875245 -0.4263981 -0.5434434 -1.8887312 0.5916187 0.2406423 0.292083 1.3467373 0.51212585 0.44196978 -0.9748935 -0.1733285 -1.0500205 0.44180337 -0.0028115935 -0.14590004 0.79631627 -0.1076867 -0.59319293 0.77230585 -0.4059036 -0.5149853 0.46749485 1.0264856 -0.62003356 -0.1214978 0.08076122 0.26451445 -0.022219539 -0.3736543 -0.17178112 1.6801683 1.6244713 -0.2459859 0.044527866 -0.20127755 -0.3286216 0.4934219 0.49906483 0.7518498 0.41540352 -0.011397177 0.7633044 0.09447985 -0.46327302 -1.8151445 1.208857 2.09573 0.92051345 1.5730945 2.0012982 0.444456 1.6042355 0.80587304 0.87949663 -0.053663764 0.7995906 0.10809081 -0.08975346 -0.022907007 0.42839795 -0.18389878 1.1502995 0.15184148 0.67377484 0.5720212 0.7607991 0.61176366 -0.2233229 0.23642074 -0.4032493 -0.05701997 -0.049058806 -0.029168418
+-0.3120106 -0.6726388 0.60258967 -1.3128567 0.76199263 0.3557241 -0.9529979 0.7796131 0.04189878 -0.5133918 0.30820948 1.4955852 -0.90046144 0.4743241 1.0590048 0.69147533 0.50355023 -0.27380842 0.22927956 -0.61967474 -0.5505922 -0.59860414 0.5804434 -0.33480558 0.05921459 -0.06914764 -0.728996 0.083487235 0.30173978 -0.17253156 0.17440605 0.10289021 0.4643948 1.109889 -0.39753604 0.5432495 -0.9563993 -0.6395443 0.57042366 -0.45023495 -0.74501365 -1.8015321 0.1269381 -0.18787786 -0.6053487 -0.7521008 -0.7985911 0.21157682 -0.5494122 -0.13889028 -0.6792477 -0.7025897 0.2494581 -1.58277 -0.8791207 -1.0855435 -0.96735644 -2.616132 -1.2924019 -0.9570277 0.20615286 0.3274567 -0.5841676 -0.43353394 0.35690147 0.14250748 -1.314844 -0.7796601 0.16459872 -1.1619126 0.1213033 -1.0912149 -1.2173625 -0.9434216 -2.0208557 -1.6634464 -1.4461288 0.5500558 -0.2910044 -0.115702674 0.16718198 0.44069552 -0.48567572 -0.17897172 -0.24855797 0.082272016 0.939331 -0.3249579 0.4910915 0.12885134 -1.6661794 -1.6972398 -0.85704464 -2.2558632 -1.0548764 -0.0044229673 0.31638232 -0.28892875 0.4634995 -0.91866976 -1.4944475 -0.3021254 -1.488098 0.9607544 1.012584 0.9903948 -0.7921884 -1.5839449 -0.9420013 -3.0950303 -1.6541036 -0.21768336 0.11262922 0.07333207 -0.8664438 -1.2089671 -0.48067153 0.6230414 -1.2906172 -0.063141234 -0.61222774 -1.2940862 -0.863175 -1.5922889 -0.17285223 -1.5164113 -1.9732398 -0.38451457 -0.7511857 -0.23926823 -0.309276 -0.74424756 -0.5115918 0.04487617 0.9503431 2.2261858 1.2033042 0.2983033 -0.20054303 0.7478195 0.44720647 -1.3701164 0.025076078 -0.18550505 -0.5416217 -0.7460135 -0.5745824 0.18354633 -0.1688947 0.7483712 -0.37131009 1.5588146 1.3242908 0.528965 0.10354441 -0.10095797 0.78019553 1.2563998 1.8420073 -0.053465147 0.22566733 0.25211 0.06683271 -0.049312428 0.6732234 1.0140339 0.49816212 1.5720763 1.1911975 0.5771229 0.86190647 1.5578518 1.8198541 -0.22855377 0.46666124 -0.73833746 0.65381795 -0.57841384 -0.19229726 -0.80294025 -0.9010407 -0.6571466 -0.17809997 0.23394789 0.65087783 2.4263923 0.82482314 2.0951633 1.7224741 1.3204674 -0.088583775 -1.1698322 0.792496 0.2713486 0.9578671 -0.29220566 0.993994 -0.72219205 -0.7276477 0.44314006 0.31814057 1.0070264 0.50891143 0.12557253 0.6881946 0.84876996 -0.25030148 -1.2812297 0.30205172 -0.28698242 -0.5528458 0.64715827 0.16514951 -0.3698934 0.14115977 0.094269656 -0.31602782 1.157565 1.0699493 1.049596 -0.17961133 2.5326138 0.28848273 -0.20890869 1.4571124 0.71821654 0.80710626 0.33683085 -1.4096146 0.102418914 -0.18468335 -0.27584943 -0.2157589 0.7233689 0.66270155 -0.1307133 0.87076336 0.76056916 0.6978896 0.9603978 0.47199434 0.8328178 1.2448459 0.6661133 1.0701189 1.152887 -0.26890662 -0.09190631 -2.049034 -1.3874335 -0.28492087 0.4319162 0.8455813 0.04454681 0.43607768 0.10287074 -0.0077168234
+0.83506364 1.3421296 1.5210059 1.3019994 0.9610961 -1.739915 -1.9840068 -0.04264199 -0.6492746 0.68140537 0.584721 -0.50890785 0.8602347 0.101917446 -0.12653388 0.21392709 1.1713158 0.944732 0.21204717 -0.5445348 -0.024603257 -2.1586475 -1.5385782 -1.9237825 0.17006885 -0.6225963 0.34583613 -0.21739545 -0.07090213 -0.011476703 -0.48340118 -0.6838255 -0.23365282 0.02912118 1.0778679 -0.25725135 -0.3123358 -1.4048775 -2.0190563 0.26838276 0.58599436 0.24957927 -0.016513485 0.8923641 0.559474 -0.034272183 -0.7988706 0.09069047 0.5885798 0.2722873 -0.018969087 0.7194841 1.0880713 -1.2998073 -1.0968001 -0.22436075 0.50076574 0.37027344 -0.17653486 0.08530361 -0.7507347 -0.26017633 -0.30614597 -0.6397796 0.32650164 1.5644566 0.6466497 0.21210513 0.27389944 -3.2060852 -2.481006 -0.41008386 -0.2615226 1.0012318 -0.16333133 -1.0771081 -0.91497767 -0.21408942 0.07782232 -0.33465534 -0.1546389 2.1037476 0.39766496 2.100532 -0.056788098 -0.8399829 -2.4874034 -1.789557 -1.3241444 -0.64177966 -0.1171624 -0.24609071 0.10654199 -0.3102452 -0.520529 0.18710357 1.0847559 1.2085757 0.67875844 1.3253442 0.63724583 -1.4978675 -1.997485 -1.4112675 -1.233663 -1.0129968 -0.96145684 0.42385033 0.5533441 -0.21198024 -1.0468575 -0.7829186 0.29263023 1.0066077 0.6659909 2.012192 1.6455915 -0.52581203 -1.5679635 -2.0220509 0.026615676 0.38267308 0.75380784 -0.45124176 0.015365636 -0.3559177 -0.98606944 -1.1616826 0.17799117 0.9295973 0.5999197 0.14045523 0.4007424 -0.13226959 -1.8109767 -1.7856138 0.14218451 -1.3100963 -0.22484827 -0.42157724 -0.29283652 -0.8557078 -0.8586125 -0.10246858 -0.07855992 1.4495137 0.38129178 1.2284194 1.8776028 -1.2727954 0.2659428 -2.6059823 -1.1936778 -0.44642913 -1.1384927 1.1437601 -0.7967337 -0.5350143 -0.54894686 -0.49834546 0.7520217 0.52263373 0.85001284 1.1398795 1.004755 -0.9312969 0.23547858 -1.9469633 -1.7580523 -0.082218155 -0.80273765 0.047082074 -0.94762677 0.20558406 -0.031200768 0.021163927 -0.74074316 0.4340175 -0.47145703 0.5286464 1.0852997 1.2367783 0.48478878 -0.9654492 0.4917852 -0.9244092 -0.9365091 -0.29637763 -0.29930514 -0.61317694 -1.3450433 -0.31489068 0.35420752 0.36446935 0.0041762735 0.9440381 -0.05520865 0.24927129 0.6771713 -0.33180583 0.3055281 -0.23946442 -0.67399293 0.7612811 -0.32506862 0.8955687 -1.2064948 -0.45044944 0.40118122 1.0874803 0.55278087 0.5813416 1.6123616 0.07771178 -0.44136363 -0.10084999 -1.1649927 0.1125998 -0.36914265 -0.23696212 -0.10186324 -0.06214986 -0.08817334 -0.3184891 0.6435502 0.14844123 0.18915746 0.2107515 0.19991894 0.3250235 0.5507905 0.58663964 -1.2015544 -0.20834622 -0.015881917 0.20038559 0.120813616 -0.0806207 -0.26918548 0.26010352 0.7302696 0.70229346 -0.11256377 -0.42905158 0.67258906 -0.3096032 0.32874584 0.06332257 -0.20829864 -0.4936469 -0.4174535 -0.0886893 1.0078698 0.5971958 0.26237556 0.32907897 -0.02251101
+0.26627624 1.2794242 0.10201574 0.24746257 -0.23607011 -0.31842032 1.4573634 -0.9079472 -0.12430162 0.9856307 1.1890104 -0.08302925 0.68327427 0.97976995 0.22728282 0.36401814 0.49890426 1.5966877 -0.16835497 0.440177 0.70625436 0.65729636 -0.47176278 -0.24504955 0.41123194 -0.31326038 0.33909675 0.1006596 0.21352912 0.5775627 0.41820878 0.4948848 0.1901451 0.48021165 -0.1986007 -0.2643754 0.28204012 0.29747897 0.98829967 -1.2417984 -0.060544103 0.009890452 1.4805177 -0.8054715 1.1026652 0.7458687 0.34330663 0.3805003 0.08593417 -0.1393559 -0.5471644 -1.1897794 -1.2021387 -0.36041594 0.1575728 -0.4815413 -0.6868118 -0.37451565 0.31544405 0.21520571 0.6526446 -0.899275 -0.052225575 -0.7244397 0.678072 0.05852802 -0.4350725 -0.886178 0.36397865 -0.102070615 0.16155972 -0.37161672 -1.4925286 0.44666424 -0.22629082 0.99753165 1.289759 0.16665909 1.1053238 -0.26616535 0.4702175 -0.059588015 -0.26468447 -0.39551204 -0.57120687 0.4127524 0.22469702 0.19215158 1.6001155 0.8798971 0.46559018 0.4933919 0.4031975 1.0216298 0.48250702 -0.9872642 -0.73771125 -0.57839656 -0.48791656 0.020454284 0.66101485 0.49601507 0.42649677 0.74785995 0.39965534 0.8877099 -0.0538483 1.5209944 0.7498982 0.5595456 1.0149499 -1.3384172 -0.37910232 -0.9881384 0.66690034 0.09498336 0.019755524 0.2624524 0.3504068 -0.12533778 -0.6711226 -0.09526164 1.6328859 0.31502897 1.0187763 -0.23861068 0.3264509 -0.41669607 -0.064021826 0.21477923 0.53160363 -0.101083346 -0.06801364 0.30233788 0.13410288 -0.21594062 1.5753762 -0.584327 1.2636567 0.936136 0.8104549 0.9259895 -0.27314115 0.13179111 -0.329048 0.20315674 1.1487744 0.3896666 0.37655944 0.29076 0.4436086 0.5410485 0.31306154 1.2307329 1.2451975 2.1324236 0.70392454 -0.43786788 0.93273205 -0.0046542175 -0.68098193 0.3633843 0.42139354 -0.80391634 0.8775776 0.33957165 0.5100352 0.8453441 -0.27119488 0.95969516 0.45136046 -0.08584012 0.05256442 -0.40977988 0.33684868 0.09168009 -0.67006814 -0.31317982 -0.9014017 -0.74368525 -0.68812495 -0.45921516 1.1459609 1.6853166 0.14699925 0.33582166 0.61561865 -0.1326604 0.8583575 -0.3137047 -0.27996 0.930401 -0.14802364 -0.19956206 -1.2979473 -0.18164228 0.56689984 -1.5888208 -0.27858996 -1.0993297 0.7438903 -0.7486228 -0.49765107 1.1147417 -0.021733899 0.9812515 1.1208563 0.18688397 0.2289556 -1.0049201 -0.9808243 -0.5221787 -1.0764918 0.31901884 -1.7285892 -1.4299401 -0.6043177 0.95149577 0.11063148 0.8391988 -0.14575419 0.47303125 0.3364003 0.6852922 -0.166354 -1.0250744 -2.3178432 -0.2509298 -0.32924733 -0.28221187 -2.6196456 -1.883239 -1.3955524 -3.0056043 -1.4162631 -1.7074177 0.255873 0.4454009 0.42515004 0.8183279 -0.29623544 -0.50075257 -1.4718046 -0.46793982 -1.2258286 -0.13568209 -1.0516437 0.60931015 -1.4979763 -0.57499593 -0.5174677 -0.009882827 0.843424 0.54160523 0.13642317 0.45373288 -0.022189317
+-0.02171785 0.603866 -0.36583036 0.58430374 0.36794236 0.1592504 -0.104343645 -0.8456701 -0.037794493 -0.31476888 0.5072387 -0.6236462 -0.09010266 -0.2944715 0.10946082 0.47240978 -0.21059136 -0.4043218 -0.79813564 -0.002387006 -2.2281737 -0.87775344 0.0022188618 -1.0328627 0.97783536 0.88703305 -0.61239314 0.5263094 -0.044581853 0.041845873 0.6156344 0.057307716 -0.8777092 -1.1526065 -1.1508079 -0.18852797 -0.86723113 -3.7178528 -3.128753 -2.852161 -2.2956445 -1.3032941 -1.4694724 -1.4875205 -2.1135542 -1.2859925 -0.56537014 -0.026899062 -0.6589382 -1.3601643 -1.2287797 -1.7440923 -2.4108098 -2.1365104 -3.0533073 -1.8641765 -3.7451322 -3.1614501 -2.9145923 -1.7408599 -1.3947519 -1.752016 -0.79600793 -0.5607197 -0.4435104 -0.29960564 -0.7684002 -1.4491597 -1.2988256 -1.7022371 -1.3784579 -1.063967 -1.7639692 -2.595215 -1.1966287 -0.948805 -1.5818723 -0.9132796 -0.5368405 -0.14898358 -0.9266239 -0.5311515 -0.5221394 -0.22751202 -0.5290409 1.4305174 -0.04894102 1.8265452 -0.10863401 0.70622677 1.3305945 -0.6371118 -0.25508776 -0.7116915 -0.1621196 0.028408915 -0.5515177 -0.4256775 -0.119045004 -0.0028868755 1.7047099 0.65529007 0.290463 0.2645048 1.1118442 0.08760529 0.35812777 0.6402641 -0.19340418 0.047335222 -0.25716418 -0.3357477 -0.028790148 -0.6340571 1.9856257 0.46009827 0.8366939 1.2006122 1.772615 0.70024043 2.0800645 0.41881752 1.9341432 1.3697416 0.2151358 -0.37917376 -0.46087041 -0.4330339 -0.3989405 0.38897437 1.7815127 0.87810373 -0.09691813 1.0793978 -0.30144322 -0.1332004 -0.47295305 0.052805353 1.3968022 -0.4405524 0.5615078 0.07214186 0.11452939 -0.43489254 -0.5254758 0.24991584 1.9852307 0.24795821 -0.19427969 -0.78738105 -0.2594365 -0.6366712 -0.059418768 -1.0128697 0.119840816 0.6233335 -0.8563437 0.16562214 -0.15575652 -1.0031153 -0.77282935 0.14595269 -0.15075806 0.69212824 0.385454 0.70164734 -0.21775697 0.1363892 0.69458365 -0.3247153 0.304316 0.40166432 0.61550486 0.4590282 -0.99416476 -0.75351214 -0.19859429 0.63311404 -0.5414229 -0.61928415 -0.33350274 -0.08193817 -0.43711534 1.312692 0.22371696 0.4998732 -1.4381112 -0.45391116 -0.14466119 0.13299882 -0.4398423 -1.0650498 -0.57404834 -0.022888102 0.07370311 0.42288736 -0.12854199 1.6363946 0.48725113 0.1256565 0.132517 2.2078724 1.7647432 0.54534477 -0.29645523 -0.014265128 0.0031991815 -1.1028551 0.20085983 -0.3626875 0.75738674 -0.5516592 0.23809087 1.2856133 0.2602971 0.159506 0.6775368 1.8702489 -0.67913526 0.5872139 -0.049447875 0.1401503 -0.30865434 -0.017763581 0.4212067 -0.5220319 -0.16127284 0.182768 0.22131704 -0.2563105 0.8774896 0.81703246 0.39628422 0.36231348 0.27511787 -0.67843133 0.7222071 -0.3318762 -0.22084595 -0.10715687 0.45792416 -0.69571006 -0.2337643 0.4646986 -0.58650315 -1.257193 0.32932052 0.69814795 0.60938543 -0.0033802344 0.57839423 -0.72781754 -0.44834042 1.2148023 -0.45138305 -0.44424665 0.002405336
+0.324198 1.0461272 1.2694957 0.4512405 -0.2652417 0.3910717 0.44935483 -0.21196514 0.2629787 -0.1512267 -0.77435136 0.09432993 -1.1581715 -1.3761951 -0.8345308 -0.14183271 0.55220014 1.6007001 2.8263679 1.70961 0.54359204 0.5355011 -0.6789151 -0.03083109 -1.2098876 0.6617001 0.22374049 -1.4273605 -0.73623675 -0.9129155 -1.131973 -0.22065617 0.691493 2.0277522 0.26925856 1.5305483 0.6709371 0.20227751 0.068769686 0.5850261 0.6748788 0.73886716 0.34821013 0.3525081 -0.07495136 0.85512173 0.39809817 -0.10609535 1.5158496 1.0238556 -0.8108836 0.46903142 1.601046 1.726886 0.34955332 -0.016258225 -0.5941145 -0.023201821 0.55685717 0.26252788 0.8420125 0.424427 0.6617056 0.08824403 0.5074534 -0.5294419 -0.14202312 0.49772465 -0.14377417 0.48481622 1.0671204 0.6021328 0.73497283 1.2793562 1.8897928 1.4676578 -0.0028625797 0.6925298 0.46102804 -0.34925345 1.0688409 0.16698326 0.048282154 0.540996 -0.30838716 0.7248276 0.29081362 0.972803 0.44625488 0.9584397 -0.11455195 0.76300156 -0.2870343 -0.02156472 -0.7065148 -0.8122646 -1.8752956 -1.0862988 -0.45103583 0.6903231 0.29875067 0.49932885 0.4794718 0.24442543 -0.0068962984 1.0294654 -0.7357702 -0.8991665 0.26515794 -0.4879827 -0.47417215 -0.19405249 -1.5863919 -1.4758667 -0.54633105 0.18324628 0.4633917 -0.033322446 0.39619434 0.42733702 0.122756906 0.02227159 -1.0575666 -0.62055826 0.49268726 -0.7136375 -0.095852174 0.5549872 -0.8536564 -2.178404 -0.300334 0.047558192 -0.3964429 0.32078004 1.0711937 0.55719215 0.813753 0.5281706 -0.232745 0.66162264 -0.78145444 -1.0273473 -0.10876257 -0.29961237 -1.4574498 -0.87940794 0.8429038 -1.0321039 -0.708817 -0.19679457 0.118829854 1.0844388 1.0192103 0.97893524 -0.995705 -0.42097467 -0.37923548 -0.8797356 -1.295534 -0.3051011 -0.8584191 -0.6237388 0.29994914 -1.3988845 -1.3279945 -0.49047482 0.32205492 1.3268211 1.1962954 -0.6294789 -0.38372847 -0.85408545 -0.73402506 -0.20355508 0.22647385 -0.07613414 -0.28519404 1.1703242 -0.45440575 -0.4135681 -0.34366113 -1.4143696 1.00077 0.24402937 1.4169945 0.4381622 -0.50034785 -1.2099575 0.08010042 -0.22207321 0.691786 0.8651564 0.5949732 -0.54578954 0.2988547 -0.70302564 -0.09706479 -0.84604925 -0.61748755 -0.47333083 -0.76055634 -0.89320695 -0.81461495 -0.4408807 -1.5906909 -1.3327279 -0.06900973 0.5701455 0.19715816 0.31585297 0.094794475 -0.8327079 -1.5525787 -1.5317106 -0.7430849 -0.09764588 -1.4631271 -0.63548887 -0.30477706 0.6044156 0.48830822 0.3792617 0.13980179 0.35247844 0.5683721 0.2620647 0.065488145 0.67121565 -1.4460824 -1.1892319 -1.1609538 -1.6012245 -0.48742616 -0.73144174 -0.80351233 -1.1037393 -0.4560784 1.2434199 1.052172 0.71905494 0.26975644 0.09405528 0.4352493 -0.34652016 -0.30116236 -0.53785765 -0.91251385 0.28221196 -0.92031467 -0.38684094 -1.4538802 -0.4093127 -1.0508169 1.2602098 0.016090408 -0.7781259 0.0038164053
+0.34899452 0.43551138 -0.1801633 -0.13980372 -0.5918415 0.18512389 -0.637774 0.026483025 -0.9288965 2.018797 0.46602428 1.1350625 0.41534 0.6509708 0.08684477 -0.04923758 0.8290408 1.3959218 0.6300726 0.5571067 0.8959025 -0.22214186 0.64646083 2.8538108 1.8655826 1.3476434 3.0967402 2.3441684 2.1149242 0.85789347 0.19943236 0.39221576 0.38796857 0.9733669 0.08322598 -0.5326969 -0.8128047 0.37836513 -0.89841354 -0.67026436 0.29363325 -0.67997354 -0.74180055 -0.058875903 -0.06250465 -0.92607105 -1.0153372 -0.0969821 0.25615576 0.40146148 -0.54210913 -1.6560907 -1.3732036 -2.8062165 -0.9654973 -0.49074185 -1.4813517 -1.6107234 -1.3373486 -0.29287192 -1.365529 -0.24954084 -0.47448388 0.16028914 0.013301278 -0.48837075 -0.4094247 -1.032309 -0.90245533 -1.03609 -1.9138631 -0.4753778 -1.6546791 -2.2272875 -1.4139003 -1.4760089 -0.15532427 -1.7432575 -1.3446383 -0.51282495 -0.95714754 -0.43583247 -1.334729 -2.2898617 -0.8643527 -0.7869274 0.31103888 0.5299115 -0.44906798 0.57519144 -1.3482019 -0.79081005 -0.38887706 -0.99623656 -1.2482314 -0.5375696 -0.37459093 -1.433549 -0.726984 -0.46087775 0.5163761 0.7579098 -0.0470452 -0.43948933 -0.1816129 -0.19911431 -0.82070637 0.041347876 -1.1635152 -0.72388643 -0.88093144 -1.1555365 -0.5438338 -0.824328 -1.342995 -1.0908883 1.3741925 -1.7666208 -0.82256263 0.358632 0.60077715 -0.8494634 -1.1399274 0.1382732 -0.91434336 0.084631145 -0.8233162 -1.2037952 -1.1061074 -0.28464884 -0.04643375 -0.19073112 -0.36857077 0.12336258 0.44430372 0.6439594 0.059810374 0.6096434 -0.70409495 -0.3088769 0.33569968 -0.37674662 -1.3242744 -0.7852339 -0.35477704 0.16999471 -0.3471375 -0.5710284 -0.49106717 -1.6561658 -0.7034081 -0.6409242 1.0552794 -0.37279034 0.35563794 -0.03772467 -0.37208197 0.060365204 -0.82755774 -0.7269516 -0.4857834 0.043305416 -0.36041072 -0.23812898 -0.77312165 0.45424488 -0.10475901 0.02657198 -0.61215305 0.014454754 -0.9827011 -0.9867617 -0.68099046 -0.17517185 -0.050069038 -0.18135889 -0.08887155 0.41666672 0.36290786 -0.81357694 -0.88243884 -0.6983182 -0.5859458 -0.82072574 -1.3786892 -0.6161044 -1.3181741 -1.154877 0.18651165 -0.60539466 -0.42235956 0.13513772 0.04606362 0.24692588 0.063127846 0.5655238 -0.50693476 1.5995939 -1.2209054 0.2774633 0.14298461 0.4657873 -0.52006763 -0.6703785 -1.5149626 -0.8586979 -0.119561225 0.61693907 0.21801832 0.22349398 0.9523007 -0.077727735 -0.6596435 0.37848318 1.5563408 0.22579147 1.0999234 -0.22044803 -0.004981784 -1.077948 -0.93620175 -0.50398755 -0.95377624 0.54068756 0.76723456 0.019627063 1.1717428 0.08105768 1.5366242 0.93099356 0.41787595 2.5288703 1.6796426 1.1964376 0.0832777 0.85741264 -0.544418 0.14558968 0.048237406 0.054582797 0.22259393 0.4035469 -0.1483494 -0.07487902 -0.8609459 0.58568764 0.9888189 1.4579424 0.7116446 0.85291827 -0.20448285 -0.40498826 0.5194304 -0.39215624 0.37348232 -0.11054524 0.025268624
+0.31355312 -0.2569207 -0.44129074 -0.32759556 -0.15829423 0.105932645 0.6399394 1.599404 0.40299812 -0.16353549 0.5335733 -0.632891 -0.24842605 1.0833986 0.41112247 0.6617023 -0.599724 -0.9514725 -0.37196353 0.3283547 0.5355613 1.4060141 1.2545475 1.0404451 0.11272732 0.13567385 0.07742863 -0.26108146 -0.67378247 -0.0870784 1.598958 1.1734076 0.103656664 0.7154092 0.35276014 1.160704 0.5682231 0.15320581 0.50946033 1.0670927 -0.6342676 -0.81340474 0.97553885 -0.62385046 -1.4823159 1.1215645 0.7644669 1.245594 -0.6637506 -0.90373206 0.54475504 0.023331244 -0.13945916 -0.52110726 -0.62472475 -0.46704677 -0.4924951 -0.71503836 1.1971612 -0.2276264 -1.8007241 0.13122723 -0.1153043 1.2140326 -0.47213677 -0.8009326 -0.2873047 -0.7838971 -0.63734716 0.26143286 0.10977667 -0.071351275 0.5698748 0.014942971 -1.4033812 -0.6306406 -0.5739755 -0.23926045 0.3807677 0.116832286 -0.96081847 -0.56976724 0.3841466 -1.4820241 -0.8008879 1.1997848 0.27921215 1.0320961 1.043212 0.51919836 -0.42857763 0.026702838 0.23546018 -0.4276841 0.11047624 0.47510648 -0.16051751 -1.1061442 -1.3156124 -0.24219395 0.3003598 0.7345225 0.77221596 2.6825595 0.9272541 0.52901965 0.17974725 0.7089881 -0.36509198 0.45378944 0.5697395 -0.7221791 -1.8710384 -1.5365134 -0.892935 -0.4457689 0.8233435 0.087499045 1.6807845 1.0369619 -1.0247252 0.94427013 -0.11924478 -0.1819553 0.13903317 0.3666592 -0.24962665 -0.83833146 -1.7741002 -2.2587268 -0.5419408 -0.5958509 -0.7266291 0.8095073 1.6498561 0.9073211 0.8720946 -0.018906552 0.32695666 0.3393011 -0.37780795 0.22121322 -0.11927222 -0.510951 -1.980878 -2.6377234 -1.367223 -1.3971337 -0.24230005 0.22565581 0.5059276 1.6443602 -0.066822946 0.50422305 -0.40116 -0.0072107436 0.9827137 0.6210337 0.255268 -0.48262388 -1.8033098 -2.4241772 -0.52113265 -0.59755844 -0.47868744 0.5800802 1.4724234 0.8924181 1.0393144 0.31674403 -0.16051611 0.63050085 2.013169 0.43357188 0.035331856 -0.45989114 -0.9146474 -1.3458794 -1.8940005 -0.23117502 -0.5375885 0.123129144 0.92206466 0.8587084 0.66943973 -0.2759229 -0.9128281 1.1141527 0.7866131 -0.02197686 0.7536428 -0.10551563 -0.50085837 -0.56148833 -0.32149318 0.2190853 0.17272301 0.31370527 -0.53203875 1.0979165 0.3691644 1.1545193 -0.36878273 -0.09787914 0.9670017 -0.08824843 0.19481541 0.32729 -0.67850226 -0.0077991383 0.29042608 0.1008822 -0.41987768 0.088948674 0.10741654 -0.06070189 -1.0778598 0.039762326 -0.8064945 0.73079884 -0.68271154 0.032141402 0.35474864 -1.4368619 0.4057375 0.18610571 -0.3733003 0.78862125 0.7269798 0.3222252 -0.8543098 -1.316651 0.38973936 -0.019797457 -0.95832705 -0.37404072 -0.26126316 -0.8943949 -1.4501934 -1.1539205 0.13762718 0.07294907 0.53397864 0.373358 0.2633841 0.06297146 -0.49937835 0.28753504 -0.64221865 -0.3434134 1.1786649 -0.9444955 -1.0259506 -1.1684353 -1.0433656 -0.92095876 0.02317189
+0.49883622 0.8738015 0.07538438 -0.53190774 -0.8169132 -0.4654301 -0.75953823 0.61147225 0.55531156 0.7574796 1.0460283 -0.46929035 -0.039527465 0.89011025 0.0029253045 0.046302635 0.60812104 0.10492641 -0.8656824 0.60333836 0.7821837 0.18454382 -0.1711819 2.8021684 2.0009508 1.243945 -2.4809805E-4 1.1659219 -0.3866369 1.3590945 1.8321466 0.17325824 0.7315904 1.0736189 0.55457634 0.58655006 0.6639926 0.5549225 0.8504128 0.86628324 0.41518113 1.0283749 0.42744657 1.1177511 0.7092364 0.48287052 0.5519719 0.6621105 0.8691472 0.68850785 -0.33879724 -0.31775013 0.8507639 -0.3774613 1.0013268 1.5704612 -0.226301 -0.6631143 0.34470502 0.736129 1.0288049 0.41759476 0.3519841 0.04826597 0.9896556 0.502269 0.59868234 1.087104 0.014414474 -0.1628346 0.13342115 0.2699755 -0.72850776 0.5009547 0.6400719 0.43565235 1.7031748 0.6933077 -0.47167856 -0.2367978 0.24320003 0.9809215 0.4564348 0.18173188 0.84841526 -0.37224346 -0.31442142 -0.057412688 -0.34721774 -0.54385746 0.31509566 -0.1115179 -0.360106 1.2927624 0.1583295 0.043638255 1.4400384 0.5007109 0.21775734 -0.622246 1.1702619 1.0436081 0.2725648 -0.21549857 -0.03598858 -0.16443002 -1.1526567 1.8192471 0.33136237 0.83405006 0.23746926 0.4573318 1.6676764 -0.087492935 0.61379576 0.0793459 -0.04422792 -1.1592702 -0.08544064 -0.23945487 0.042512167 0.35734397 -0.8288806 -0.65794015 -0.29728588 0.15713137 0.536605 1.0444872 0.27764803 0.39361793 -0.85221267 -0.76842654 -0.8112615 0.47227907 0.87249994 -0.42854384 0.2784465 -0.19874159 -1.0792364 -0.22735132 0.6576991 0.8266387 -0.78881276 0.13905783 -0.20210706 0.61103046 -0.51635265 -0.3043786 -0.8134132 -1.4495662 -1.271393 -0.20779374 1.3198719 0.2956729 0.459104 -0.1824437 -0.15204583 -0.90568125 -0.37422338 0.43446416 -0.052006707 -0.13453352 0.47284144 0.3424477 0.7878659 -1.29038 -1.1850036 -0.48110694 -0.051368486 -0.8004262 -0.8516914 0.74701405 -0.55217254 -1.4585956 0.2849024 0.3748153 -0.52690715 -0.13875818 0.91924167 -0.60812974 -0.16129309 -0.41176206 0.60509497 0.26093718 -0.09773811 -1.7672535 -1.326208 -0.7874701 -1.130104 -1.0682622 0.05656509 0.25562486 -0.29242155 0.7207595 0.07820444 0.55645066 -1.1481186 -0.4348599 0.47691604 0.61596817 -0.92253006 -1.1836563 -1.5725946 -0.7895914 -0.13117582 -1.2490474 0.027346283 -0.31888416 0.4242007 0.4647982 -0.6039706 -0.86170834 -1.5070595 -0.29471865 0.7806233 -0.30346632 0.82369167 -1.9140621 -1.2397135 -0.5477873 -1.087546 -0.3498546 -0.84286237 0.43365687 0.33316892 0.31791714 -0.35534674 -0.64584637 -1.1461787 -0.53249437 -0.9726551 0.31310228 0.8493431 0.26505184 -1.1402653 -1.6951883 -0.7881438 -0.34877223 -0.56603265 -0.5316156 0.21854547 -0.200699 -0.22073564 0.74820566 -1.3174651 0.44954658 0.48710498 1.5799721 1.0713131 0.54062665 -0.35746223 -1.3621521 -0.8017228 -0.91521835 0.33674014 0.2767572 -0.02616764
+-0.18537915 -0.98226094 -0.45052698 0.5297868 -0.01609077 0.4291576 0.86536914 1.5901328 1.3896016 0.71268654 0.99405 0.6231499 -0.42216265 -0.1024484 -0.6611997 -0.6285279 -0.5370125 -0.73067737 -1.0556656 0.49071532 -0.3982177 0.30409858 1.925281 3.0892148 3.6179695 2.3695128 1.1990675 -0.56124395 -0.1690238 -0.74463964 -0.88408464 -1.2845768 0.13468586 -0.38228047 -0.6500104 0.2669491 -0.42273104 0.63166416 1.2274182 1.402954 1.7609581 1.0579638 -0.6925936 -0.8886774 -0.33242154 0.078056514 -0.45943132 -1.3518296 -0.75991064 -0.8375209 0.63642204 -0.066176854 -0.3558449 1.5183419 1.7831364 1.763367 0.66410565 -0.046603177 0.29276398 0.0153499 -0.49144736 -1.0273223 0.012938061 -0.46269718 0.83231515 -0.61673874 0.04597479 0.09324714 0.65462494 0.95914596 0.5155392 -0.70423424 -1.774696 -0.16532516 0.16753882 -0.112238616 -1.422655 -1.0354193 -0.45090258 0.10113637 0.3230875 0.7984015 0.57364917 -0.70329285 -1.2432072 -0.7258935 -0.4964063 -2.6535492 -1.3737441 -0.5719242 0.49697337 0.4245664 -1.3735908 0.27821648 -0.06963703 0.682949 1.0315195 -0.9389445 0.16737415 0.0023131468 -0.8528607 -0.23022734 -0.21757695 -0.5087957 -1.5721607 -0.45037323 -0.099977255 0.6938178 0.05377063 -0.5183964 -0.60970247 0.77048725 0.7966707 0.5762057 -0.42235973 0.12370597 0.66862684 0.99824667 -0.026461136 -0.9778955 -0.028188748 -1.944228 -0.69752586 -0.8686891 0.64038384 0.72719777 0.35285038 -0.27627587 -0.5498595 0.88892 0.023587577 1.1860816 0.71524984 0.8106411 -0.4101577 -0.35699233 -1.4711772 -0.31003162 0.7970542 -0.5812901 0.7590856 -0.0938436 -1.1353674 0.07782559 0.66103345 1.1277606 0.3490475 0.80413306 0.6273428 1.2402729 0.19842999 0.47186854 -0.4705327 -0.43522015 -0.07149193 -1.6771804 -0.5813705 0.0112961745 -0.953584 0.04100304 1.4994781 0.45771185 -0.952377 -0.31170908 0.18784817 -0.008882234 -0.42909992 -0.19479105 -0.8323455 -0.53422433 -1.6523142 -0.3984525 -0.20211801 -0.0031169986 -0.6823954 -1.1172303 0.7882518 -0.37490264 0.7321961 -0.3677952 0.7414583 0.7516236 -1.062251 -0.3738374 0.9049916 -0.38614756 -0.016904717 0.35313255 -0.22672379 -0.5068809 -0.4261392 1.0213126 0.9686542 -0.10154391 1.0424329 0.5673016 0.11186445 0.8623114 0.31082287 1.2003645 -0.25093895 -0.28917968 1.6349493 0.19981417 -0.2829063 0.009311169 1.1590991 0.24980175 -0.16430834 -1.4226515 0.92513716 -0.40189648 -0.4083443 -0.21450014 -0.4346813 -0.08093666 -1.2166839 -0.19779441 0.24804594 0.69058484 0.2754155 0.27351496 0.23796122 0.7480597 -0.72054225 -0.73124254 -0.07224956 1.2715003 0.60294753 -0.7234926 -0.5987044 -0.42238608 0.89744955 -0.053801876 0.43394342 0.58834773 1.0219165 -0.58623266 -0.30641058 -0.075494915 -0.40545318 -0.5162443 0.015226424 -0.4084876 -0.1230162 0.22420669 -0.72882015 -0.013819115 -0.21843338 -0.218198 -0.9387914 -0.30078402 1.2397376 -0.37904623 -0.69836 -0.37839484 0.007250318
+3.3188453 0.40059 -1.9679902 -0.06969836 0.645592 0.8478403 -3.7597065 1.8643434 0.868009 -5.94918 -0.8111086 1.3716624 -1.3318771 -6.057943 -3.4167368 -1.7107545 3.0471072 -6.8019423 -0.5861023 0.6775545 1.8216686 -1.0352285 -2.411754 2.232938 -7.9369297 1.5046302 -3.332253 -3.018245 -2.5044243 -6.877499 0.5581923 4.473815 -0.024825856
+0.3632732 2.3614464 3.3713956 -5.623532 0.93494517 -1.0177035 0.7173615 -4.96804 -1.6503501 -6.0000777 0.2045284 -5.0006113 -6.1966662 2.0163178 -3.598368 3.9817402 0.5001878 -1.5116302 -0.5121971 -3.8322074 0.89451444 -0.18629399 -2.5604308 0.71212083 0.306262 -1.8034369 0.42934173 -2.145597 -4.502384 1.0959655 -3.1901493 -0.891438 0.0052635614
+-4.4513197 -1.232425 2.6870427 3.2452874 -1.3963414 1.6518897 -2.8090582 -0.8918251 -4.6075926 -2.5077202 -2.6742818 -0.6963682 0.9420355 -1.6897413 0.99827325 0.04448109 -2.7016869 -3.7606738 -0.94711155 -0.42924723 2.9632182 0.93144786 4.764138 -1.4380913 4.107077 -3.2295914 -2.9563181 -2.8342938 1.9359553 -4.9888434 0.4994436 0.18100053 0.022587147
+-0.639423 -1.3831495 0.4468618 -0.28865674 -9.775045 2.6633239 0.06268622 1.8427695 -3.4072003 3.9190497 1.0533204 -1.4792175 1.8750358 0.7115673 -3.861028 2.03331 1.6446928 -1.7451559 -2.9372728 -2.8554428 2.783749 -1.178357 -3.765316 -1.1463546 -3.5237794 -1.1172531 -0.8649558 -2.4926033 -4.0221877 -0.57793397 -6.928154 -0.74644136 0.030580435
+-0.8511717 -1.0888187 0.21832423 3.6264567 -0.72284603 -2.165236 -2.7835886 1.1359786 4.094847 -0.14354818 0.12435902 0.7284857 -0.77557224 2.8904648 -3.0898228 1.6451933 -0.5899573 1.6661206 -3.752382 -3.29638 -0.6516911 -6.2895336 -4.9999743 -4.751674 -3.8747354 -4.665546 -2.5337596 -5.1378093 0.9923492 -9.2668705 2.0741165 2.574558 0.039836783
+-3.3618622 2.6225154 -6.2883058 0.25442094 -4.1493583 -0.41389433 2.6924343 -1.1820143 -5.618627 1.356849 -5.019766 1.6696825 2.092018 -1.6391217 -5.393632 -2.7981253 1.8893806 -1.9388933 5.1797557 -2.954032 -1.1735597 -3.8161666 -4.4212675 -3.9115098 -3.2309496 6.0728264 0.025871223 -4.6461387 5.3370523 1.0341136 1.2461692 -1.720388 0.024860557
+-1.2358694 4.1247025 0.08740824 -4.3771353 -0.030969817 1.031388 -3.1342778 0.7090729 0.49605337 -1.6042751 -1.8085297 -9.046925 0.8157869 -3.8854432 -3.3482633 -0.53522027 0.21666339 0.8697372 -7.8332415 -0.5469962 -4.405077 -4.7637396 -4.394621 -5.994705 -5.418705 -4.145933 -1.8615875 -3.1843278 -2.735348 3.6834736 3.6490235 4.945123 -0.020013118
+1.8197824 -2.8312726 -1.6365352 -2.9895499 1.6129265 3.4348679 -1.8052833 -1.5420055 -4.8966184 -4.6325965 -0.061136648 2.165334 2.1105518 1.6097159 -0.31565392 -9.934366 2.260088 -2.6938198 -1.3954766 -0.7070942 -1.1792121 -2.2252917 -0.10980059 -0.11566961 2.7799675 1.0673789 4.6228166 -2.2967038 -1.3443925 1.2742109 -4.1370153 -0.63993543 -0.024386141
+-0.7715497 -2.3300824 -1.8012121 4.8299856 -3.2595117 4.664556 -1.9699382 -7.3050585 -0.5722891 1.8220688 -2.5350072 -2.4604144 0.092435844 0.53040916 2.7670844 -3.0026073 -10.599527 1.0140266 1.9128901 -0.29929286 1.8670084 1.8597156 1.8260541 1.6761122 -0.09393797 -2.0504067 4.558832 2.234363 3.7772114 2.0039213 -0.6626459 -1.574328 -0.0040445877
+1.8952433 1.8856168 1.1119277 -4.4144793 -4.7854204 -2.56885 -1.6020781 -0.42634428 -1.1362706 1.3833557 -4.02971 -2.8391373 -4.173429 -4.0498304 2.928348 0.46056744 -1.0412822 -3.0846875 -2.8325171 -1.9743062 4.5396714 1.4534146 3.8350468 -0.06542266 -0.48209596 -3.496334 3.4790037 -1.0122944 4.563831 -2.4299686 -4.1514144 -1.9072495 0.019211592
+0.28322476 -5.1883173 0.122715116 4.0505824 -3.1462262 -6.796414 2.2734184 -4.098528 -0.60894316 -6.54831 4.2180057 0.6621108 1.6274971 2.2397742 -5.5765843 0.6283236 0.7379073 1.7373952 -0.3651221 -5.041317 3.965837 -5.2236643 -2.2686272 -1.9154938 2.6809785 -0.22754136 0.3797499 2.6155822 -0.37388822 -3.9279466 -6.1213164 -3.1557689 0.0030120001
+-0.8198072 -3.320936 -2.829201 -0.6887955 -0.47655535 -5.633271 5.8044443 1.834403 -4.216584 -2.6752787 -1.0306456 -4.2755737 -6.588805 -1.0150422 1.7686261 -0.3829343 2.1872528 -3.4612815 3.4437048 -2.207867 0.1888097 0.49778536 5.7171288 0.32646227 -1.2284694 0.51398253 -10.336291 2.114793 6.6587143 -1.5447686 -2.3190935 1.8876063 -0.047436677
+-0.62963194 1.4777945 -1.7571894 -2.6769009 0.39057454 -3.7364814 -0.8392782 -2.3699584 0.09312773 1.8219194 2.7355092 1.7888372 -0.81204736 -2.935253 -2.1590881 -1.5556968 -4.610923 1.9892942 2.3136575 3.2912333 -4.83361 -4.248878 -1.400305 -2.403121 -4.0466743 -0.08205262 -1.2859818 3.1537158 -1.861443 -5.811996 0.458375 -4.027502 -0.02590746
+-7.615588 1.3614897 1.4939482 -5.205575 -1.673643 0.74357635 -2.7372591 1.6170616 2.435418 -3.4419708 -0.06518204 1.2442499 1.1266783 1.3549963 -0.9004273 -5.7754664 -2.624869 -1.6468443 1.0941269 0.7589392 -5.706259 2.6252341 -2.405118 -2.4348783 3.6782053 3.306361 -3.2466447 -1.553077 -2.5804696 1.0159948 -2.3408878 -1.8535192 -0.0021200308
+-4.013827 0.2610515 2.111559 -6.3211656 -2.1001635 1.9053426 -1.6727843 -0.44091293 -0.76261014 -1.0390077 -1.7525955 -2.720178 -2.529168 -5.6742926 2.6151636 0.51420337 0.71321785 4.3812776 3.1439812 0.77312356 -2.8765817 1.9708476 -0.86634195 -2.2173822 0.38174078 -4.7265043 -2.6250343 -3.9365456 -1.9344738 -4.6156936 -0.7695132 1.912843 0.011368353
+-7.697162 -0.26664928 -6.4262285 0.72342825 -4.9268126 -3.5221684 -3.8728328 -3.2982187 1.3733284 -5.8051333 1.4574023 -0.96571344 0.58893365 -3.181542 3.262099 1.6309257 -1.5365862 2.3387916 -5.255009 -0.10661021 -2.132601 -3.5527897 2.3372629 -3.7519357 -1.9273626 3.992388 -5.48636 0.6817621 -2.9058044 -1.9674861 4.4054747 3.334584 0.007431256
+-1.6424383 -5.8564734 -1.8093833 -3.715056 1.3547465 -1.2179599 -5.499006 2.3751373 0.4895267 2.7063863 -6.2402163 7.3155036 -3.6011443 -2.7977996 -4.6695447 -2.862364 0.75960207 2.9870906 2.8959186 -5.650074 0.539843 -4.619602 -2.5695598 -0.467896 -3.390343 -2.4309294 -2.590085 3.249129 -5.5731363 1.9717381 0.26087123 0.67754215 -0.045831084
+-1.7940446 -1.3843921 -4.6716633 4.1857424 -0.50761205 -3.6805487 1.9576495 -3.053029 -5.650654 -0.72363085 -0.4052815 -0.891051 -2.4934862 2.1326828 4.351335 -4.7457786 -0.87060124 1.9086488 0.39036214 4.53587 -5.013919 4.2015347 -1.5139904 -1.8883435 4.1603584 -2.70182 -0.36223388 1.7974008 1.2901081 -0.37577942 0.0105882725 -4.2853737 -0.01637644
+-1.5830569 -0.7317656 2.4023943 -2.004526 1.2185715 -0.55593747 -3.4697645 -6.1193686 -1.7822918 1.5736116 -2.7630713 3.676887 1.0927823 -1.3736699 -4.150244 0.2997286 1.5663744 -3.378952 -1.3276973 0.24779214 -5.9093213 1.0596575 0.50607246 4.050893 -4.0679774 -5.162828 -1.8389171 -4.4217887 1.7034249 3.731301 -2.2410748 -0.7650962 -0.016503714
+3.5579996 -2.51934 4.575838 7.258866 -4.859554 -1.3860203 1.3648074 2.2165234 4.1006 -3.2093186 -4.469197 -4.7680097 -0.6160599 -0.62733936 1.571316 -5.516408 -2.6344726 -0.36233923 1.2449152 -2.4668746 -8.253659 1.8876019 4.7397947 -4.1485906 -0.40496337 0.9102521 5.0837426 1.9607608 -4.3280587 -0.7465847 -3.9982235 -1.049976 0.041746177
+2.4787107 -2.440761 -1.4641386 -2.9584825 1.8319176 2.6269035 -7.5023637 1.8800472 -0.64747334 2.6456115 1.113191 -2.2647874 0.39089805 -3.2810428 -1.1749662 0.18277311 -5.4791713 -2.1531775 -1.6886452 2.1894584 3.0858085 2.0088425 -3.1921341 -2.1513703 7.11089 -1.8595059 -1.14462 0.7134691 -2.9010673 -2.1420977 -4.555495 -5.8109202 -0.0020564618
+1.7578679 -2.3976014 1.5388082 -2.8396344 -0.17281288 -5.439047 3.2236662 -1.862213 -4.4158125 0.08120502 -4.8469143 1.0403296 -0.57074785 -0.8282122 4.5666046 -0.057304364 -5.511647 1.7642924 -2.6845326 0.25282356 5.579816 1.5881189 -3.7861753 -3.7130008 5.0709996 1.1625888 2.1444614 -0.0748934 -2.7709198 -1.1461511 2.6962454 -3.866843 -0.01615078
+-1.3438528 0.6370322 -5.153015 -1.706669 -1.5238507 -1.461546 3.4800727 3.378386 0.21473399 1.3823695 1.2987071 -3.2407484 -6.6887445 3.9367244 -4.3351197 -1.388976 -1.423658 2.1621523 1.1173093 2.1123621 -0.18855162 -2.5684676 -1.3163676 1.7352618 -3.5005045 -1.4386475 -1.4427011 -6.3370504 -2.3031182 -0.64208794 -1.9835476 -2.4418921 0.01610778
+-3.1874948 -2.3977308 -2.702749 -1.1587065 -1.0463094 -1.710468 0.033704665 0.3566389 -0.76097363 1.7152604 0.3606053 -0.44375435 1.4578848 -0.61850345 -5.278605 -2.339693 -0.8100282 -3.6413932 -4.3556676 5.3163548 -6.138357 0.7554096 -0.3293253 7.2791667 -2.2634993 -1.4381553 -5.0166793 3.4261372 -2.924105 2.9263134 -2.9614942 -4.837568 0.04072551
+3.7139666 0.19742009 2.0511174 -1.384915 0.016993588 -4.7682934 0.6759354 -4.224599 -1.8024838 0.7470361 4.309398 -0.46020854 -4.684363 -3.2771602 4.121208 2.430816 0.93080497 -5.46639 -5.5941343 -2.4674442 -5.472979 -0.32386532 3.2534885 -6.1389556 -2.179047 1.4061046 -3.4079444 2.4176822 -4.659507 2.3622673 -0.5147894 -5.554515 0.0031532426
+-0.9338535 -8.511058 -2.4692512 -0.89263976 2.3165276 1.7393429 -2.2559807 -0.43257144 2.4999452 -0.1843885 0.49021253 -4.820904 -1.1133385 0.09079128 1.7847239 -1.9373181 -0.8417471 -5.1364603 1.234991 1.8285574 1.554807 2.6041527 -1.9148797 -4.530061 -4.047518 -2.2234762 -3.6861074 2.988775 6.2937946 0.9297057 -1.7499388 2.496612 -0.0090153795
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 43eec1b..052ab35 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" />
@@ -664,8 +668,8 @@
<!-- 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/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 b5808ea..af9dbcd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1106,6 +1106,7 @@
<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 type="anim" name="linear_interpolator" id="0x010a000b" />
<public type="drawable" name="stat_sys_vp_phone_call" id="0x0108022d" />
<public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x0108022e" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ed81cb4..4a6a564 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -473,6 +473,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
@@ -1069,7 +1075,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>
@@ -1095,6 +1101,9 @@
<item>Custom</item>
</string-array>
+ <!-- String which means the type "mobile phone". -->
+ <string name="mobileEmailTypeName">Mobile</string>
+
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Postal address types from android.provider.Contacts. This could be used when adding a new address for a contact, for example. -->
<string-array name="postalAddressTypes">
@@ -1244,15 +1253,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>
@@ -1353,12 +1353,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. -->
@@ -1492,21 +1486,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. -->
@@ -1529,16 +1508,6 @@
<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.
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>
@@ -1583,42 +1552,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 -->
@@ -1628,29 +1561,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>
@@ -1749,312 +1659,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>
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..526b6d9 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,6 +132,8 @@
<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.INSTALL_LOCATION_COLLECTOR" uid="shell" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
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/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/ByteOrder.h b/include/utils/ByteOrder.h
index 4c06067..baa3a83 100644
--- a/include/utils/ByteOrder.h
+++ b/include/utils/ByteOrder.h
@@ -38,6 +38,16 @@
* intent is to allow us to avoid byte swapping on the device.
*/
+static inline uint32_t android_swap_long(uint32_t v)
+{
+ return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
+}
+
+static inline uint16_t android_swap_short(uint16_t v)
+{
+ return (v<<8) | (v>>8);
+}
+
#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
#if BYTE_ORDER == DEVICE_BYTE_ORDER
@@ -49,16 +59,6 @@
#else
-static inline uint32_t android_swap_long(uint32_t v)
-{
- return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
-}
-
-static inline uint16_t android_swap_short(uint16_t v)
-{
- return (v<<8) | (v>>8);
-}
-
#define dtohl(x) (android_swap_long(x))
#define dtohs(x) (android_swap_short(x))
#define htodl(x) (android_swap_long(x))
@@ -66,4 +66,16 @@
#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define fromlel(x) (x)
+#define fromles(x) (x)
+#define tolel(x) (x)
+#define toles(x) (x)
+#else
+#define fromlel(x) (android_swap_long(x))
+#define fromles(x) (android_swap_short(x))
+#define tolel(x) (android_swap_long(x))
+#define toles(x) (android_swap_short(x))
+#endif
+
#endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/include/utils/backup_helpers.h b/include/utils/backup_helpers.h
index 137c5f1..0c59fec 100644
--- a/include/utils/backup_helpers.h
+++ b/include/utils/backup_helpers.h
@@ -1,15 +1,128 @@
+/*
+ * 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.
+ */
+
#ifndef _UTILS_BACKUP_HELPERS_H
#define _UTILS_BACKUP_HELPERS_H
+#include <utils/Errors.h>
+#include <utils/String8.h>
+
+namespace android {
+
int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
char const* fileBase, char const* const* files, int fileCount);
+// the sizes of all of these match.
+typedef struct {
+ int type; // == APP_MAGIC_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; // 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
+ int cookie;
+} app_footer_v1;
+
+
+/**
+ * Writes the data.
+ *
+ * If an error occurs, it poisons this object and all write calls will fail
+ * with the error that occurred.
+ */
+class BackupDataWriter
+{
+public:
+ BackupDataWriter(int fd);
+ // does not close fd
+ ~BackupDataWriter();
+
+ 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(int cookie);
+
+private:
+ explicit BackupDataWriter();
+ status_t write_padding_for(int n);
+
+ int m_fd;
+ status_t m_status;
+ ssize_t m_pos;
+ int m_entityCount;
+};
+
+/**
+ * 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();
+
+ status_t ReadAppHeader(String8* packageName, int* cookie);
+ bool HasEntities();
+ status_t ReadEntityHeader(String8* key, size_t* dataSize);
+ 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;
+};
+
#define TEST_BACKUP_HELPERS 0
#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
+
#endif // _UTILS_BACKUP_HELPERS_H
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index f9fb780..5a1a89b 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -117,7 +117,8 @@
IPermissionController.cpp \
IServiceManager.cpp \
Unicode.cpp \
- file_backup_helper.cpp
+ backup_data.cpp \
+ backup_helper_file.cpp
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_SRC_FILES += $(hostSources)
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/backup_data.cpp b/libs/utils/backup_data.cpp
new file mode 100644
index 0000000..dd04449
--- /dev/null
+++ b/libs/utils/backup_data.cpp
@@ -0,0 +1,428 @@
+/*
+ * 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 "backup_data"
+
+#include <utils/backup_helpers.h>
+#include <utils/ByteOrder.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+
+namespace android {
+
+/*
+ * File Format (v1):
+ *
+ * All ints are stored little-endian.
+ *
+ * - An app_header_v1 struct.
+ * - The name of the package, utf-8, null terminated, padded to 4-byte boundary.
+ * - A sequence of zero or more key/value paires (entities), each with
+ * - A entity_header_v1 struct
+ * - The key, utf-8, null terminated, padded to 4-byte boundary.
+ * - 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)
+
+const static int ROUND_UP[4] = { 0, 3, 2, 1 };
+
+static inline size_t
+round_up(size_t n)
+{
+ return n + ROUND_UP[n % 4];
+}
+
+static inline size_t
+padding_extra(size_t n)
+{
+ return ROUND_UP[n % 4];
+}
+
+BackupDataWriter::BackupDataWriter(int fd)
+ :m_fd(fd),
+ m_status(NO_ERROR),
+ m_pos(0),
+ m_entityCount(0)
+{
+}
+
+BackupDataWriter::~BackupDataWriter()
+{
+}
+
+// Pad out anything they've previously written to the next 4 byte boundary.
+status_t
+BackupDataWriter::write_padding_for(int n)
+{
+ ssize_t amt;
+ ssize_t paddingSize;
+
+ paddingSize = padding_extra(n);
+ if (paddingSize > 0) {
+ uint32_t padding = 0xbcbcbcbc;
+ amt = write(m_fd, &padding, paddingSize);
+ if (amt != paddingSize) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+ }
+ return NO_ERROR;
+}
+
+status_t
+BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+
+ ssize_t amt;
+
+ amt = write_padding_for(m_pos);
+ if (amt != 0) {
+ return amt;
+ }
+
+ app_header_v1 header;
+ ssize_t nameLen;
+
+ nameLen = packageName.length();
+
+ header.type = tolel(APP_MAGIC_V1);
+ header.packageLen = tolel(nameLen);
+ header.cookie = cookie;
+
+ amt = write(m_fd, &header, sizeof(app_header_v1));
+ if (amt != sizeof(app_header_v1)) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+
+ amt = write(m_fd, packageName.string(), nameLen+1);
+ if (amt != nameLen+1) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+
+ return NO_ERROR;
+}
+
+status_t
+BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+
+ ssize_t amt;
+
+ amt = write_padding_for(m_pos);
+ if (amt != 0) {
+ return amt;
+ }
+
+ entity_header_v1 header;
+ ssize_t keyLen;
+
+ keyLen = key.length();
+
+ header.type = tolel(ENTITY_MAGIC_V1);
+ header.keyLen = tolel(keyLen);
+ header.dataSize = tolel(dataSize);
+
+ amt = write(m_fd, &header, sizeof(entity_header_v1));
+ if (amt != sizeof(entity_header_v1)) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+
+ amt = write(m_fd, key.string(), keyLen+1);
+ if (amt != keyLen+1) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+
+ amt = write_padding_for(keyLen+1);
+
+ m_entityCount++;
+
+ return amt;
+}
+
+status_t
+BackupDataWriter::WriteEntityData(const void* data, size_t size)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+
+ // We don't write padding here, because they're allowed to call this several
+ // times with smaller buffers. We write it at the end of WriteEntityHeader
+ // instead.
+ ssize_t amt = write(m_fd, data, size);
+ if (amt != (ssize_t)size) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+ return NO_ERROR;
+}
+
+status_t
+BackupDataWriter::WriteAppFooter(int cookie)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+
+ ssize_t amt;
+
+ amt = write_padding_for(m_pos);
+ if (amt != 0) {
+ return amt;
+ }
+
+ app_footer_v1 footer;
+ ssize_t nameLen;
+
+ footer.type = tolel(FOOTER_MAGIC_V1);
+ footer.entityCount = tolel(m_entityCount);
+ footer.cookie = cookie;
+
+ amt = write(m_fd, &footer, sizeof(app_footer_v1));
+ if (amt != sizeof(app_footer_v1)) {
+ m_status = errno;
+ return m_status;
+ }
+ m_pos += amt;
+
+ 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()
+{
+ 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 APP_MAGIC_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 ENTITY_MAGIC_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);
+ if (m_header.entity.dataSize < 0) {
+ LOGD("Entity header at %d has dataSize<0: 0x%08x\n", (int)m_pos,
+ (int)m_header.entity.dataSize);
+ m_status = EINVAL;
+ }
+ m_entityCount++;
+ break;
+ case FOOTER_MAGIC_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);
+
+ return m_status;
+}
+
+status_t
+BackupDataReader::ReadAppHeader(String8* packageName, int* cookie)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != APP_MAGIC_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 == ENTITY_MAGIC_V1;
+}
+
+status_t
+BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
+{
+ if (m_status != NO_ERROR) {
+ return m_status;
+ }
+ if (m_header.type != ENTITY_MAGIC_V1) {
+ return EINVAL;
+ }
+ size_t size = m_header.app.packageLen;
+ 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::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 != FOOTER_MAGIC_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/file_backup_helper.cpp b/libs/utils/backup_helper_file.cpp
similarity index 66%
rename from libs/utils/file_backup_helper.cpp
rename to libs/utils/backup_helper_file.cpp
index 453084a..bf56945 100644
--- a/libs/utils/file_backup_helper.cpp
+++ b/libs/utils/backup_helper_file.cpp
@@ -1,3 +1,19 @@
+/*
+ * 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 "file_backup_helper"
#include <utils/backup_helpers.h>
@@ -19,13 +35,16 @@
#include <cutils/log.h>
-using namespace android;
+namespace android {
#define MAGIC0 0x70616e53 // Snap
#define MAGIC1 0x656c6946 // File
+#if TEST_BACKUP_HELPERS
+#define LOGP(x...) printf(x)
+#else
#define LOGP(x...) LOGD(x)
-//#define LOGP(x...) printf(x)
+#endif
struct SnapshotHeader {
int magic0;
@@ -118,6 +137,8 @@
bytesWritten += sizeof(FileState) + round_up(name.length());
}
+ LOGP("write_snapshot_file fd=%d\n", fd);
+
int amt;
SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
@@ -248,11 +269,13 @@
// file added
String8 realFilename(base);
realFilename.appendPath(q);
+ LOGP("file added: %s\n", realFilename.string());
write_update_file(realFilename, q);
m++;
}
else if (cmp < 0) {
// file removed
+ LOGP("file removed: %s\n", p.string());
write_delete_file(p);
n++;
}
@@ -573,6 +596,266 @@
return matched ? 0 : 1;
}
+// 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,
+ 0xdd, 0xcc, 0xbb, 0xaa, 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, 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,
+ 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+ 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
+ 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, 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, 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,
+ 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
+ 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);
+
+static int
+test_write_header_and_entity(BackupDataWriter& writer, const char* str)
+{
+ int err;
+ String8 text(str);
+
+ err = writer.WriteAppHeader(text, 0xaabbccdd);
+ if (err != 0) {
+ fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
+ return err;
+ }
+
+ err = writer.WriteEntityHeader(text, text.length()+1);
+ if (err != 0) {
+ fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
+ return err;
+ }
+
+ err = writer.WriteEntityData(text.string(), text.length()+1);
+ if (err != 0) {
+ fprintf(stderr, "write failed for data '%s'\n", text.string());
+ return errno;
+ }
+
+ return err;
+}
+
+int
+backup_helper_test_data_writer()
+{
+ int err;
+ int fd;
+ const char* filename = SCRATCH_DIR "data_writer.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;
+ }
+
+ BackupDataWriter writer(fd);
+
+ err = 0;
+ err |= test_write_header_and_entity(writer, "no_padding_");
+ err |= test_write_header_and_entity(writer, "padded_to__3");
+ err |= test_write_header_and_entity(writer, "padded_to_2__");
+ err |= test_write_header_and_entity(writer, "padded_to1");
+
+ writer.WriteAppFooter(0x77779999);
+
+ close(fd);
+
+ err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
+ if (err != 0) {
+ return err;
+ }
+
+ 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])
{
@@ -594,8 +877,9 @@
backup_helper_test_files()
{
int err;
- int newSnapshotFD;
int oldSnapshotFD;
+ int dataStreamFD;
+ int newSnapshotFD;
system("rm -r " SCRATCH_DIR);
mkdir(SCRATCH_DIR, 0777);
@@ -616,17 +900,24 @@
"data/f"
};
+ dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
+ if (dataStreamFD == -1) {
+ fprintf(stderr, "error creating: %s\n", strerror(errno));
+ return errno;
+ }
+
newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
if (newSnapshotFD == -1) {
fprintf(stderr, "error creating: %s\n", strerror(errno));
return errno;
}
-
- err = back_up_files(-1, newSnapshotFD, 0, SCRATCH_DIR, files_before, 5);
+
+ err = back_up_files(-1, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_before, 5);
if (err != 0) {
return err;
}
+ close(dataStreamFD);
close(newSnapshotFD);
sleep(3);
@@ -665,21 +956,30 @@
return errno;
}
+ dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
+ if (dataStreamFD == -1) {
+ fprintf(stderr, "error creating: %s\n", strerror(errno));
+ return errno;
+ }
+
newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
if (newSnapshotFD == -1) {
fprintf(stderr, "error creating: %s\n", strerror(errno));
return errno;
}
- err = back_up_files(oldSnapshotFD, newSnapshotFD, 0, SCRATCH_DIR, files_after, 6);
+ err = back_up_files(oldSnapshotFD, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_after, 6);
if (err != 0) {
return err;
}
close(oldSnapshotFD);
+ close(dataStreamFD);
close(newSnapshotFD);
return 0;
}
#endif // TEST_BACKUP_HELPERS
+
+}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index ae3e181..3dd8563 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/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/libs/Android.mk b/opengl/libs/Android.mk
index 5ba6b76..23304d5 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -39,7 +39,7 @@
GLES_CM/gl.cpp.arm \
#
-LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL
+LOCAL_SHARED_LIBRARIES += libcutils libEGL
LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE:= libGLESv1_CM
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 b9d567c..f6958ed 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/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/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4ce40b6..1471435 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);
}
}
@@ -2828,6 +2826,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) {
@@ -2866,17 +2879,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);
}
@@ -2890,8 +2900,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);
}
@@ -3010,17 +3025,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);
}
@@ -3586,7 +3598,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..90ab270 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -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;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3fa5baf..a04d73a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1300,7 +1300,6 @@
mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
}
}
-
if (localLOGV) Log.v(
TAG, "New client " + client.asBinder()
+ ": window=" + win);
@@ -7732,7 +7731,6 @@
int i;
// FIRST LOOP: Perform a layout, if needed.
-
performLayoutLockedInner();
if (mFxSession == null) {
@@ -7752,7 +7750,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..fd37cc2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -191,6 +191,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 +332,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 +724,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 +883,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 +942,8 @@
d.show();
proc.anrDialog = d;
}
+
+ ensureScreenEnabled();
} break;
case SHOW_FACTORY_ERROR_MSG: {
Dialog d = new FactoryErrorDialog(
@@ -1041,6 +1075,11 @@
processStartTimedOutLocked(app);
}
}
+ case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
+ synchronized (ActivityManagerService.this) {
+ doPendingActivityLaunchesLocked(true);
+ }
+ }
}
}
};
@@ -1495,6 +1534,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 +2296,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 +2524,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 +2612,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 +2642,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 +2658,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 +2908,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 +2984,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 +3022,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 +3030,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 +3043,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 +3065,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 +3086,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 +3098,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 +3164,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 +3183,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 +3193,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 +3210,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 +3221,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 +3241,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 +3263,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 +3294,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 +5048,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 +6402,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 +6490,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 +6599,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 +7344,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,
@@ -10176,8 +10390,6 @@
}
}
- final ContentResolver resolver = mContext.getContentResolver();
-
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
@@ -10200,8 +10412,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/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/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 0b161d6..af94100 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;
@@ -111,45 +113,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
@@ -179,12 +276,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
@@ -194,7 +293,7 @@
int mDataState = TelephonyManager.DATA_DISCONNECTED;
int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
ServiceState mServiceState;
- int mSignalAsu = -1;
+ SignalStrength mSignalStrength;
// data connection
private IBinder mDataIcon;
@@ -249,6 +348,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) {
@@ -306,6 +409,7 @@
private StatusBarPolicy(Context context, StatusBarService service) {
mContext = context;
mService = service;
+ mSignalStrength = new SignalStrength();
mBatteryStats = BatteryStatsService.getService();
// clock
@@ -321,14 +425,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);
@@ -351,6 +462,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);
@@ -666,8 +783,8 @@
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
- public void onSignalStrengthChanged(int asu) {
- mSignalAsu = asu;
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrength = signalStrength;
updateSignalStrength();
}
@@ -675,6 +792,7 @@
public void onServiceStateChanged(ServiceState state) {
mServiceState = state;
updateSignalStrength();
+ updateCdmaRoamingIcon();
updateDataIcon();
}
@@ -696,7 +814,6 @@
updateDataIcon();
}
};
-
private final void updateSimState(Intent intent) {
String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
@@ -723,25 +840,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) {
@@ -750,48 +893,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;
@@ -819,32 +1006,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;
@@ -852,10 +1058,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);
@@ -863,6 +1067,7 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
+
if (mDataIconVisible != visible) {
mService.setIconVisibility(mDataIcon, visible);
mDataIconVisible = visible;
@@ -873,7 +1078,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;
@@ -905,7 +1110,7 @@
} else {
return;
}
-
+
if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
@@ -920,15 +1125,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);
@@ -937,9 +1142,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;
@@ -986,18 +1191,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);
@@ -1007,14 +1212,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) {
@@ -1028,6 +1278,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/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..2bb17e4 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.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..2fce188 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.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/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/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/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/backup_helper_test.cpp b/tests/backup/backup_helper_test.cpp
index 6da16b4..1085909 100644
--- a/tests/backup/backup_helper_test.cpp
+++ b/tests/backup/backup_helper_test.cpp
@@ -3,6 +3,8 @@
#include <stdio.h>
#include <string.h>
+using namespace android;
+
#if TEST_BACKUP_HELPERS
// ============================================================
@@ -20,6 +22,8 @@
{ "backup_helper_test_empty", backup_helper_test_empty, 0, false },
{ "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..1f4333c 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,11 +14,12 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.gesture"
+ package="com.android.gesture.example"
android:versionCode="1"
android:versionName="1.0.0">
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name="com.android.gesture.example.GestureEntryDemo"
+ <activity android:name="com.android.gesture.example.GestureEntry"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -26,5 +27,12 @@
</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
index 29c07ad..a5e7a25 100755
--- a/tests/sketch/src/com/android/gesture/Gesture.java
+++ b/tests/sketch/src/com/android/gesture/Gesture.java
@@ -18,343 +18,290 @@
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.
+ * A gesture can have a single or multiple strokes
*/
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;
+ 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 ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
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();
+ 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() {
- return this.mLength;
+ int len = 0;
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ len += stroke.length;
+ }
+ return len;
}
-
- public RectF getBBX() {
- return mBBX;
+
+ /**
+ * @return the bounding box of the gesture
+ */
+ public RectF getBoundingBox() {
+ return mBoundingBox;
}
-
- public void setID(long id) {
- mID = id;
+
+ /**
+ * Set the id of the gesture
+ *
+ * @param id
+ */
+ void setID(long id) {
+ mGestureID = id;
}
-
+
+ /**
+ * @return the id of the gesture
+ */
public long getID() {
- return mID;
+ return mGestureID;
}
-
- 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;
- }
- }
+ void draw(Canvas canvas, Paint paint) {
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ stroke.draw(canvas, paint);
}
-
- 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
+ * 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 foreground
- * @return
+ * @param color
+ * @return the bitmap
*/
- 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);
+ public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
+ RectF bbx = getBoundingBox();
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.translate(edge, edge);
Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setDither(true);
- paint.setColor(mColor);
+ 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(2);
- c.drawPath(path, paint);
+ paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ Path path = stroke.toPath(width - 2 * edge, height - 2 * edge, numSample);
+ canvas.drawPath(path, paint);
+ }
+
return bitmap;
}
-
+
/**
- * save the gesture as XML
+ * 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) {
+ RectF bbx = getBoundingBox();
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.translate(edge, edge);
+ 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);
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ stroke.draw(canvas, 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;
+ void toXML(String namespace, XmlSerializer serializer) throws IOException {
+ serializer.startTag(namespace, GestureConstants.XML_TAG_GESTURE);
+ serializer.attribute(namespace, GestureConstants.XML_TAG_ID, Long.toString(mGestureID));
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ stroke.toXML(namespace, serializer);
}
- serializer.text(pts);
- serializer.endTag(namespace, "stroke");
+ serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE);
}
-
-
+
+ /**
+ * Create the gesture from a string
+ *
+ * @param str
+ */
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));
+ int startIndex = 0;
+ int endIndex;
+ while ((endIndex = str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) {
+ String token = str.substring(startIndex, endIndex);
+ if (startIndex > 0) { // stroke tokens
+ addStroke(GestureStroke.createFromString(token));
+ } else { // id token
+ mGestureID = Long.parseLong(token);
+ }
+ startIndex = endIndex + 1;
}
-
- 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);
}
-
+
+ /**
+ * Convert the gesture to string
+ */
@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 + ",";
+ StringBuilder str = new StringBuilder();
+ str.append(mGestureID);
+ ArrayList<GestureStroke> strokes = mStrokes;
+ int count = strokes.size();
+ for (int i = 0; i < count; i++) {
+ GestureStroke stroke = strokes.get(i);
+ str.append(GestureConstants.STRING_GESTURE_DELIIMITER);
+ str.append(stroke.toString());
}
- str += "#";
- str += this.mColor;
-
- str += "#";
- str += this.mWidth;
-
- str += "#";
- str += this.mLength;
-
- str += "#";
- str += this.mTimestamp;
-
- return str;
+ return str.toString();
}
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+
+ public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
public Gesture createFromParcel(Parcel in) {
String str = in.readString();
- Gesture stk = new Gesture();
- stk.createFromString(str);
- return stk;
+ Gesture gesture = new Gesture();
+ gesture.createFromString(str);
+ return gesture;
}
-
+
public Gesture[] newArray(int size) {
return new Gesture[size];
}
};
-
- public static Gesture buildFromArray(byte[] bytes) {
+
+ /**
+ * Build a gesture from a byte array
+ *
+ * @param bytes
+ * @return the gesture
+ */
+ static Gesture buildFromArray(byte[] bytes) {
String str = new String(bytes);
- Gesture stk = new Gesture();
- stk.createFromString(str);
- return stk;
+ Gesture gesture = new Gesture();
+ gesture.createFromString(str);
+ return gesture;
}
-
- public static byte[] saveToArray(Gesture stk) {
- String str = stk.toString();
+
+ /**
+ * Save a gesture to a byte array
+ *
+ * @param stroke
+ * @return the byte array
+ */
+ static byte[] saveToArray(Gesture stroke) {
+ String str = stroke.toString();
return str.getBytes();
}
-
+
public void writeToParcel(Parcel out, int flags) {
- out.writeString(this.toString());
+ out.writeString(toString());
}
-
+
public int describeContents() {
return CONTENTS_FILE_DESCRIPTOR;
}
diff --git a/tests/sketch/src/com/android/gesture/GestureActionListener.java b/tests/sketch/src/com/android/gesture/GestureActionListener.java
new file mode 100644
index 0000000..130ac19
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureActionListener.java
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+
+public interface GestureActionListener {
+ public void onGesturePerformed(GestureOverlay overlay, Gesture gesture);
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureConstants.java b/tests/sketch/src/com/android/gesture/GestureConstants.java
new file mode 100644
index 0000000..0e17c8a
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureConstants.java
@@ -0,0 +1,31 @@
+/*
+ * 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.gesture;
+
+interface GestureConstants {
+ static final String XML_TAG_LIBRARY = "library";
+ static final String XML_TAG_ENTRY = "entry";
+ static final String XML_TAG_GESTURE = "gesture";
+ static final String XML_TAG_STROKE = "stroke";
+ static final String XML_TAG_ID = "id";
+ static final String XML_TAG_NAME = "name";
+ static final String STRING_GESTURE_DELIIMITER = "#";
+ static final String STRING_STROKE_DELIIMITER = ",";
+ static final int STROKE_STRING_BUFFER_SIZE = 1024;
+ static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
+ static final int IO_BUFFER_SIZE = 8 * 1024; // 8K
+}
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/GestureLibrary.java b/tests/sketch/src/com/android/gesture/GestureLibrary.java
new file mode 100644
index 0000000..c89aa16
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureLibrary.java
@@ -0,0 +1,337 @@
+/*
+ * 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.Config;
+import android.util.Log;
+import android.util.Xml;
+import android.util.Xml.Encoding;
+
+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;
+
+/**
+ * GestureLibrary maintains gesture examples and makes predictions on a new
+ * gesture
+ */
+public class GestureLibrary {
+
+ public static final int SEQUENCE_INVARIANT = 1;
+
+ // when SEQUENCE_SENSITIVE is used, only single stroke gestures are allowed
+ public static final int SEQUENCE_SENSITIVE = 2;
+
+ private int mSequenceType = SEQUENCE_SENSITIVE;
+
+ public static final int ORIENTATION_INVARIANT = 1;
+
+ // ORIENTATION_SENSITIVE is only available for single stroke gestures
+ public static final int ORIENTATION_SENSITIVE = 2;
+
+ private int mOrientationStyle = ORIENTATION_SENSITIVE;
+
+ private static final String LOGTAG = "GestureLibrary";
+
+ private static final String NAMESPACE = "";
+
+ private final String mGestureFileName;
+
+ private HashMap<String, ArrayList<Gesture>> mEntryName2gestures = 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 whether the gesture library will handle orientation sensitive
+ * gestures. Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
+ *
+ * @param style
+ */
+ public void setOrientationStyle(int style) {
+ mOrientationStyle = style;
+ }
+
+ public int getOrientationStyle() {
+ return mOrientationStyle;
+ }
+
+ public void setGestureType(int type) {
+ mSequenceType = type;
+ }
+
+ public int getGestureType() {
+ return mSequenceType;
+ }
+
+ /**
+ * Get all the gesture entry names in the library
+ *
+ * @return a set of strings
+ */
+ public Set<String> getGestureEntries() {
+ return mEntryName2gestures.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(this, gesture, null);
+ return mClassifier.classify(this, instance);
+ }
+
+ /**
+ * Add a gesture for the entry
+ *
+ * @param entryName entry name
+ * @param gesture
+ */
+ public void addGesture(String entryName, Gesture gesture) {
+ if (Config.DEBUG) {
+ Log.v(LOGTAG, "Add an example for gesture: " + entryName);
+ }
+ if (entryName == null || entryName.length() == 0) {
+ return;
+ }
+ ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
+ if (gestures == null) {
+ gestures = new ArrayList<Gesture>();
+ mEntryName2gestures.put(entryName, gestures);
+ }
+ gestures.add(gesture);
+ mClassifier.addInstance(Instance.createInstance(this, 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 = mEntryName2gestures.get(entryName);
+ if (gestures == null) {
+ return;
+ }
+
+ gestures.remove(gesture);
+
+ // if there are no more samples, remove the entry automatically
+ if (gestures.isEmpty()) {
+ mEntryName2gestures.remove(entryName);
+ }
+
+ mClassifier.removeInstance(gesture.getID());
+
+ mChanged = true;
+ }
+
+ /**
+ * Remove a entry of gestures
+ *
+ * @param entryName the entry name
+ */
+ public void removeEntireEntry(String entryName) {
+ mEntryName2gestures.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
+ */
+ @SuppressWarnings("unchecked")
+ public ArrayList<Gesture> getGestures(String entryName) {
+ ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
+ if (gestures != null) {
+ return (ArrayList<Gesture>)gestures.clone();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Save the gesture library
+ */
+ public void save() {
+ if (!mChanged)
+ return;
+
+ try {
+ File file = new File(mGestureFileName);
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+ if (Config.DEBUG) {
+ Log.v(LOGTAG, "Save to " + mGestureFileName);
+ }
+ BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(
+ mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
+
+ PrintWriter writer = new PrintWriter(outputStream);
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(writer);
+ serializer.startDocument(Encoding.ISO_8859_1.name(), null);
+ serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
+ HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures;
+ Iterator<String> it = maps.keySet().iterator();
+ while (it.hasNext()) {
+ String key = it.next();
+ ArrayList<Gesture> examples = maps.get(key);
+ // save an entry
+ serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
+ serializer.attribute(NAMESPACE, GestureConstants.XML_TAG_NAME, key);
+ int count = examples.size();
+ for (int i = 0; i < count; i++) {
+ Gesture gesture = examples.get(i);
+ // save each gesture in the entry
+ gesture.toXML(NAMESPACE, serializer);
+ }
+ serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
+ }
+ serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
+ serializer.endDocument();
+ serializer.flush();
+ writer.close();
+ outputStream.close();
+ mChanged = false;
+ } catch (IOException ex) {
+ Log.d(LOGTAG, "Failed to save gestures:", ex);
+ }
+ }
+
+ /**
+ * Load the gesture library
+ */
+ public void load() {
+ File file = new File(mGestureFileName);
+ if (file.exists()) {
+ try {
+ if (Config.DEBUG) {
+ Log.v(LOGTAG, "Load from " + mGestureFileName);
+ }
+ BufferedInputStream in = new BufferedInputStream(new FileInputStream(
+ mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
+ Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
+ in.close();
+ } catch (SAXException ex) {
+ Log.d(LOGTAG, "Failed to load gestures:", ex);
+ } catch (IOException ex) {
+ Log.d(LOGTAG, "Failed to load gestures:", ex);
+ }
+ }
+ }
+
+ private class CompactInkHandler implements ContentHandler {
+ Gesture currentGesture = null;
+
+ StringBuilder buffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
+
+ String entryName;
+
+ ArrayList<Gesture> gestures;
+
+ CompactInkHandler() {
+ }
+
+ public void characters(char[] ch, int start, int length) {
+ buffer.append(ch, start, length);
+ }
+
+ public void endDocument() {
+ }
+
+ public void endElement(String uri, String localName, String qName) {
+ if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
+ mEntryName2gestures.put(entryName, gestures);
+ gestures = null;
+ } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
+ gestures.add(currentGesture);
+ mClassifier.addInstance(Instance.createInstance(GestureLibrary.this,
+ currentGesture, entryName));
+ currentGesture = null;
+ } else if (localName.equals(GestureConstants.XML_TAG_STROKE)) {
+ currentGesture.addStroke(GestureStroke.createFromString(buffer.toString()));
+ buffer.setLength(0);
+ }
+ }
+
+ public void endPrefixMapping(String prefix) {
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length) {
+ }
+
+ public void processingInstruction(String target, String data) {
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ }
+
+ public void skippedEntity(String name) {
+ }
+
+ public void startDocument() {
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
+ gestures = new ArrayList<Gesture>();
+ entryName = attributes.getValue(NAMESPACE, GestureConstants.XML_TAG_NAME);
+ } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
+ currentGesture = new Gesture();
+ currentGesture.setID(Long.parseLong(attributes.getValue(NAMESPACE,
+ GestureConstants.XML_TAG_ID)));
+ }
+ }
+
+ public void startPrefixMapping(String prefix, String uri) {
+ }
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/GestureListener.java
index ebb4149..9b50714 100755
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/tests/sketch/src/com/android/gesture/GestureListener.java
@@ -18,8 +18,13 @@
import android.view.MotionEvent;
+/**
+ * An interface for processing gesture events
+ */
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 void onStartGesture(GestureOverlay overlay, MotionEvent event);
+
+ public void onGesture(GestureOverlay overlay, MotionEvent event);
+
+ public void onFinishGesture(GestureOverlay overlay, MotionEvent event);
}
diff --git a/tests/sketch/src/com/android/gesture/GestureOverlay.java b/tests/sketch/src/com/android/gesture/GestureOverlay.java
new file mode 100755
index 0000000..9907831
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureOverlay.java
@@ -0,0 +1,386 @@
+/*
+ * 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.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+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 GestureOverlay extends View {
+
+ static final float TOUCH_TOLERANCE = 3;
+
+ private static final int TRANSPARENT_BACKGROUND = Color.argb(0, 0, 0, 0);
+
+ private static final float FADING_ALPHA_CHANGE = 0.03f;
+
+ private static final long FADING_REFRESHING_RATE = 100;
+
+ private static final int GESTURE_STROKE_WIDTH = 12;
+
+ private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
+
+ private static final BlurMaskFilter BLUR_MASK_FILTER = new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL);
+
+ private static final boolean DITHER_FLAG = true;
+
+ private static final int REFRESH_RANGE = 10;
+
+ public static final int DEFAULT_GESTURE_COLOR = Color.argb(255, 255, 255, 0);
+
+ // double buffering
+ private Paint mGesturePaint;
+
+ private Bitmap mBitmap; // with transparent background
+
+ private Canvas mBitmapCanvas;
+
+ // 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;
+
+ // gesture event handlers
+ ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
+
+ private ArrayList<GesturePoint> mPointBuffer = null;
+
+ // fading out effect
+ private boolean mIsFadingOut = false;
+
+ private float mFadingAlpha = 1;
+
+ private Handler mHandler = new Handler();
+
+ private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+
+ private 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 GestureOverlay(Context context) {
+ super(context);
+ init();
+ }
+
+ public GestureOverlay(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 setGestureColor(int color) {
+ mGesturePaint.setColor(color);
+ if (mCurrentGesture != null) {
+ mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+ mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+ }
+ }
+
+ /**
+ * 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();
+ mGesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
+ mGesturePaint.setColor(DEFAULT_GESTURE_COLOR);
+ mGesturePaint.setStyle(Paint.Style.STROKE);
+ mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
+ mGesturePaint.setStrokeCap(Paint.Cap.ROUND);
+ mGesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
+ mGesturePaint.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;
+ mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
+ mBitmapCanvas = new Canvas(mBitmap);
+ mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
+ if (mCurrentGesture != null) {
+ mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+ }
+ }
+
+ public void addGestureListener(GestureListener listener) {
+ mGestureListeners.add(listener);
+ }
+
+ public void removeGestureListener(GestureListener listener) {
+ mGestureListeners.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_REFRESHING_RATE);
+ } 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
+ ArrayList<GestureListener> listeners = mGestureListeners;
+ int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ GestureListener listener = listeners.get(i);
+ listener.onStartGesture(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
+ ArrayList<GestureListener> listeners = mGestureListeners;
+ int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ GestureListener listener = listeners.get(i);
+ listener.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
+ ArrayList<GestureListener> listeners = mGestureListeners;
+ int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ GestureListener listener = listeners.get(i);
+ listener.onFinishGesture(this, event);
+ }
+
+ mPath = null;
+ mPointBuffer = null;
+ }
+
+}
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/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/GesturePoint.java
old mode 100755
new mode 100644
similarity index 60%
copy from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
copy to tests/sketch/src/com/android/gesture/GesturePoint.java
index c318754..d06eff47
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/GesturePoint.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.
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package com.android.gesture.recognizer;
+package com.android.gesture;
/**
- *
- * A recognition result that includes the label and its score
+ * A timed point of a gesture stroke
*/
-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;
- }
+
+public class GesturePoint {
+ public final float xpos;
+
+ public final float ypos;
+
+ public final long timestamp;
+
+ public GesturePoint(float x, float y, long t) {
+ xpos = x;
+ ypos = y;
+ timestamp = t;
+ }
}
diff --git a/tests/sketch/src/com/android/gesture/GestureStroke.java b/tests/sketch/src/com/android/gesture/GestureStroke.java
new file mode 100644
index 0000000..b5e38b7
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureStroke.java
@@ -0,0 +1,238 @@
+/*
+ * 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.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+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 pts
+ */
+ public GestureStroke(ArrayList<GesturePoint> pts) {
+ float[] tmpPoints = new float[pts.size() * 2];
+ long[] times = new long[pts.size()];
+
+ RectF bx = null;
+ float len = 0;
+ int index = 0;
+ int count = pts.size();
+
+ for (int i = 0; i < count; i++) {
+ GesturePoint p = pts.get(i);
+ tmpPoints[i * 2] = p.xpos;
+ tmpPoints[i * 2 + 1] = p.ypos;
+ times[index] = p.timestamp;
+
+ if (bx == null) {
+ bx = new RectF();
+ bx.top = p.ypos;
+ bx.left = p.xpos;
+ bx.right = p.xpos;
+ bx.bottom = p.ypos;
+ len = 0;
+ } else {
+ len += Math.sqrt(Math.pow(p.xpos - tmpPoints[(i - 1) * 2], 2)
+ + Math.pow(p.ypos - tmpPoints[(i -1 ) * 2 + 1], 2));
+ bx.union(p.xpos, p.ypos);
+ }
+ index++;
+ }
+
+ timestamps = times;
+ 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) {
+ float[] pts = points;
+ int count = pts.length;
+ Path path = null;
+ float mX = 0, mY = 0;
+ 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 >= 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) {
+ float[] pts = GestureUtils.temporalSampling(this, numSample);
+ RectF rect = boundingBox;
+ float scale = height / rect.height();
+ Matrix matrix = new Matrix();
+ matrix.setTranslate(-rect.left, -rect.top);
+ Matrix scaleMatrix = new Matrix();
+ scaleMatrix.setScale(scale, scale);
+ matrix.postConcat(scaleMatrix);
+ Matrix translate = new Matrix();
+ matrix.postConcat(translate);
+ matrix.mapPoints(pts);
+
+ Path path = null;
+ float mX = 0;
+ float mY = 0;
+ 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 >= GestureOverlay.TOUCH_TOLERANCE || dy >= GestureOverlay.TOUCH_TOLERANCE) {
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+ return path;
+ }
+
+ /**
+ * Save the gesture stroke as XML
+ *
+ * @param namespace
+ * @param serializer
+ * @throws IOException
+ */
+ void toXML(String namespace, XmlSerializer serializer) throws IOException {
+ serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE);
+ serializer.text(toString());
+ serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE);
+ }
+
+ /**
+ * Create a gesture stroke from a string
+ *
+ * @param str
+ * @return the gesture stroke
+ */
+ public static GestureStroke createFromString(String str) {
+ ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(
+ GestureConstants.STROKE_POINT_BUFFER_SIZE);
+ int endIndex;
+ int startIndex = 0;
+ while ((endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1)) != -1) {
+
+ // parse x
+ String token = str.substring(startIndex, endIndex);
+ float x = Float.parseFloat(token);
+ startIndex = endIndex + 1;
+
+ // parse y
+ endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
+ token = str.substring(startIndex, endIndex);
+ float y = Float.parseFloat(token);
+ startIndex = endIndex + 1;
+
+ // parse t
+ endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
+ token = str.substring(startIndex, endIndex);
+ long time = Long.parseLong(token);
+ startIndex = endIndex + 1;
+
+ points.add(new GesturePoint(x, y, time));
+ }
+ return new GestureStroke(points);
+ }
+
+ /**
+ * Convert the stroke to string
+ */
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
+ float[] pts = points;
+ long[] times = timestamps;
+ int count = points.length;
+ for (int i = 0; i < count; i += 2) {
+ str.append(points[i] + GestureConstants.STRING_STROKE_DELIIMITER + points[i + 1]
+ + GestureConstants.STRING_STROKE_DELIIMITER + times[i / 2]
+ + GestureConstants.STRING_STROKE_DELIIMITER);
+ }
+ return str.toString();
+ }
+
+ /**
+ * Invalidate the cached path that is used for rendering the stroke
+ */
+ public void invalidate() {
+ mCachedPath = null;
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureUtils.java b/tests/sketch/src/com/android/gesture/GestureUtils.java
new file mode 100755
index 0000000..09d2625
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureUtils.java
@@ -0,0 +1,426 @@
+/*
+ * 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.RectF;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class GestureUtils {
+
+ private static final int TEMPORAL_SAMPLING_RATE = 16;
+
+ protected 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;
+ android.graphics.Matrix trans = new android.graphics.Matrix();
+ trans.setScale(scale, scale);
+ android.graphics.Matrix translate1 = new android.graphics.Matrix();
+ translate1.setTranslate(-rect.centerX(), -rect.centerY());
+ trans.preConcat(translate1);
+ android.graphics.Matrix translate2 = new android.graphics.Matrix();
+ translate2.setTranslate(targetPatchSize / 2, targetPatchSize / 2);
+ trans.postConcat(translate2);
+
+ ArrayList<GestureStroke> strokes = gesture.getStrokes();
+ int count = strokes.size();
+ int size;
+ float xpos;
+ float ypos;
+ for (int index = 0; index < count; index++) {
+ GestureStroke stroke = strokes.get(index);
+ size = stroke.points.length;
+ 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
+ */
+ protected 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
+ */
+ public 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;
+ }
+
+ public 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;
+ }
+
+ 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;
+ }
+
+ /**
+ * Calculate the squared Euclidean distance between two vectors
+ *
+ * @param vector1
+ * @param vector2
+ * @return the distance
+ */
+ protected 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 in1
+ * @param in2
+ * @return the distance between 0 and Math.PI
+ */
+ protected static double cosineDistance(Instance in1, Instance in2) {
+ float sum = 0;
+ float[] vector1 = in1.vector;
+ float[] vector2 = in2.vector;
+ int len = vector1.length;
+ for (int i = 0; i < len; i++) {
+ sum += vector1[i] * vector2[i];
+ }
+ return Math.acos(sum / (in1.magnitude * in2.magnitude));
+ }
+
+ public static OrientedBoundingBox computeOrientedBBX(ArrayList<GesturePoint> pts) {
+ GestureStroke stroke = new GestureStroke(pts);
+ float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE);
+ return computeOrientedBBX(points);
+ }
+
+ public static OrientedBoundingBox computeOrientedBBX(float[] points) {
+ float[] meanVector = computeCentroid(points);
+ return computeOrientedBBX(points, meanVector);
+ }
+
+ public static OrientedBoundingBox computeOrientedBBX(float[] points, float[] centroid) {
+
+ android.graphics.Matrix tr = new android.graphics.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];
+ }
+ }
+
+ OrientedBoundingBox bbx = new OrientedBoundingBox(angle, centroid[0], centroid[1], maxx
+ - minx, maxy - miny);
+ return bbx;
+ }
+
+ 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/tests/sketch/src/com/android/gesture/Instance.java b/tests/sketch/src/com/android/gesture/Instance.java
new file mode 100755
index 0000000..4fbebf9
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/Instance.java
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+/**
+ * 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 = 8;
+
+ 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 length of the vector
+ final float magnitude;
+
+ // the id of the instance
+ final long instanceID;
+
+ private Instance(long id, float[] sample, String sampleName) {
+ instanceID = id;
+ vector = sample;
+ label = sampleName;
+ float sum = 0;
+ int size = sample.length;
+ for (int i = 0; i < size; i++) {
+ sum += sample[i] * sample[i];
+ }
+ magnitude = (float) Math.sqrt(sum);
+ }
+
+ /**
+ * create a learning instance for a single stroke gesture
+ *
+ * @param gesture
+ * @param label
+ * @return the instance
+ */
+ static Instance createInstance(GestureLibrary gesturelib, Gesture gesture, String label) {
+ float[] pts;
+ if (gesturelib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
+ pts = temporalSampler(gesturelib, gesture);
+ } else {
+ pts = spatialSampler(gesture);
+ }
+ return new Instance(gesture.getID(), pts, label);
+ }
+
+ private static float[] spatialSampler(Gesture gesture) {
+ float[] pts = GestureUtils.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
+ return pts;
+ }
+
+ private static float[] temporalSampler(GestureLibrary gesturelib, Gesture gesture) {
+ float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
+ SEQUENCE_SAMPLE_SIZE);
+ float[] center = GestureUtils.computeCentroid(pts);
+ float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
+ orientation *= 180 / Math.PI;
+
+ float adjustment = -orientation;
+ if (gesturelib.getOrientationStyle() == 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;
+ }
+ }
+ }
+
+ android.graphics.Matrix m = new android.graphics.Matrix();
+ m.setTranslate(-center[0], -center[1]);
+ android.graphics.Matrix rotation = new android.graphics.Matrix();
+ rotation.setRotate(adjustment);
+ m.postConcat(rotation);
+ m.mapPoints(pts);
+ return pts;
+ }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/InstanceLearner.java b/tests/sketch/src/com/android/gesture/InstanceLearner.java
new file mode 100644
index 0000000..95241d4
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/InstanceLearner.java
@@ -0,0 +1,105 @@
+/*
+ * 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.Config;
+import android.util.Log;
+
+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 {
+
+ private static final String LOGTAG = "InstanceLearner";
+
+ @Override
+ ArrayList<Prediction> classify(GestureLibrary lib, Instance instance) {
+ 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 != instance.vector.length) {
+ continue;
+ }
+ double distance;
+ if (lib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
+ distance = GestureUtils.cosineDistance(sample, instance);
+ } else {
+ distance = GestureUtils.squaredEuclideanDistance(sample.vector, instance.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;
+ Iterator<String> lableIterator = label2score.keySet().iterator();
+ while (lableIterator.hasNext()) {
+ String name = lableIterator.next();
+ double score = label2score.get(name);
+ sum += score;
+ predictions.add(new Prediction(name, score));
+ }
+
+ // normalize
+ Iterator<Prediction> predictionIterator = predictions.iterator();
+ while (predictionIterator.hasNext()) {
+ Prediction name = predictionIterator.next();
+ name.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;
+ }
+ }
+ });
+
+ if (Config.DEBUG) {
+ predictionIterator = predictions.iterator();
+ while (predictionIterator.hasNext()) {
+ Prediction name = predictionIterator.next();
+ Log.v(LOGTAG, "prediction [" + name.name + " = " + name.score + "]");
+ }
+ }
+
+ return predictions;
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/Learner.java b/tests/sketch/src/com/android/gesture/Learner.java
new file mode 100755
index 0000000..63f3156
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/Learner.java
@@ -0,0 +1,82 @@
+/*
+ * 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 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.instanceID) {
+ instances.remove(instance);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Remove all the instances of a category
+ *
+ * @param name the category name
+ */
+ void removeInstances(String name) {
+ ArrayList<Instance> toDelete = new ArrayList<Instance>();
+ ArrayList<Instance> instances = mInstances;
+ int count = instances.size();
+ for (int i = 0; i < count; i++) {
+ Instance instance = instances.get(i);
+ if (instance.label.equals(name)) {
+ toDelete.add(instance);
+ }
+ }
+ mInstances.removeAll(toDelete);
+ }
+
+ abstract ArrayList<Prediction> classify(GestureLibrary library, Instance instance);
+}
diff --git a/tests/sketch/src/com/android/gesture/LetterRecognizer.java b/tests/sketch/src/com/android/gesture/LetterRecognizer.java
new file mode 100644
index 0000000..1c15c7d
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/LetterRecognizer.java
@@ -0,0 +1,198 @@
+/*
+ * 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.gesture;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class LetterRecognizer {
+
+ private static final String LOGTAG = "LetterRecognizer";
+
+ public final static int LATTIN_LOWERCASE = 0;
+
+ private SigmoidUnit[] mHiddenLayer;
+
+ private SigmoidUnit[] mOutputLayer;
+
+ private final String[] mClasses;
+
+ private final int mInputCount;
+
+ private class SigmoidUnit {
+
+ private float[] mWeights;
+
+ private SigmoidUnit(float[] weights) {
+ mWeights = weights;
+ }
+
+ private float compute(float[] inputs) {
+ float sum = 0;
+ int count = inputs.length;
+ float[] weights = mWeights;
+ for (int i = 0; i < count; i++) {
+ sum += inputs[i] * weights[i];
+ }
+ sum += weights[weights.length - 1];
+ return 1 / (float)(1 + Math.exp(-sum));
+ }
+ }
+
+ private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
+ mInputCount = (int)Math.sqrt(numOfInput);
+ mHiddenLayer = new SigmoidUnit[numOfHidden];
+ mClasses = classes;
+ mOutputLayer = new SigmoidUnit[classes.length];
+ }
+
+ public static LetterRecognizer getLetterRecognizer(Context context, int type) {
+ switch (type) {
+ case LATTIN_LOWERCASE: {
+ return createFromResource(context, com.android.internal.R.raw.lattin_lowercase);
+ }
+ }
+ return null;
+ }
+
+ public ArrayList<Prediction> recognize(Gesture gesture) {
+ return this.classify(GestureUtils.spatialSampling(gesture, mInputCount));
+ }
+
+ private ArrayList<Prediction> classify(float[] vector) {
+ float[] intermediateOutput = compute(mHiddenLayer, vector);
+ float[] output = compute(mOutputLayer, intermediateOutput);
+ ArrayList<Prediction> predictions = new ArrayList<Prediction>();
+ double sum = 0;
+ int count = mClasses.length;
+ for (int i = 0; i < count; i++) {
+ String name = mClasses[i];
+ double score = output[i];
+ sum += score;
+ predictions.add(new Prediction(name, score));
+ }
+
+ for (int i = 0; i < count; i++) {
+ Prediction name = predictions.get(i);
+ name.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) {
+ float[] output = new float[layer.length];
+ 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) {
+ Resources resources = context.getResources();
+ InputStream stream = resources.openRawResource(resourceID);
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+
+ String line = reader.readLine();
+ int startIndex = 0;
+ int endIndex = -1;
+ endIndex = line.indexOf(" ", startIndex);
+ int iCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ startIndex = endIndex + 1;
+ endIndex = line.indexOf(" ", startIndex);
+ int hCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ startIndex = endIndex + 1;
+ endIndex = line.length();
+ int oCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+ String[] classes = new String[oCount];
+ line = reader.readLine();
+ startIndex = 0;
+ endIndex = -1;
+ for (int i = 0; i < oCount; i++) {
+ endIndex = line.indexOf(" ", startIndex);
+ classes[i] = line.substring(startIndex, endIndex);
+ startIndex = endIndex + 1;
+ }
+
+ LetterRecognizer classifier = new LetterRecognizer(iCount, hCount, classes);
+ SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
+ SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
+
+ for (int i = 0; i < hCount; i++) {
+ float[] weights = new float[iCount];
+ line = reader.readLine();
+ startIndex = 0;
+ for (int j = 0; j < iCount; j++) {
+ endIndex = line.indexOf(" ", startIndex);
+ weights[j] = Float.parseFloat(line.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+ hiddenLayer[i] = classifier.new SigmoidUnit(weights);
+ }
+
+ for (int i = 0; i < oCount; i++) {
+ float[] weights = new float[hCount];
+ line = reader.readLine();
+ startIndex = 0;
+ for (int j = 0; j < hCount; j++) {
+ endIndex = line.indexOf(" ", startIndex);
+ weights[j] = Float.parseFloat(line.substring(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+ outputLayer[i] = classifier.new SigmoidUnit(weights);
+ }
+
+ reader.close();
+
+ classifier.mHiddenLayer = hiddenLayer;
+ classifier.mOutputLayer = outputLayer;
+
+ return classifier;
+
+ } catch (IOException ex) {
+ Log.d(LOGTAG, "Failed to save gestures:", ex);
+ }
+ return null;
+ }
+}
diff --git a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java b/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
new file mode 100644
index 0000000..90c3969
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
@@ -0,0 +1,81 @@
+/*
+ * 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.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;
+ }
+ }
+
+ 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/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/Prediction.java
similarity index 65%
rename from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
rename to tests/sketch/src/com/android/gesture/Prediction.java
index c318754..92d3ba4 100755
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/Prediction.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.
@@ -14,23 +14,20 @@
* limitations under the License.
*/
-package com.android.gesture.recognizer;
+package com.android.gesture;
-/**
- *
- * 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 final String name;
+
+ public double score;
+
+ Prediction(String label, double predictionScore) {
+ name = label;
+ score = predictionScore;
+ }
+
+ @Override
public String toString() {
- return label;
- }
+ return name;
+ }
}
diff --git a/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java b/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
new file mode 100644
index 0000000..0ffc370
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
@@ -0,0 +1,147 @@
+/*
+ * 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.Color;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * 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 TouchThroughGesturing implements GestureListener {
+
+ public static final int SINGLE_STROKE = 0;
+
+ public static final int MULTIPLE_STROKE = 1;
+
+ private static final float STROKE_LENGTH_THRESHOLD = 30;
+
+ private static final float SQUARENESS_THRESHOLD = 0.275f;
+
+ private static final float ANGLE_THRESHOLD = 40;
+
+ public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
+
+ private boolean mIsGesturing = false;
+
+ private float mTotalLength;
+
+ private float mX, mY;
+
+ private View mModel;
+
+ private int mGestureType = SINGLE_STROKE;
+
+ private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
+
+ private ArrayList<GestureActionListener> mActionListeners = new ArrayList<GestureActionListener>();
+
+ public TouchThroughGesturing(View model) {
+ mModel = model;
+ }
+
+ /**
+ *
+ * @param type SINGLE_STROKE or MULTIPLE_STROKE
+ */
+ public void setGestureType(int type) {
+ mGestureType = type;
+ }
+
+ public void setUncertainGestureColor(int color) {
+ mUncertainGestureColor = color;
+ }
+
+ public void onStartGesture(GestureOverlay 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.setGestureColor(mUncertainGestureColor);
+ }
+ mModel.dispatchTouchEvent(event);
+ }
+
+ public void onGesture(GestureOverlay overlay, MotionEvent event) {
+ if (mIsGesturing) {
+ return;
+ }
+ float x = event.getX();
+ float y = event.getY();
+ float dx = x - mX;
+ float dy = y - mY;
+ mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
+ mX = x;
+ mY = y;
+
+ if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
+ OrientedBoundingBox bbx = GestureUtils.computeOrientedBBX(overlay.getCurrentStroke());
+ float angle = Math.abs(bbx.orientation);
+ if (angle > 90) {
+ angle = 180 - angle;
+ }
+ if (bbx.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
+ mIsGesturing = true;
+ overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
+ 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());
+ }
+ }
+ mModel.dispatchTouchEvent(event);
+ }
+
+ public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
+ if (mIsGesturing) {
+ overlay.clear(true);
+ ArrayList<GestureActionListener> listeners = mActionListeners;
+ int count = listeners.size();
+ for (int i = 0; i < count; i++) {
+ GestureActionListener listener = listeners.get(i);
+ listener.onGesturePerformed(overlay, overlay.getCurrentGesture());
+ }
+ } else {
+ mModel.dispatchTouchEvent(event);
+ overlay.clear(false);
+ }
+ }
+
+ public void addGestureActionListener(GestureActionListener listener) {
+ mActionListeners.add(listener);
+ }
+
+ public void removeGestureActionListener(GestureActionListener listener) {
+ mActionListeners.remove(listener);
+ }
+
+ public boolean isGesturing() {
+ return mIsGesturing;
+ }
+}
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/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/example/ContactItem.java
old mode 100755
new mode 100644
similarity index 62%
copy from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
copy to tests/sketch/src/com/android/gesture/example/ContactItem.java
index c318754..557c4d9
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/example/ContactItem.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.
@@ -14,23 +14,21 @@
* limitations under the License.
*/
-package com.android.gesture.recognizer;
+package com.android.gesture.example;
-/**
- *
- * 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
+
+class ContactItem {
+ final String itemName;
+
+ final long itemID;
+
+ public ContactItem(long id, String name) {
+ itemID = id;
+ itemName = name;
+ }
+
+ @Override
public String toString() {
- return label;
- }
+ 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..1d3fdf3
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
@@ -0,0 +1,122 @@
+/*
+ * 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 com.android.gesture.Gesture;
+import com.android.gesture.GestureActionListener;
+import com.android.gesture.GestureOverlay;
+import com.android.gesture.LetterRecognizer;
+import com.android.gesture.Prediction;
+import com.android.gesture.TouchThroughGesturing;
+
+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 GestureOverlay mOverlay;
+
+ private ContactAdapter mContactAdapter;
+
+ private TouchThroughGesturing 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.LATTIN_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
+ mOverlay = new GestureOverlay(this);
+ mGestureProcessor = new TouchThroughGesturing(mContactList);
+ mGestureProcessor.setGestureType(TouchThroughGesturing.MULTIPLE_STROKE);
+ mGestureProcessor.addGestureActionListener(new GestureActionListener() {
+ public void onGesturePerformed(GestureOverlay 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);
+ }
+ }
+ }
+ });
+ mOverlay.addGestureListener(mGestureProcessor);
+ ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
+ this.addContentView(mOverlay, 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..03a26da
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
@@ -0,0 +1,207 @@
+/*
+ * 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 com.android.gesture.Gesture;
+import com.android.gesture.GestureLibrary;
+import com.android.gesture.GestureListener;
+import com.android.gesture.GestureOverlay;
+import com.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 + "gestureEntry.xml";
+
+ 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 GestureOverlay 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 = (GestureOverlay) findViewById(R.id.drawingpad);
+ mGesturePad.setBackgroundColor(Color.BLACK);
+ mGesturePad.addGestureListener(new GestureListener() {
+ public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
+ recognize(overlay.getCurrentGesture());
+ }
+
+ public void onGesture(GestureOverlay overlay, MotionEvent event) {
+ }
+
+ public void onStartGesture(GestureOverlay 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..ca54110 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;
@@ -30,228 +28,156 @@
import android.widget.AdapterView.OnItemSelectedListener;
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 com.android.gesture.GestureLibrary;
+import com.android.gesture.GestureOverlay;
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 GestureOverlay 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 = (GestureOverlay) 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/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/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 b2bd9ff..49ccf71 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -495,6 +495,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)); \
@@ -1013,7 +1065,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..25ab147 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) {
@@ -1307,7 +1317,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 d476567..2a85bc7 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -524,12 +524,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;
@@ -550,6 +568,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) {
@@ -561,6 +611,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/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 64084cf..4073ddc 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));
@@ -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);