summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2009-06-24 18:31:21 -0700
committerMathias Agopian <mathias@google.com>2009-06-24 18:31:21 -0700
commitf31868e59fbf59a8d479587c80b648fb37a166fc (patch)
tree5a0aa67a76d6b0e48041f557eefd764e57eb97cf /core
parentc6603951d45fc9b0d1776fec9444b6f31af92840 (diff)
parentecf2b68d834d334de218dc427615b4ca05c0293a (diff)
downloadframeworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.zip
frameworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.tar.gz
frameworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.tar.bz2
merge master in master_gl
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ActivityManagerNative.java12
-rw-r--r--core/java/android/app/ActivityThread.java31
-rw-r--r--core/java/android/app/ApplicationContext.java5
-rw-r--r--core/java/android/app/ApplicationErrorReport.java8
-rw-r--r--core/java/android/app/ApplicationThreadNative.java14
-rw-r--r--core/java/android/app/BackupAgent.java11
-rw-r--r--core/java/android/app/FullBackupAgent.java6
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--core/java/android/app/IBackupAgent.aidl7
-rw-r--r--core/java/android/app/SearchDialog.java166
-rw-r--r--core/java/android/app/SearchManager.java70
-rw-r--r--core/java/android/app/SuggestionsAdapter.java6
-rw-r--r--core/java/android/backup/BackupDataOutput.java7
-rw-r--r--core/java/android/backup/BackupHelper.java (renamed from core/java/android/backup/RestoreHelper.java)18
-rw-r--r--core/java/android/backup/BackupHelperAgent.java56
-rw-r--r--core/java/android/backup/BackupHelperDispatcher.java (renamed from core/java/android/backup/RestoreHelperDispatcher.java)41
-rw-r--r--core/java/android/backup/FileBackupHelper.java83
-rw-r--r--core/java/android/backup/FileBackupHelperBase.java (renamed from core/java/android/backup/RestoreHelperBase.java)54
-rw-r--r--core/java/android/backup/FileRestoreHelper.java41
-rw-r--r--core/java/android/backup/IBackupManager.aidl8
-rw-r--r--core/java/android/backup/RestoreSet.java10
-rw-r--r--core/java/android/backup/SharedPreferencesBackupHelper.java40
-rw-r--r--core/java/android/content/AbstractSyncableContentProvider.java3
-rw-r--r--core/java/android/content/ContentResolver.java249
-rw-r--r--core/java/android/content/ContentService.java71
-rw-r--r--core/java/android/content/IContentService.aidl23
-rw-r--r--core/java/android/content/Intent.java9
-rw-r--r--core/java/android/content/SyncAdapterType.aidl20
-rw-r--r--core/java/android/content/SyncAdapterType.java27
-rw-r--r--core/java/android/content/SyncManager.java179
-rw-r--r--core/java/android/content/SyncStatusObserver.java21
-rw-r--r--core/java/android/content/SyncStorageEngine.java103
-rw-r--r--core/java/android/content/TempProviderSyncAdapter.java10
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java393
-rw-r--r--core/java/android/content/res/Resources.java6
-rw-r--r--core/java/android/database/BulkCursorToCursorAdaptor.java8
-rw-r--r--core/java/android/os/Debug.java15
-rw-r--r--core/java/android/provider/Browser.java16
-rw-r--r--core/java/android/provider/Settings.java10
-rw-r--r--core/java/android/provider/Sync.java649
-rw-r--r--core/java/android/provider/Telephony.java10
-rw-r--r--core/java/android/server/search/Searchables.java17
-rwxr-xr-xcore/java/android/speech/tts/ITts.aidl2
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java32
-rw-r--r--core/java/android/syncml/pim/vcard/ContactStruct.java60
-rw-r--r--core/java/android/util/DisplayMetrics.java29
-rw-r--r--core/java/android/view/MotionEvent.java55
-rw-r--r--core/java/android/view/SurfaceView.java58
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/android/view/ViewRoot.java168
-rw-r--r--core/java/android/view/WindowManager.java17
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java16
-rw-r--r--core/java/android/webkit/JWebCoreJavaBridge.java3
-rw-r--r--core/java/android/webkit/WebView.java14
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java102
-rw-r--r--core/java/android/widget/ListView.java8
-rw-r--r--core/java/android/widget/PopupWindow.java16
-rw-r--r--core/java/android/widget/RelativeLayout.java424
-rw-r--r--core/java/android/widget/TextView.java22
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl1
-rw-r--r--core/java/com/android/internal/backup/IBackupTransport.aidl77
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java120
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java121
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java10
-rw-r--r--core/java/com/google/android/mms/pdu/PduPersister.java101
-rw-r--r--core/jni/Android.mk3
-rw-r--r--core/jni/AndroidRuntime.cpp6
-rw-r--r--core/jni/android/graphics/Bitmap.cpp54
-rw-r--r--core/jni/android/graphics/Canvas.cpp3
-rw-r--r--core/jni/android/graphics/ColorFilter.cpp6
-rw-r--r--core/jni/android_backup_BackupDataOutput.cpp15
-rw-r--r--core/jni/android_backup_FileBackupHelperBase.cpp (renamed from core/jni/android_backup_FileBackupHelper.cpp)51
-rw-r--r--core/jni/android_backup_RestoreHelperBase.cpp94
-rw-r--r--core/jni/android_hardware_Camera.cpp338
-rw-r--r--core/res/AndroidManifest.xml16
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable/search_dropdown_background.9.pngbin229 -> 3058 bytes
-rw-r--r--core/res/res/drawable/search_dropdown_background_apps.9.pngbin3058 -> 0 bytes
-rw-r--r--core/res/res/layout/search_bar.xml2
-rw-r--r--core/res/res/values-bg-rBG/donottranslate-cldr.xml18
-rw-r--r--core/res/res/values-cs-rCZ/donottranslate-cldr.xml4
-rw-r--r--core/res/res/values-cs/donottranslate-cldr.xml4
-rw-r--r--core/res/res/values-da-rDK/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-de-rAT/donottranslate-cldr.xml53
-rw-r--r--core/res/res/values-de-rCH/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-de-rDE/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-de-rLI/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-de/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-en-rAU/donottranslate-cldr.xml24
-rw-r--r--core/res/res/values-en-rCA/donottranslate-cldr.xml8
-rw-r--r--core/res/res/values-en-rGB/donottranslate-cldr.xml18
-rw-r--r--core/res/res/values-en-rIE/donottranslate-cldr.xml26
-rw-r--r--core/res/res/values-en-rIN/donottranslate-cldr.xml32
-rw-r--r--core/res/res/values-en-rNZ/donottranslate-cldr.xml22
-rw-r--r--core/res/res/values-en-rZA/donottranslate-cldr.xml30
-rw-r--r--core/res/res/values-es-rUS/donottranslate-cldr.xml24
-rw-r--r--core/res/res/values-fi-rFI/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-fr-rBE/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-fr-rCH/donottranslate-cldr.xml30
-rw-r--r--core/res/res/values-hi-rIN/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-hu-rHU/donottranslate-cldr.xml20
-rw-r--r--core/res/res/values-id-rID/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-it-rCH/donottranslate-cldr.xml35
-rw-r--r--core/res/res/values-it-rIT/donottranslate-cldr.xml9
-rw-r--r--core/res/res/values-it/donottranslate-cldr.xml9
-rw-r--r--core/res/res/values-ja-rJP/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-ja/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-ko-rKR/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-ko/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-lt-rLT/donottranslate-cldr.xml32
-rw-r--r--core/res/res/values-nl-rBE/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-pt-rPT/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-sk-rSK/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-sl-rSI/donottranslate-cldr.xml34
-rw-r--r--core/res/res/values-uk-rUA/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-vi-rVN/donottranslate-cldr.xml2
-rw-r--r--core/res/res/values-zh-rCN/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values-zh-rTW/donottranslate-cldr.xml6
-rw-r--r--core/res/res/values/attrs.xml10
-rw-r--r--core/res/res/values/public.xml3
-rw-r--r--core/res/res/values/strings.xml26
121 files changed, 2944 insertions, 2186 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b6f855a..dfa8139 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -986,7 +986,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
String process = data.readString();
boolean start = data.readInt() != 0;
String path = data.readString();
- boolean res = profileControl(process, start, path);
+ ParcelFileDescriptor fd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ boolean res = profileControl(process, start, path, fd);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2232,7 +2234,7 @@ class ActivityManagerProxy implements IActivityManager
}
public boolean profileControl(String process, boolean start,
- String path) throws RemoteException
+ String path, ParcelFileDescriptor fd) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2240,6 +2242,12 @@ class ActivityManagerProxy implements IActivityManager
data.writeString(process);
data.writeInt(start ? 1 : 0);
data.writeString(path);
+ if (fd != null) {
+ data.writeInt(1);
+ fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 98bd45a..79588ea 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -48,6 +48,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -74,6 +75,7 @@ import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -1236,6 +1238,11 @@ public final class ActivityThread {
String who;
}
+ private static final class ProfilerControlData {
+ String path;
+ ParcelFileDescriptor fd;
+ }
+
private final class ApplicationThread extends ApplicationThreadNative {
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -1494,8 +1501,11 @@ public final class ActivityThread {
}
}
- public void profilerControl(boolean start, String path) {
- queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0);
+ public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
+ ProfilerControlData pcd = new ProfilerControlData();
+ pcd.path = path;
+ pcd.fd = fd;
+ queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
}
public void setSchedulingGroup(int group) {
@@ -1838,7 +1848,7 @@ public final class ActivityThread {
handleActivityConfigurationChanged((IBinder)msg.obj);
break;
case PROFILER_CONTROL:
- handleProfilerControl(msg.arg1 != 0, (String)msg.obj);
+ handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
break;
case CREATE_BACKUP_AGENT:
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -3618,15 +3628,20 @@ public final class ActivityThread {
performConfigurationChanged(r.activity, mConfiguration);
}
- final void handleProfilerControl(boolean start, String path) {
+ final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
if (start) {
- File file = new File(path);
- file.getParentFile().mkdirs();
try {
- Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
+ Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
+ 8 * 1024 * 1024, 0);
} catch (RuntimeException e) {
- Log.w(TAG, "Profiling failed on path " + path
+ Log.w(TAG, "Profiling failed on path " + pcd.path
+ " -- can the process access this path?");
+ } finally {
+ try {
+ pcd.fd.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failure closing profile fd", e);
+ }
}
} else {
Debug.stopMethodTracing();
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 1666588..8ec1445 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -1053,11 +1053,6 @@ class ApplicationContext extends Context {
}
private SearchManager getSearchManager() {
- // This is only useable in Activity Contexts
- if (getActivityToken() == null) {
- throw new AndroidRuntimeException(
- "Acquiring SearchManager objects only valid in Activity Contexts.");
- }
synchronized (mSync) {
if (mSearchManager == null) {
mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 6b17236..aeae5f9 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -171,6 +171,11 @@ public class ApplicationErrorReport implements Parcelable {
public String throwMethodName;
/**
+ * Line number the exception was thrown from.
+ */
+ public int throwLineNumber;
+
+ /**
* Stack trace.
*/
public String stackTrace;
@@ -190,6 +195,7 @@ public class ApplicationErrorReport implements Parcelable {
throwFileName = in.readString();
throwClassName = in.readString();
throwMethodName = in.readString();
+ throwLineNumber = in.readInt();
stackTrace = in.readString();
}
@@ -202,6 +208,7 @@ public class ApplicationErrorReport implements Parcelable {
dest.writeString(throwFileName);
dest.writeString(throwClassName);
dest.writeString(throwMethodName);
+ dest.writeInt(throwLineNumber);
dest.writeString(stackTrace);
}
@@ -214,6 +221,7 @@ public class ApplicationErrorReport implements Parcelable {
pw.println(prefix + "throwFileName: " + throwFileName);
pw.println(prefix + "throwClassName: " + throwClassName);
pw.println(prefix + "throwMethodName: " + throwMethodName);
+ pw.println(prefix + "throwLineNumber: " + throwLineNumber);
pw.println(prefix + "stackTrace: " + stackTrace);
}
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 4b64c94..b052c99 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -26,6 +26,7 @@ import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Parcel;
@@ -331,7 +332,9 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
boolean start = data.readInt() != 0;
String path = data.readString();
- profilerControl(start, path);
+ ParcelFileDescriptor fd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ profilerControl(start, path, fd);
return true;
}
@@ -711,11 +714,18 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
- public void profilerControl(boolean start, String path) throws RemoteException {
+ public void profilerControl(boolean start, String path,
+ ParcelFileDescriptor fd) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeInt(start ? 1 : 0);
data.writeString(path);
+ if (fd != null) {
+ data.writeInt(1);
+ fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
mRemote.transact(PROFILER_CONTROL_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 85c001c..e810775 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -78,11 +78,16 @@ public abstract class BackupAgent extends ContextWrapper {
*
* @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
* of the application's data.
+ * @param appVersionCode The android:versionCode value of the application that backed
+ * up this particular data set. This makes it easier for an application's
+ * agent to distinguish among several possible older data versions when
+ * asked to perform the restore operation.
* @param newState An open, read/write ParcelFileDescriptor pointing to an empty
* file. The application should record the final backup state
* here after restoring its data from dataFd.
*/
- public abstract void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+ public abstract void onRestore(BackupDataInput data, int appVersionCode,
+ ParcelFileDescriptor newState)
throws IOException;
@@ -121,13 +126,13 @@ public abstract class BackupAgent extends ContextWrapper {
}
}
- public void doRestore(ParcelFileDescriptor data,
+ public void doRestore(ParcelFileDescriptor data, int appVersionCode,
ParcelFileDescriptor newState) throws RemoteException {
// !!! TODO - real implementation; for now just invoke the callbacks directly
Log.v(TAG, "doRestore() invoked");
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
try {
- BackupAgent.this.onRestore(input, newState);
+ BackupAgent.this.onRestore(input, appVersionCode, newState);
} catch (IOException ex) {
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw new RuntimeException(ex);
diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java
index 89becf4..d89db96 100644
--- a/core/java/android/app/FullBackupAgent.java
+++ b/core/java/android/app/FullBackupAgent.java
@@ -48,11 +48,11 @@ public class FullBackupAgent extends BackupAgent {
}
// That's the file set; now back it all up
- FileBackupHelper helper = new FileBackupHelper(this);
- helper.performBackup(oldState, data, newState, (String[])allFiles.toArray());
+ FileBackupHelper helper = new FileBackupHelper(this, (String[])allFiles.toArray());
+ helper.performBackup(oldState, data, newState);
}
@Override
- public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
}
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 66bc85b..3ec7938 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -250,7 +250,7 @@ public interface IActivityManager extends IInterface {
// Turn on/off profiling in a particular process.
public boolean profileControl(String process, boolean start,
- String path) throws RemoteException;
+ String path, ParcelFileDescriptor fd) throws RemoteException;
public boolean shutdown(int timeout) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 029c650..c0bc2a0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -25,6 +25,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IInterface;
@@ -92,7 +93,8 @@ public interface IApplicationThread extends IInterface {
void scheduleLowMemory() throws RemoteException;
void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
void requestPss() throws RemoteException;
- void profilerControl(boolean start, String path) throws RemoteException;
+ void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
+ throws RemoteException;
void setSchedulingGroup(int group) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index bb9f008..9b0550f 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -51,9 +51,14 @@ interface IBackupAgent {
* app's backup. This is to be a <i>replacement</i> of the app's
* current data, not to be merged into it.
*
+ * @param appVersionCode The android:versionCode attribute of the application
+ * that created this data set. This can help the agent distinguish among
+ * various historical backup content possibilities.
+ *
* @param newState Read-write file, empty when onRestore() is called,
* that is to be written with the state description that holds after
* the restore has been completed.
*/
- void doRestore(in ParcelFileDescriptor data, in ParcelFileDescriptor newState);
+ void doRestore(in ParcelFileDescriptor data, int appVersionCode,
+ in ParcelFileDescriptor newState);
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 3a3a983..6ddf50f 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -44,6 +44,7 @@ import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.util.Regex;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -55,6 +56,7 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
@@ -86,13 +88,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
private static final String INSTANCE_KEY_COMPONENT = "comp";
private static final String INSTANCE_KEY_APPDATA = "data";
private static final String INSTANCE_KEY_GLOBALSEARCH = "glob";
- private static final String INSTANCE_KEY_DISPLAY_QUERY = "dQry";
- private static final String INSTANCE_KEY_DISPLAY_SEL_START = "sel1";
- private static final String INSTANCE_KEY_DISPLAY_SEL_END = "sel2";
- private static final String INSTANCE_KEY_SELECTED_ELEMENT = "slEl";
- private static final int INSTANCE_SELECTED_BUTTON = -2;
- private static final int INSTANCE_SELECTED_QUERY = -1;
-
+ private static final String INSTANCE_KEY_STORED_COMPONENT = "sComp";
+ private static final String INSTANCE_KEY_STORED_APPDATA = "sData";
+ private static final String INSTANCE_KEY_PREVIOUS_COMPONENTS = "sPrev";
+ private static final String INSTANCE_KEY_USER_QUERY = "uQry";
+
private static final int SEARCH_PLATE_LEFT_PADDING_GLOBAL = 12;
private static final int SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL = 7;
@@ -145,7 +145,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
// more than once.
private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
new WeakHashMap<String, Drawable>();
-
+
+ // Last known IME options value for the search edit text.
+ private int mSearchAutoCompleteImeOptions;
+
/**
* Constructor - fires it up and makes it look like the search UI.
*
@@ -224,6 +227,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ mSearchAutoCompleteImeOptions = mSearchAutoComplete.getImeOptions();
}
/**
@@ -310,15 +315,17 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
+ appSearchData + ", " + globalSearch + ")");
}
+ SearchManager searchManager = (SearchManager)
+ mContext.getSystemService(Context.SEARCH_SERVICE);
// Try to get the searchable info for the provided component (or for global search,
// if globalSearch == true).
- mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch);
+ mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
// If we got back nothing, and it wasn't a request for global search, then try again
// for global search, as we'll try to launch that in lieu of any component-specific search.
if (!globalSearch && mSearchable == null) {
globalSearch = true;
- mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch);
+ mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
// If we still get back null (i.e., there's not even a searchable info available
// for global search), then really give up.
@@ -333,7 +340,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
mAppSearchData = appSearchData;
// Using globalSearch here is just an optimization, just calling
// isDefaultSearchable() should always give the same result.
- mGlobalSearchMode = globalSearch || SearchManager.isDefaultSearchable(mSearchable);
+ mGlobalSearchMode = globalSearch || searchManager.isDefaultSearchable(mSearchable);
mActivityContext = mSearchable.getActivityContext(getContext());
// show the dialog. this will call onStart().
@@ -441,8 +448,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
/**
* Save the minimal set of data necessary to recreate the search
*
- * TODO: go through this and make sure that it saves everything that is needed
- *
* @return A bundle with the state of the dialog.
*/
@Override
@@ -453,20 +458,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent);
bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData);
bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode);
-
- // UI state
- bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchAutoComplete.getText().toString());
- bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchAutoComplete.getSelectionStart());
- bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchAutoComplete.getSelectionEnd());
-
- int selectedElement = INSTANCE_SELECTED_QUERY;
- if (mGoButton.isFocused()) {
- selectedElement = INSTANCE_SELECTED_BUTTON;
- } else if (mSearchAutoComplete.isPopupShowing()) {
- selectedElement = 0; // TODO mSearchTextField.getListSelection() // 0..n
- }
- bundle.putInt(INSTANCE_KEY_SELECTED_ELEMENT, selectedElement);
-
+ bundle.putParcelable(INSTANCE_KEY_STORED_COMPONENT, mStoredComponentName);
+ bundle.putBundle(INSTANCE_KEY_STORED_APPDATA, mStoredAppSearchData);
+ bundle.putParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS, mPreviousComponents);
+ bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery);
+
return bundle;
}
@@ -480,45 +476,27 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
*/
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
- // Get the launch info
ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT);
Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA);
boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH);
-
- // get the UI state
- String displayQuery = savedInstanceState.getString(INSTANCE_KEY_DISPLAY_QUERY);
- int querySelStart = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_START, -1);
- int querySelEnd = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_END, -1);
- int selectedElement = savedInstanceState.getInt(INSTANCE_KEY_SELECTED_ELEMENT);
-
- // show the dialog. skip any show/hide animation, we want to go fast.
- // send the text that actually generates the suggestions here; we'll replace the display
- // text as necessary in a moment.
- if (!show(displayQuery, false, launchComponent, appSearchData, globalSearch)) {
+ ComponentName storedComponentName =
+ savedInstanceState.getParcelable(INSTANCE_KEY_STORED_COMPONENT);
+ Bundle storedAppSearchData =
+ savedInstanceState.getBundle(INSTANCE_KEY_STORED_APPDATA);
+ ArrayList<ComponentName> previousComponents =
+ savedInstanceState.getParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS);
+ String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY);
+
+ // Set stored state
+ mStoredComponentName = storedComponentName;
+ mStoredAppSearchData = storedAppSearchData;
+ mPreviousComponents = previousComponents;
+
+ // show the dialog.
+ if (!doShow(userQuery, false, launchComponent, appSearchData, globalSearch)) {
// for some reason, we couldn't re-instantiate
return;
}
-
- mSearchAutoComplete.setText(displayQuery);
-
- // clean up the selection state
- switch (selectedElement) {
- case INSTANCE_SELECTED_BUTTON:
- mGoButton.setEnabled(true);
- mGoButton.setFocusable(true);
- mGoButton.requestFocus();
- break;
- case INSTANCE_SELECTED_QUERY:
- if (querySelStart >= 0 && querySelEnd >= 0) {
- mSearchAutoComplete.requestFocus();
- mSearchAutoComplete.setSelection(querySelStart, querySelEnd);
- }
- break;
- default:
- // TODO: defer selecting a list element until suggestion list appears
-// mSearchAutoComplete.setListSelection(selectedElement)
- break;
- }
}
/**
@@ -563,7 +541,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
}
mSearchAutoComplete.setInputType(inputType);
- mSearchAutoComplete.setImeOptions(mSearchable.getImeOptions());
+ mSearchAutoCompleteImeOptions = mSearchable.getImeOptions();
+ mSearchAutoComplete.setImeOptions(mSearchAutoCompleteImeOptions);
}
}
@@ -581,12 +560,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (mGlobalSearchMode) {
mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in
- mSearchAutoComplete.setDropDownBackgroundResource(
- com.android.internal.R.drawable.search_dropdown_background);
} else {
mSearchAutoComplete.setDropDownAlwaysVisible(false);
- mSearchAutoComplete.setDropDownBackgroundResource(
- com.android.internal.R.drawable.search_dropdown_background_apps);
}
// attach the suggestions adapter, if suggestions are available
@@ -794,7 +769,24 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
}
- public void afterTextChanged(Editable s) { }
+ public void afterTextChanged(Editable s) {
+ if (!mSearchAutoComplete.isPerformingCompletion()) {
+ // The user changed the query, check if it is a URL and if so change the search
+ // button in the soft keyboard to the 'Go' button.
+ int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION));
+ if (Regex.WEB_URL_PATTERN.matcher(mUserQuery).matches()) {
+ options = options | EditorInfo.IME_ACTION_GO;
+ } else {
+ options = options | EditorInfo.IME_ACTION_SEARCH;
+ }
+ if (options != mSearchAutoCompleteImeOptions) {
+ mSearchAutoCompleteImeOptions = options;
+ mSearchAutoComplete.setImeOptions(options);
+ // This call is required to update the soft keyboard UI with latest IME flags.
+ mSearchAutoComplete.setInputType(mSearchAutoComplete.getInputType());
+ }
+ }
+ }
};
/**
@@ -932,6 +924,32 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
/**
+ * Corrects http/https typo errors in the given url string, and if the protocol specifier was
+ * not present defaults to http.
+ *
+ * @param inUrl URL to check and fix
+ * @return fixed URL string.
+ */
+ private String fixUrl(String inUrl) {
+ if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
+ return inUrl;
+
+ if (inUrl.startsWith("http:") || inUrl.startsWith("https:")) {
+ if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
+ inUrl = inUrl.replaceFirst("/", "//");
+ } else {
+ inUrl = inUrl.replaceFirst(":", "://");
+ }
+ }
+
+ if (inUrl.indexOf("://") == -1) {
+ inUrl = "http://" + inUrl;
+ }
+
+ return inUrl;
+ }
+
+ /**
* React to the user typing "enter" or other hardwired keys while typing in the search box.
* This handles these special keys while the edit box has focus.
*/
@@ -961,7 +979,19 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (keyCode == KeyEvent.KEYCODE_ENTER
&& event.getAction() == KeyEvent.ACTION_UP) {
v.cancelLongPress();
- launchQuerySearch();
+
+ // If this is a url entered by the user and we displayed the 'Go' button which
+ // the user clicked, launch the url instead of using it as a search query.
+ if ((mSearchAutoCompleteImeOptions & EditorInfo.IME_MASK_ACTION)
+ == EditorInfo.IME_ACTION_GO) {
+ Uri uri = Uri.parse(fixUrl(mSearchAutoComplete.getText().toString()));
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ launchIntent(intent);
+ } else {
+ // Launch as a regular search.
+ launchQuerySearch();
+ }
return true;
}
if (event.getAction() == KeyEvent.ACTION_DOWN) {
@@ -1292,6 +1322,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
String query = intent.getStringExtra(SearchManager.QUERY);
setUserQuery(query);
+ mSearchAutoComplete.showDropDown();
}
/**
@@ -1440,6 +1471,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (data != null) {
intent.setData(data);
}
+ intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
if (query != null) {
intent.putExtra(SearchManager.QUERY, query);
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index eb80400..e5ba6a4 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1136,6 +1136,20 @@ public class SearchManager
public final static String QUERY = "query";
/**
+ * Intent extra data key: Use this key with
+ * {@link android.content.Intent#getStringExtra
+ * content.Intent.getStringExtra()}
+ * to obtain the query string typed in by the user.
+ * This may be different from the value of {@link #QUERY}
+ * if the intent is the result of selecting a suggestion.
+ * In that case, {@link #QUERY} will contain the value of
+ * {@link #SUGGEST_COLUMN_QUERY} for the suggestion, and
+ * {@link #USER_QUERY} will contain the string typed by the
+ * user.
+ */
+ public final static String USER_QUERY = "user_query";
+
+ /**
* Intent extra data key: Use this key with Intent.ACTION_SEARCH and
* {@link android.content.Intent#getBundleExtra
* content.Intent.getBundleExtra()}
@@ -1514,7 +1528,7 @@ public class SearchManager
/**
* Reference to the shared system search service.
*/
- private static ISearchManager sService = getSearchManagerService();
+ private static ISearchManager mService;
private final Context mContext;
@@ -1529,6 +1543,8 @@ public class SearchManager
/*package*/ SearchManager(Context context, Handler handler) {
mContext = context;
mHandler = handler;
+ mService = ISearchManager.Stub.asInterface(
+ ServiceManager.getService(Context.SEARCH_SERVICE));
}
/**
@@ -1581,7 +1597,7 @@ public class SearchManager
try {
mIsShowing = true;
// activate the search manager and start it up!
- sService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
+ mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
globalSearch, mSearchManagerCallback);
} catch (RemoteException ex) {
Log.e(TAG, "startSearch() failed: " + ex);
@@ -1603,7 +1619,7 @@ public class SearchManager
if (DBG) debug("stopSearch(), mIsShowing=" + mIsShowing);
if (!mIsShowing) return;
try {
- sService.stopSearch();
+ mService.stopSearch();
// onDismiss will also clear this, but we do it here too since onDismiss() is
// called asynchronously.
mIsShowing = false;
@@ -1725,7 +1741,7 @@ public class SearchManager
if (DBG) debug("saveSearchDialog(), mIsShowing=" + mIsShowing);
if (!mIsShowing) return null;
try {
- return sService.onSaveInstanceState();
+ return mService.onSaveInstanceState();
} catch (RemoteException ex) {
Log.e(TAG, "onSaveInstanceState() failed: " + ex);
return null;
@@ -1743,7 +1759,7 @@ public class SearchManager
if (DBG) debug("restoreSearchDialog(" + searchDialogState + ")");
if (searchDialogState == null) return;
try {
- sService.onRestoreInstanceState(searchDialogState);
+ mService.onRestoreInstanceState(searchDialogState);
} catch (RemoteException ex) {
Log.e(TAG, "onRestoreInstanceState() failed: " + ex);
}
@@ -1760,17 +1776,12 @@ public class SearchManager
if (DBG) debug("onConfigurationChanged(" + newConfig + "), mIsShowing=" + mIsShowing);
if (!mIsShowing) return;
try {
- sService.onConfigurationChanged(newConfig);
+ mService.onConfigurationChanged(newConfig);
} catch (RemoteException ex) {
Log.e(TAG, "onConfigurationChanged() failed:" + ex);
}
}
- private static ISearchManager getSearchManagerService() {
- return ISearchManager.Stub.asInterface(
- ServiceManager.getService(Context.SEARCH_SERVICE));
- }
-
/**
* Gets information about a searchable activity. This method is static so that it can
* be used from non-Activity contexts.
@@ -1782,10 +1793,10 @@ public class SearchManager
*
* @hide because SearchableInfo is not part of the API.
*/
- public static SearchableInfo getSearchableInfo(ComponentName componentName,
+ public SearchableInfo getSearchableInfo(ComponentName componentName,
boolean globalSearch) {
try {
- return sService.getSearchableInfo(componentName, globalSearch);
+ return mService.getSearchableInfo(componentName, globalSearch);
} catch (RemoteException ex) {
Log.e(TAG, "getSearchableInfo() failed: " + ex);
return null;
@@ -1797,23 +1808,22 @@ public class SearchManager
*
* @hide because SearchableInfo is not part of the API.
*/
- public static boolean isDefaultSearchable(SearchableInfo searchable) {
- SearchableInfo defaultSearchable = SearchManager.getSearchableInfo(null, true);
+ public boolean isDefaultSearchable(SearchableInfo searchable) {
+ SearchableInfo defaultSearchable = getSearchableInfo(null, true);
return defaultSearchable != null
&& defaultSearchable.getSearchActivity().equals(searchable.getSearchActivity());
}
-
+
/**
- * Gets a cursor with search suggestions. This method is static so that it can
- * be used from non-Activity context.
+ * Gets a cursor with search suggestions.
*
* @param searchable Information about how to get the suggestions.
* @param query The search text entered (so far).
- * @return a cursor with suggestions, or <code>null</null> the suggestion query failed.
- *
+ * @return a cursor with suggestions, or <code>null</null> the suggestion query failed.
+ *
* @hide because SearchableInfo is not part of the API.
*/
- public static Cursor getSuggestions(Context context, SearchableInfo searchable, String query) {
+ public Cursor getSuggestions(SearchableInfo searchable, String query) {
if (searchable == null) {
return null;
}
@@ -1852,7 +1862,7 @@ public class SearchManager
.build();
// finally, make the query
- return context.getContentResolver().query(uri, null, selection, selArgs, null);
+ return mContext.getContentResolver().query(uri, null, selection, selArgs, null);
}
/**
@@ -1864,9 +1874,9 @@ public class SearchManager
*
* @hide because SearchableInfo is not part of the API.
*/
- public static List<SearchableInfo> getSearchablesInGlobalSearch() {
+ public List<SearchableInfo> getSearchablesInGlobalSearch() {
try {
- return sService.getSearchablesInGlobalSearch();
+ return mService.getSearchablesInGlobalSearch();
} catch (RemoteException e) {
Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
return null;
@@ -1881,9 +1891,9 @@ public class SearchManager
*
* @hide because SearchableInfo is not part of the API.
*/
- public static List<SearchableInfo> getSearchablesForWebSearch() {
+ public List<SearchableInfo> getSearchablesForWebSearch() {
try {
- return sService.getSearchablesForWebSearch();
+ return mService.getSearchablesForWebSearch();
} catch (RemoteException e) {
Log.e(TAG, "getSearchablesForWebSearch() failed: " + e);
return null;
@@ -1897,9 +1907,9 @@ public class SearchManager
*
* @hide because SearchableInfo is not part of the API.
*/
- public static SearchableInfo getDefaultSearchableForWebSearch() {
+ public SearchableInfo getDefaultSearchableForWebSearch() {
try {
- return sService.getDefaultSearchableForWebSearch();
+ return mService.getDefaultSearchableForWebSearch();
} catch (RemoteException e) {
Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e);
return null;
@@ -1913,9 +1923,9 @@ public class SearchManager
*
* @hide
*/
- public static void setDefaultWebSearch(ComponentName component) {
+ public void setDefaultWebSearch(ComponentName component) {
try {
- sService.setDefaultWebSearch(component);
+ mService.setDefaultWebSearch(component);
} catch (RemoteException e) {
Log.e(TAG, "setDefaultWebSearch() failed: " + e);
}
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index ed76f4e..49c94d1 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -54,6 +54,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
private static final boolean DBG = false;
private static final String LOG_TAG = "SuggestionsAdapter";
+ private SearchManager mSearchManager;
private SearchDialog mSearchDialog;
private SearchableInfo mSearchable;
private Context mProviderContext;
@@ -92,6 +93,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
com.android.internal.R.layout.search_dropdown_item_icons_2line,
null, // no initial cursor
true); // auto-requery
+ mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
mSearchDialog = searchDialog;
mSearchable = searchable;
@@ -142,10 +144,10 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable);
}
try {
- final Cursor cursor = SearchManager.getSuggestions(mContext, mSearchable, query);
+ final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query);
// trigger fill window so the spinner stays up until the results are copied over and
// closer to being ready
- if (!mGlobalSearchMode) cursor.getCount();
+ if (!mGlobalSearchMode && cursor != null) cursor.getCount();
return cursor;
} catch (RuntimeException e) {
Log.w(LOG_TAG, "Search suggestions query threw an exception.", e);
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index 05e667e..d29c5ba 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -55,6 +55,10 @@ public class BackupDataOutput {
}
}
+ public void setKeyPrefix(String keyPrefix) {
+ setKeyPrefix_native(mBackupWriter, keyPrefix);
+ }
+
protected void finalize() throws Throwable {
try {
dtor(mBackupWriter);
@@ -62,11 +66,12 @@ public class BackupDataOutput {
super.finalize();
}
}
-
+
private native static int ctor(FileDescriptor fd);
private native static void dtor(int mBackupWriter);
private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize);
private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size);
+ private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix);
}
diff --git a/core/java/android/backup/RestoreHelper.java b/core/java/android/backup/BackupHelper.java
index e47869c..3983e28 100644
--- a/core/java/android/backup/RestoreHelper.java
+++ b/core/java/android/backup/BackupHelper.java
@@ -21,14 +21,26 @@ import android.os.ParcelFileDescriptor;
import java.io.InputStream;
/** @hide */
-public interface RestoreHelper {
+public interface BackupHelper {
/**
- * Called by RestoreHelperDispatcher to dispatch one entity of data.
+ * Based on oldState, determine which of the files from the application's data directory
+ * need to be backed up, write them to the data stream, and fill in newState with the
+ * state as it exists now.
+ */
+ public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState);
+
+ /**
+ * Called by BackupHelperDispatcher to dispatch one entity of data.
* <p class=note>
* Do not close the <code>data</code> stream. Do not read more than
* <code>dataSize</code> bytes from <code>data</code>.
*/
public void restoreEntity(BackupDataInputStream data);
- public void writeSnapshot(ParcelFileDescriptor fd);
+
+ /**
+ *
+ */
+ public void writeRestoreSnapshot(ParcelFileDescriptor fd);
}
diff --git a/core/java/android/backup/BackupHelperAgent.java b/core/java/android/backup/BackupHelperAgent.java
new file mode 100644
index 0000000..3720d50
--- /dev/null
+++ b/core/java/android/backup/BackupHelperAgent.java
@@ -0,0 +1,56 @@
+/*
+ * 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.backup;
+
+import android.app.BackupAgent;
+import android.backup.BackupHelper;
+import android.backup.BackupHelperDispatcher;
+import android.backup.BackupDataInput;
+import android.backup.BackupDataOutput;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.IOException;
+
+/** @hide */
+public class BackupHelperAgent extends BackupAgent {
+ static final String TAG = "BackupHelperAgent";
+
+ BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher();
+
+ @Override
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) {
+ mDispatcher.performBackup(oldState, data, newState);
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+ throws IOException {
+ mDispatcher.performRestore(data, appVersionCode, newState);
+ }
+
+ public BackupHelperDispatcher getDispatcher() {
+ return mDispatcher;
+ }
+
+ public void addHelper(String keyPrefix, BackupHelper helper) {
+ mDispatcher.addHelper(keyPrefix, helper);
+ }
+}
+
+
diff --git a/core/java/android/backup/RestoreHelperDispatcher.java b/core/java/android/backup/BackupHelperDispatcher.java
index 4861775..b25c3e3 100644
--- a/core/java/android/backup/RestoreHelperDispatcher.java
+++ b/core/java/android/backup/BackupHelperDispatcher.java
@@ -20,20 +20,35 @@ import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.IOException;
-import java.util.HashMap;
+import java.util.TreeMap;
import java.util.Map;
/** @hide */
-public class RestoreHelperDispatcher {
- private static final String TAG = "RestoreHelperDispatcher";
+public class BackupHelperDispatcher {
+ private static final String TAG = "BackupHelperDispatcher";
- HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
+ TreeMap<String,BackupHelper> mHelpers = new TreeMap<String,BackupHelper>();
+
+ public BackupHelperDispatcher() {
+ }
- public void addHelper(String keyPrefix, RestoreHelper helper) {
+ public void addHelper(String keyPrefix, BackupHelper helper) {
mHelpers.put(keyPrefix, helper);
}
- public void dispatch(BackupDataInput input, ParcelFileDescriptor newState) throws IOException {
+ /** TODO: Make this save and restore the key prefix. */
+ public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) {
+ // Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
+ for (Map.Entry<String,BackupHelper> entry: mHelpers.entrySet()) {
+ data.setKeyPrefix(entry.getKey());
+ entry.getValue().performBackup(oldState, data, newState);
+ }
+ }
+
+ public void performRestore(BackupDataInput input, int appVersionCode,
+ ParcelFileDescriptor newState)
+ throws IOException {
boolean alreadyComplained = false;
BackupDataInputStream stream = new BackupDataInputStream(input);
@@ -43,7 +58,7 @@ public class RestoreHelperDispatcher {
int pos = rawKey.indexOf(':');
if (pos > 0) {
String prefix = rawKey.substring(0, pos);
- RestoreHelper helper = mHelpers.get(prefix);
+ BackupHelper helper = mHelpers.get(prefix);
if (helper != null) {
stream.dataSize = input.getDataSize();
stream.key = rawKey.substring(pos+1);
@@ -63,15 +78,9 @@ public class RestoreHelperDispatcher {
input.skipEntityData(); // In case they didn't consume the data.
}
- if (mHelpers.size() > 1) {
- throw new RuntimeException("RestoreHelperDispatcher won't get your your"
- + " data in the right order yet.");
- }
-
- // Write out the state files
- for (RestoreHelper helper: mHelpers.values()) {
- // TODO: Write a header for the state
- helper.writeSnapshot(newState);
+ // Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
+ for (BackupHelper helper: mHelpers.values()) {
+ helper.writeRestoreSnapshot(newState);
}
}
}
diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java
index ed840bb..4058497 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -24,19 +24,19 @@ import java.io.File;
import java.io.FileDescriptor;
/** @hide */
-public class FileBackupHelper {
+public class FileBackupHelper extends FileBackupHelperBase implements BackupHelper {
private static final String TAG = "FileBackupHelper";
Context mContext;
- String mKeyPrefix;
+ File mFilesDir;
+ String[] mFiles;
- public FileBackupHelper(Context context) {
- mContext = context;
- }
+ public FileBackupHelper(Context context, String... files) {
+ super(context);
- public FileBackupHelper(Context context, String keyPrefix) {
mContext = context;
- mKeyPrefix = keyPrefix;
+ mFilesDir = context.getFilesDir();
+ mFiles = files;
}
/**
@@ -45,8 +45,9 @@ public class FileBackupHelper {
* state as it exists now.
*/
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
- ParcelFileDescriptor newState, String[] files) {
+ ParcelFileDescriptor newState) {
// file names
+ String[] files = mFiles;
File base = mContext.getFilesDir();
final int N = files.length;
String[] fullPaths = new String[N];
@@ -54,66 +55,18 @@ public class FileBackupHelper {
fullPaths[i] = (new File(base, files[i])).getAbsolutePath();
}
- // keys
- String[] keys = makeKeys(mKeyPrefix, files);
-
// go
- performBackup_checked(oldState, data, newState, fullPaths, keys);
+ performBackup_checked(oldState, data, newState, fullPaths, files);
}
- /**
- * If keyPrefix is not null, prepend it to each of the strings in <code>original</code>;
- * otherwise, return original.
- */
- static String[] makeKeys(String keyPrefix, String[] original) {
- if (keyPrefix != null) {
- String[] keys;
- final int N = original.length;
- keys = new String[N];
- for (int i=0; i<N; i++) {
- keys[i] = keyPrefix + ':' + original[i];
- }
- return keys;
- } else {
- return original;
- }
- }
-
- /**
- * Check the parameters so the native code doens't have to throw all the exceptions
- * since it's easier to do that from java.
- */
- static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
- ParcelFileDescriptor newState, String[] files, String[] keys) {
- if (files.length == 0) {
- return;
- }
- // files must be all absolute paths
- for (String f: files) {
- if (f.charAt(0) != '/') {
- throw new RuntimeException("files must have all absolute paths: " + f);
- }
- }
- // the length of files and keys must be the same
- if (files.length != keys.length) {
- throw new RuntimeException("files.length=" + files.length
- + " keys.length=" + keys.length);
- }
- // oldStateFd can be null
- FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
- FileDescriptor newStateFd = newState.getFileDescriptor();
- if (newStateFd == null) {
- throw new NullPointerException();
- }
-
- int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
-
- if (err != 0) {
- // TODO: more here
- throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
+ public void restoreEntity(BackupDataInputStream data) {
+ // TODO: turn this off before ship
+ Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
+ String key = data.getKey();
+ if (isKeyInList(key, mFiles)) {
+ File f = new File(mFilesDir, key);
+ writeFile(f, data);
}
}
-
- native private static int performBackup_native(FileDescriptor oldState,
- int data, FileDescriptor newState, String[] files, String[] keys);
}
+
diff --git a/core/java/android/backup/RestoreHelperBase.java b/core/java/android/backup/FileBackupHelperBase.java
index 93a8fef..03ae476 100644
--- a/core/java/android/backup/RestoreHelperBase.java
+++ b/core/java/android/backup/FileBackupHelperBase.java
@@ -25,14 +25,14 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
-class RestoreHelperBase {
+class FileBackupHelperBase {
private static final String TAG = "RestoreHelperBase";
int mPtr;
Context mContext;
boolean mExceptionLogged;
- RestoreHelperBase(Context context) {
+ FileBackupHelperBase(Context context) {
mPtr = ctor();
mContext = context;
}
@@ -45,6 +45,41 @@ class RestoreHelperBase {
}
}
+ /**
+ * Check the parameters so the native code doens't have to throw all the exceptions
+ * since it's easier to do that from java.
+ */
+ static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState, String[] files, String[] keys) {
+ if (files.length == 0) {
+ return;
+ }
+ // files must be all absolute paths
+ for (String f: files) {
+ if (f.charAt(0) != '/') {
+ throw new RuntimeException("files must have all absolute paths: " + f);
+ }
+ }
+ // the length of files and keys must be the same
+ if (files.length != keys.length) {
+ throw new RuntimeException("files.length=" + files.length
+ + " keys.length=" + keys.length);
+ }
+ // oldStateFd can be null
+ FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
+ FileDescriptor newStateFd = newState.getFileDescriptor();
+ if (newStateFd == null) {
+ throw new NullPointerException();
+ }
+
+ int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
+
+ if (err != 0) {
+ // TODO: more here
+ throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
+ }
+ }
+
void writeFile(File f, InputStream in) {
if (!(in instanceof BackupDataInputStream)) {
throw new IllegalStateException("input stream must be a BackupDataInputStream");
@@ -68,13 +103,26 @@ class RestoreHelperBase {
}
}
- public void writeSnapshot(ParcelFileDescriptor fd) {
+ public void writeRestoreSnapshot(ParcelFileDescriptor fd) {
int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
// TODO: Do something with the error.
}
+ boolean isKeyInList(String key, String[] list) {
+ for (String s: list) {
+ if (s.equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static native int ctor();
private static native void dtor(int ptr);
+
+ native private static int performBackup_native(FileDescriptor oldState,
+ int data, FileDescriptor newState, String[] files, String[] keys);
+
private static native int writeFile_native(int ptr, String filename, int backupReader);
private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
}
diff --git a/core/java/android/backup/FileRestoreHelper.java b/core/java/android/backup/FileRestoreHelper.java
deleted file mode 100644
index b7e3625..0000000
--- a/core/java/android/backup/FileRestoreHelper.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.backup;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.io.File;
-
-/** @hide */
-public class FileRestoreHelper extends RestoreHelperBase implements RestoreHelper {
- private static final String TAG = "FileRestoreHelper";
-
- File mFilesDir;
-
- public FileRestoreHelper(Context context) {
- super(context);
- mFilesDir = context.getFilesDir();
- }
-
- public void restoreEntity(BackupDataInputStream data) {
- Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); // TODO: turn this off before ship
- File f = new File(mFilesDir, data.getKey());
- writeFile(f, data);
- }
-}
-
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index efc664c..d6283d0 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -33,19 +33,19 @@ interface IBackupManager {
* Tell the system service that the caller has made changes to its
* data, and therefore needs to undergo an incremental backup pass.
*/
- oneway void dataChanged(String packageName);
+ void dataChanged(String packageName);
/**
* Notifies the Backup Manager Service that an agent has become available. This
* method is only invoked by the Activity Manager.
*/
- oneway void agentConnected(String packageName, IBinder agent);
+ void agentConnected(String packageName, IBinder agent);
/**
* Notify the Backup Manager Service that an agent has unexpectedly gone away.
* This method is only invoked by the Activity Manager.
*/
- oneway void agentDisconnected(String packageName);
+ void agentDisconnected(String packageName);
/**
* Schedule an immediate backup attempt for all pending updates. This is
@@ -57,7 +57,7 @@ interface IBackupManager {
*
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
*/
- oneway void backupNow();
+ void backupNow();
/**
* Identify the currently selected transport. Callers must hold the
diff --git a/core/java/android/backup/RestoreSet.java b/core/java/android/backup/RestoreSet.java
index 96a99ae..eeca148 100644
--- a/core/java/android/backup/RestoreSet.java
+++ b/core/java/android/backup/RestoreSet.java
@@ -43,14 +43,14 @@ public class RestoreSet implements Parcelable {
* transport. This is guaranteed to be valid for the duration of a restore
* session, but is meaningless once the session has ended.
*/
- public int token;
+ public long token;
public RestoreSet() {
// Leave everything zero / null
}
- public RestoreSet(String _name, String _dev, int _token) {
+ public RestoreSet(String _name, String _dev, long _token) {
name = _name;
device = _dev;
token = _token;
@@ -65,7 +65,7 @@ public class RestoreSet implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeString(name);
out.writeString(device);
- out.writeInt(token);
+ out.writeLong(token);
}
public static final Parcelable.Creator<RestoreSet> CREATOR
@@ -82,6 +82,6 @@ public class RestoreSet implements Parcelable {
private RestoreSet(Parcel in) {
name = in.readString();
device = in.readString();
- token = in.readInt();
+ token = in.readLong();
}
-} \ No newline at end of file
+}
diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java
index cad79df..f492629 100644
--- a/core/java/android/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/backup/SharedPreferencesBackupHelper.java
@@ -18,39 +18,51 @@ package android.backup;
import android.content.Context;
import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import java.io.File;
import java.io.FileDescriptor;
/** @hide */
-public class SharedPreferencesBackupHelper {
+public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper {
+ private static final String TAG = "SharedPreferencesBackupHelper";
+
private Context mContext;
- private String mKeyPrefix;
+ private String[] mPrefGroups;
- public SharedPreferencesBackupHelper(Context context) {
- mContext = context;
- }
+ public SharedPreferencesBackupHelper(Context context, String[] prefGroups) {
+ super(context);
- public SharedPreferencesBackupHelper(Context context, String keyPrefix) {
mContext = context;
- mKeyPrefix = keyPrefix;
+ mPrefGroups = prefGroups;
}
-
- public void performBackup(ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
- BackupDataOutput data, String[] prefGroups) {
+
+ public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) {
Context context = mContext;
// make filenames for the prefGroups
+ String[] prefGroups = mPrefGroups;
final int N = prefGroups.length;
String[] files = new String[N];
for (int i=0; i<N; i++) {
files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath();
}
- // make keys if necessary
- String[] keys = FileBackupHelper.makeKeys(mKeyPrefix, prefGroups);
-
// go
- FileBackupHelper.performBackup_checked(oldSnapshot, data, newSnapshot, files, prefGroups);
+ performBackup_checked(oldState, data, newState, files, prefGroups);
+ }
+
+ public void restoreEntity(BackupDataInputStream data) {
+ Context context = mContext;
+
+ // TODO: turn this off before ship
+ Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
+ String key = data.getKey();
+ if (isKeyInList(key, mPrefGroups)) {
+ File f = context.getSharedPrefsFile(key).getAbsoluteFile();
+ writeFile(f, data);
+ }
}
}
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index e628dcd..db73dd5 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -141,7 +141,8 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (!upgradeDatabase(db, oldVersion, newVersion)) {
mSyncState.discardSyncData(db, null /* all accounts */);
- getContext().getContentResolver().startSync(mContentUri, new Bundle());
+ ContentResolver.requestSync(null /* all accounts */,
+ mContentUri.getAuthority(), new Bundle());
}
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index a01c5d1..98ed098 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -48,9 +48,18 @@ import java.util.ArrayList;
* This class provides applications access to the content model.
*/
public abstract class ContentResolver {
- public final static String SYNC_EXTRAS_ACCOUNT = "account";
+ /**
+ * @deprecated instead use
+ * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
+ */
+ public static final String SYNC_EXTRAS_ACCOUNT = "account";
public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
+ /**
+ * @deprecated instead use
+ * {@link #SYNC_EXTRAS_MANUAL}
+ */
public static final String SYNC_EXTRAS_FORCE = "force";
+ public static final String SYNC_EXTRAS_MANUAL = "force";
public static final String SYNC_EXTRAS_UPLOAD = "upload";
public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
@@ -90,7 +99,35 @@ public abstract class ContentResolver {
* in the cursor is the same.
*/
public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
-
+
+ /** @hide */
+ public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
+ /** @hide */
+ public static final int SYNC_ERROR_AUTHENTICATION = 2;
+ /** @hide */
+ public static final int SYNC_ERROR_IO = 3;
+ /** @hide */
+ public static final int SYNC_ERROR_PARSE = 4;
+ /** @hide */
+ public static final int SYNC_ERROR_CONFLICT = 5;
+ /** @hide */
+ public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
+ /** @hide */
+ public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
+ /** @hide */
+ public static final int SYNC_ERROR_INTERNAL = 8;
+
+ /** @hide */
+ public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
+ /** @hide */
+ public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
+ /** @hide */
+ public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
+ /** @hide */
+ public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
+ /** @hide */
+ public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
+
public ContentResolver(Context context) {
mContext = context;
}
@@ -829,11 +866,42 @@ public abstract class ContentResolver {
*
* @param uri the uri of the provider to sync or null to sync all providers.
* @param extras any extras to pass to the SyncAdapter.
+ * @deprecated instead use
+ * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
*/
public void startSync(Uri uri, Bundle extras) {
+ Account account = null;
+ if (extras != null) {
+ String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
+ if (!TextUtils.isEmpty(accountName)) {
+ account = new Account(accountName, "com.google.GAIA");
+ }
+ extras.remove(SYNC_EXTRAS_ACCOUNT);
+ }
+ requestSync(account, uri != null ? uri.getAuthority() : null, extras);
+ }
+
+ /**
+ * Start an asynchronous sync operation. If you want to monitor the progress
+ * of the sync you may register a SyncObserver. Only values of the following
+ * types may be used in the extras bundle:
+ * <ul>
+ * <li>Integer</li>
+ * <li>Long</li>
+ * <li>Boolean</li>
+ * <li>Float</li>
+ * <li>Double</li>
+ * <li>String</li>
+ * </ul>
+ *
+ * @param account which account should be synced
+ * @param authority which authority should be synced
+ * @param extras any extras to pass to the SyncAdapter.
+ */
+ public static void requestSync(Account account, String authority, Bundle extras) {
validateSyncExtrasBundle(extras);
try {
- getContentService().startSync(uri, extras);
+ getContentService().requestSync(account, authority, extras);
} catch (RemoteException e) {
}
}
@@ -874,13 +942,186 @@ public abstract class ContentResolver {
}
}
+ /**
+ * Cancel any active or pending syncs that match the Uri. If the uri is null then
+ * all syncs will be canceled.
+ *
+ * @param uri the uri of the provider to sync or null to sync all providers.
+ * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
+ */
public void cancelSync(Uri uri) {
+ cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
+ }
+
+ /**
+ * Cancel any active or pending syncs that match account and authority. The account and
+ * authority can each independently be set to null, which means that syncs with any account
+ * or authority, respectively, will match.
+ *
+ * @param account filters the syncs that match by this account
+ * @param authority filters the syncs that match by this authority
+ */
+ public static void cancelSync(Account account, String authority) {
+ try {
+ getContentService().cancelSync(account, authority);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Get information about the SyncAdapters that are known to the system.
+ * @return an array of SyncAdapters that have registered with the system
+ */
+ public static SyncAdapterType[] getSyncAdapterTypes() {
+ try {
+ return getContentService().getSyncAdapterTypes();
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Check if the provider should be synced when a network tickle is received
+ *
+ * @param account the account whose setting we are querying
+ * @param authority the provider whose setting we are querying
+ * @return true if the provider should be synced when a network tickle is received
+ */
+ public static boolean getSyncAutomatically(Account account, String authority) {
+ try {
+ return getContentService().getSyncAutomatically(account, authority);
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Set whether or not the provider is synced when it receives a network tickle.
+ *
+ * @param account the account whose setting we are querying
+ * @param authority the provider whose behavior is being controlled
+ * @param sync true if the provider should be synced when tickles are received for it
+ */
+ public static void setSyncAutomatically(Account account, String authority, boolean sync) {
try {
- getContentService().cancelSync(uri);
+ getContentService().setSyncAutomatically(account, authority, sync);
} catch (RemoteException e) {
+ // exception ignored; if this is thrown then it means the runtime is in the midst of
+ // being restarted
}
}
+ /**
+ * Gets the master auto-sync setting that applies to all the providers and accounts.
+ * If this is false then the per-provider auto-sync setting is ignored.
+ *
+ * @return the master auto-sync setting that applies to all the providers and accounts
+ */
+ public static boolean getMasterSyncAutomatically() {
+ try {
+ return getContentService().getMasterSyncAutomatically();
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Sets the master auto-sync setting that applies to all the providers and accounts.
+ * If this is false then the per-provider auto-sync setting is ignored.
+ *
+ * @param sync the master auto-sync setting that applies to all the providers and accounts
+ */
+ public static void setMasterSyncAutomatically(boolean sync) {
+ try {
+ getContentService().setMasterSyncAutomatically(sync);
+ } catch (RemoteException e) {
+ // exception ignored; if this is thrown then it means the runtime is in the midst of
+ // being restarted
+ }
+ }
+
+ /**
+ * Returns true if there is currently a sync operation for the given
+ * account or authority in the pending list, or actively being processed.
+ * @param account the account whose setting we are querying
+ * @param authority the provider whose behavior is being queried
+ * @return true if a sync is active for the given account or authority.
+ */
+ public static boolean isSyncActive(Account account, String authority) {
+ try {
+ return getContentService().isSyncActive(account, authority);
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * If a sync is active returns the information about it, otherwise returns false.
+ * @return the ActiveSyncInfo for the currently active sync or null if one is not active.
+ * @hide
+ */
+ public static ActiveSyncInfo getActiveSync() {
+ try {
+ return getContentService().getActiveSync();
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Returns the status that matches the authority. If there are multiples accounts for
+ * the authority, the one with the latest "lastSuccessTime" status is returned.
+ * @param account the account whose setting we are querying
+ * @param authority the provider whose behavior is being queried
+ * @return the SyncStatusInfo for the authority, or null if none exists
+ * @hide
+ */
+ public static SyncStatusInfo getSyncStatus(Account account, String authority) {
+ try {
+ return getContentService().getSyncStatus(account, authority);
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Return true if the pending status is true of any matching authorities.
+ * @param account the account whose setting we are querying
+ * @param authority the provider whose behavior is being queried
+ * @return true if there is a pending sync with the matching account and authority
+ */
+ public static boolean isSyncPending(Account account, String authority) {
+ try {
+ return getContentService().isSyncPending(account, authority);
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
+ try {
+ ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
+ public void onStatusChanged(int which) throws RemoteException {
+ callback.onStatusChanged(which);
+ }
+ };
+ getContentService().addStatusChangeListener(mask, observer);
+ return observer;
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ public static void removeStatusChangeListener(Object handle) {
+ try {
+ getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
+ } catch (RemoteException e) {
+ // exception ignored; if this is thrown then it means the runtime is in the midst of
+ // being restarted
+ }
+ }
+
+
private final class CursorWrapperInner extends CursorWrapper {
private IContentProvider mContentProvider;
public static final String TAG="CursorWrapperInner";
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index c768ffa..7a1ad2b 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -161,7 +161,9 @@ public final class ContentService extends IContentService.Stub {
}
if (syncToNetwork) {
SyncManager syncManager = getSyncManager();
- if (syncManager != null) syncManager.scheduleLocalSync(uri);
+ if (syncManager != null) {
+ syncManager.scheduleLocalSync(null /* all accounts */, uri.getAuthority());
+ }
}
} finally {
restoreCallingIdentity(identityToken);
@@ -187,14 +189,16 @@ public final class ContentService extends IContentService.Stub {
}
}
- public void startSync(Uri url, Bundle extras) {
+ public void requestSync(Account account, String authority, Bundle extras) {
ContentResolver.validateSyncExtrasBundle(extras);
// This makes it so that future permission checks will be in the context of this
// process rather than the caller's process. We will restore this before returning.
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
- if (syncManager != null) syncManager.startSync(url, extras);
+ if (syncManager != null) {
+ syncManager.scheduleSync(account, authority, extras, 0 /* no delay */);
+ }
} finally {
restoreCallingIdentity(identityToken);
}
@@ -202,34 +206,50 @@ public final class ContentService extends IContentService.Stub {
/**
* Clear all scheduled sync operations that match the uri and cancel the active sync
- * if it matches the uri. If the uri is null, clear all scheduled syncs and cancel
- * the active one, if there is one.
- * @param uri Filter on the sync operations to cancel, or all if null.
+ * if they match the authority and account, if they are present.
+ * @param account filter the pending and active syncs to cancel using this account
+ * @param authority filter the pending and active syncs to cancel using this authority
*/
- public void cancelSync(Uri uri) {
+ public void cancelSync(Account account, String authority) {
// This makes it so that future permission checks will be in the context of this
// process rather than the caller's process. We will restore this before returning.
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.clearScheduledSyncOperations(uri);
- syncManager.cancelActiveSync(uri);
+ syncManager.clearScheduledSyncOperations(account, authority);
+ syncManager.cancelActiveSync(account, authority);
}
} finally {
restoreCallingIdentity(identityToken);
}
}
- public boolean getSyncProviderAutomatically(String providerName) {
+ /**
+ * Get information about the SyncAdapters that are known to the system.
+ * @return an array of SyncAdapters that have registered with the system
+ */
+ public SyncAdapterType[] getSyncAdapterTypes() {
+ // This makes it so that future permission checks will be in the context of this
+ // process rather than the caller's process. We will restore this before returning.
+ long identityToken = clearCallingIdentity();
+ try {
+ SyncManager syncManager = getSyncManager();
+ return syncManager.getSyncAdapterTypes();
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ public boolean getSyncAutomatically(Account account, String providerName) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- return syncManager.getSyncStorageEngine().getSyncProviderAutomatically(
- null, providerName);
+ return syncManager.getSyncStorageEngine().getSyncAutomatically(
+ account, providerName);
}
} finally {
restoreCallingIdentity(identityToken);
@@ -237,29 +257,29 @@ public final class ContentService extends IContentService.Stub {
return false;
}
- public void setSyncProviderAutomatically(String providerName, boolean sync) {
+ public void setSyncAutomatically(Account account, String providerName, boolean sync) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.getSyncStorageEngine().setSyncProviderAutomatically(
- null, providerName, sync);
+ syncManager.getSyncStorageEngine().setSyncAutomatically(
+ account, providerName, sync);
}
} finally {
restoreCallingIdentity(identityToken);
}
}
- public boolean getListenForNetworkTickles() {
+ public boolean getMasterSyncAutomatically() {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- return syncManager.getSyncStorageEngine().getListenForNetworkTickles();
+ return syncManager.getSyncStorageEngine().getMasterSyncAutomatically();
}
} finally {
restoreCallingIdentity(identityToken);
@@ -267,14 +287,14 @@ public final class ContentService extends IContentService.Stub {
return false;
}
- public void setListenForNetworkTickles(boolean flag) {
+ public void setMasterSyncAutomatically(boolean flag) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.getSyncStorageEngine().setListenForNetworkTickles(flag);
+ syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag);
}
} finally {
restoreCallingIdentity(identityToken);
@@ -312,7 +332,7 @@ public final class ContentService extends IContentService.Stub {
return null;
}
- public SyncStatusInfo getStatusByAuthority(String authority) {
+ public SyncStatusInfo getSyncStatus(Account account, String authority) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
long identityToken = clearCallingIdentity();
@@ -328,15 +348,14 @@ public final class ContentService extends IContentService.Stub {
return null;
}
- public boolean isAuthorityPending(Account account, String authority) {
+ public boolean isSyncPending(Account account, String authority) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
"no permission to read the sync stats");
long identityToken = clearCallingIdentity();
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- return syncManager.getSyncStorageEngine().isAuthorityPending(
- account, authority);
+ return syncManager.getSyncStorageEngine().isSyncPending(account, authority);
}
} finally {
restoreCallingIdentity(identityToken);
@@ -349,8 +368,7 @@ public final class ContentService extends IContentService.Stub {
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.getSyncStorageEngine().addStatusChangeListener(
- mask, callback);
+ syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
}
} finally {
restoreCallingIdentity(identityToken);
@@ -362,8 +380,7 @@ public final class ContentService extends IContentService.Stub {
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
- syncManager.getSyncStorageEngine().removeStatusChangeListener(
- callback);
+ syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
}
} finally {
restoreCallingIdentity(identityToken);
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 4352227..658a5bc 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -19,6 +19,7 @@ package android.content;
import android.accounts.Account;
import android.content.ActiveSyncInfo;
import android.content.ISyncStatusObserver;
+import android.content.SyncAdapterType;
import android.content.SyncStatusInfo;
import android.net.Uri;
import android.os.Bundle;
@@ -35,15 +36,15 @@ interface IContentService {
void notifyChange(in Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork);
- void startSync(in Uri url, in Bundle extras);
- void cancelSync(in Uri uri);
+ void requestSync(in Account account, String authority, in Bundle extras);
+ void cancelSync(in Account account, String authority);
/**
* Check if the provider should be synced when a network tickle is received
* @param providerName the provider whose setting we are querying
* @return true of the provider should be synced when a network tickle is received
*/
- boolean getSyncProviderAutomatically(String providerName);
+ boolean getSyncAutomatically(in Account account, String providerName);
/**
* Set whether or not the provider is synced when it receives a network tickle.
@@ -51,11 +52,11 @@ interface IContentService {
* @param providerName the provider whose behavior is being controlled
* @param sync true if the provider should be synced when tickles are received for it
*/
- void setSyncProviderAutomatically(String providerName, boolean sync);
+ void setSyncAutomatically(in Account account, String providerName, boolean sync);
- void setListenForNetworkTickles(boolean flag);
+ void setMasterSyncAutomatically(boolean flag);
- boolean getListenForNetworkTickles();
+ boolean getMasterSyncAutomatically();
/**
* Returns true if there is currently a sync operation for the given
@@ -66,17 +67,23 @@ interface IContentService {
ActiveSyncInfo getActiveSync();
/**
+ * Returns the types of the SyncAdapters that are registered with the system.
+ * @return Returns the types of the SyncAdapters that are registered with the system.
+ */
+ SyncAdapterType[] getSyncAdapterTypes();
+
+ /**
* Returns the status that matches the authority. If there are multiples accounts for
* the authority, the one with the latest "lastSuccessTime" status is returned.
* @param authority the authority whose row should be selected
* @return the SyncStatusInfo for the authority, or null if none exists
*/
- SyncStatusInfo getStatusByAuthority(String authority);
+ SyncStatusInfo getSyncStatus(in Account account, String authority);
/**
* Return true if the pending status is true of any matching authorities.
*/
- boolean isAuthorityPending(in Account account, String authority);
+ boolean isSyncPending(in Account account, String authority);
void addStatusChangeListener(int mask, ISyncStatusObserver callback);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 33e769e..87f762d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1593,6 +1593,15 @@ public class Intent implements Parcelable {
public static final String ACTION_REMOTE_INTENT =
"android.intent.action.REMOTE_INTENT";
+ /**
+ * @hide
+ * TODO: This will be unhidden in a later CL.
+ * Broadcast Action: The TextToSpeech synthesizer has completed processing
+ * all of the text in the speech queue.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
+ "android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED";
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
diff --git a/core/java/android/content/SyncAdapterType.aidl b/core/java/android/content/SyncAdapterType.aidl
new file mode 100644
index 0000000..e67841f
--- /dev/null
+++ b/core/java/android/content/SyncAdapterType.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+parcelable SyncAdapterType;
+
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 368a879..5a96003 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -17,12 +17,14 @@
package android.content;
import android.text.TextUtils;
+import android.os.Parcelable;
+import android.os.Parcel;
/**
* Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
* {@link #hashCode}, making it suitable for use as the key of a {@link java.util.Map}
*/
-public class SyncAdapterType {
+public class SyncAdapterType implements Parcelable {
public final String authority;
public final String accountType;
@@ -54,4 +56,27 @@ public class SyncAdapterType {
public String toString() {
return "SyncAdapterType {name=" + authority + ", type=" + accountType + "}";
}
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(authority);
+ dest.writeString(accountType);
+ }
+
+ public SyncAdapterType(Parcel source) {
+ this(source.readString(), source.readString());
+ }
+
+ public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
+ public SyncAdapterType createFromParcel(Parcel source) {
+ return new SyncAdapterType(source);
+ }
+
+ public SyncAdapterType[] newArray(int size) {
+ return new SyncAdapterType[size];
+ }
+ };
} \ No newline at end of file
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index c7954a5..f73b394 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -35,7 +35,6 @@ import android.content.pm.ResolveInfo;
import android.content.pm.RegisteredServicesCache;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -72,7 +71,7 @@ import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Random;
-import java.util.Set;
+import java.util.Collection;
/**
* @hide
@@ -160,7 +159,7 @@ class SyncManager implements OnAccountsUpdatedListener {
Log.v(TAG, "Internal storage is low.");
}
mStorageIsLow = true;
- cancelActiveSync(null /* no url */);
+ cancelActiveSync(null /* any account */, null /* any authority */);
} else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Internal storage is ok.");
@@ -204,7 +203,7 @@ class SyncManager implements OnAccountsUpdatedListener {
if (hadAccountsAlready && accounts.length > 0) {
// request a sync so that if the password was changed we will
// retry any sync that failed when it was wrong
- startSync(null /* all providers */, null /* no extras */);
+ scheduleSync(null, null, null, 0 /* no delay */);
}
}
@@ -327,7 +326,7 @@ class SyncManager implements OnAccountsUpdatedListener {
mHandleAlarmWakeLock.setReferenceCounted(false);
mSyncStorageEngine.addStatusChangeListener(
- SyncStorageEngine.CHANGE_SETTINGS, new ISyncStatusObserver.Stub() {
+ ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
public void onStatusChanged(int which) {
// force the sync loop to run if the settings change
sendCheckAlarmsMessage();
@@ -406,7 +405,8 @@ class SyncManager implements OnAccountsUpdatedListener {
scheduleSyncPollAlarm(nextRelativePollTimeMs);
// perform a poll
- scheduleSync(null /* sync all syncable providers */, new Bundle(), 0 /* no delay */);
+ scheduleSync(null /* sync all syncable accounts */, null /* sync all syncable providers */,
+ new Bundle(), 0 /* no delay */);
}
private void writeSyncPollTime(long when) {
@@ -502,20 +502,21 @@ class SyncManager implements OnAccountsUpdatedListener {
*
* <p>You'll start getting callbacks after this.
*
- * @param url The Uri of a specific provider to be synced, or
- * null to sync all providers.
+ * @param requestedAccount the account to sync, may be null to signify all accounts
+ * @param requestedAuthority the authority to sync, may be null to indicate all authorities
* @param extras a Map of SyncAdapter-specific information to control
* syncs of a specific provider. Can be null. Is ignored
* if the url is null.
* @param delay how many milliseconds in the future to wait before performing this
- * sync. -1 means to make this the next sync to perform.
*/
- public void scheduleSync(Uri url, Bundle extras, long delay) {
+ public void scheduleSync(Account requestedAccount, String requestedAuthority,
+ Bundle extras, long delay) {
boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
if (isLoggable) {
Log.v(TAG, "scheduleSync:"
+ " delay " + delay
- + ", url " + ((url == null) ? "(null)" : url)
+ + ", account " + requestedAccount
+ + ", authority " + requestedAuthority
+ ", extras " + ((extras == null) ? "(null)" : extras));
}
@@ -539,9 +540,8 @@ class SyncManager implements OnAccountsUpdatedListener {
}
Account[] accounts;
- Account accountFromExtras = extras.getParcelable(ContentResolver.SYNC_EXTRAS_ACCOUNT);
- if (accountFromExtras != null) {
- accounts = new Account[]{accountFromExtras};
+ if (requestedAccount != null) {
+ accounts = new Account[]{requestedAccount};
} else {
// if the accounts aren't configured yet then we can't support an account-less
// sync request
@@ -563,14 +563,14 @@ class SyncManager implements OnAccountsUpdatedListener {
}
final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
- final boolean force = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
+ final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
int source;
if (uploadOnly) {
source = SyncStorageEngine.SOURCE_LOCAL;
- } else if (force) {
+ } else if (manualSync) {
source = SyncStorageEngine.SOURCE_USER;
- } else if (url == null) {
+ } else if (requestedAuthority == null) {
source = SyncStorageEngine.SOURCE_POLL;
} else {
// this isn't strictly server, since arbitrary callers can (and do) request
@@ -578,9 +578,9 @@ class SyncManager implements OnAccountsUpdatedListener {
source = SyncStorageEngine.SOURCE_SERVER;
}
- // compile a list of authorities that have sync adapters
- // for each authority sync each account that matches a sync adapter
- Set<String> syncableAuthorities = new HashSet<String>();
+ // Compile a list of authorities that have sync adapters.
+ // For each authority sync each account that matches a sync adapter.
+ final HashSet<String> syncableAuthorities = new HashSet<String>();
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
mSyncAdapters.getAllServices()) {
syncableAuthorities.add(syncAdapter.type.authority);
@@ -588,10 +588,10 @@ class SyncManager implements OnAccountsUpdatedListener {
// if the url was specified then replace the list of authorities with just this authority
// or clear it if this authority isn't syncable
- if (url != null) {
- boolean isSyncable = syncableAuthorities.contains(url.getAuthority());
+ if (requestedAuthority != null) {
+ final boolean isSyncable = syncableAuthorities.contains(requestedAuthority);
syncableAuthorities.clear();
- if (isSyncable) syncableAuthorities.add(url.getAuthority());
+ if (isSyncable) syncableAuthorities.add(requestedAuthority);
}
for (String authority : syncableAuthorities) {
@@ -614,10 +614,10 @@ class SyncManager implements OnAccountsUpdatedListener {
mStatusText = message;
}
- public void scheduleLocalSync(Uri url) {
+ public void scheduleLocalSync(Account account, String authority) {
final Bundle extras = new Bundle();
extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
- scheduleSync(url, extras, LOCAL_SYNC_DELAY);
+ scheduleSync(account, authority, extras, LOCAL_SYNC_DELAY);
}
private IPackageManager getPackageManager() {
@@ -631,18 +631,16 @@ class SyncManager implements OnAccountsUpdatedListener {
return mPackageManager;
}
- /**
- * Initiate a sync for this given URL, or pass null for a full sync.
- *
- * <p>You'll start getting callbacks after this.
- *
- * @param url The Uri of a specific provider to be synced, or
- * null to sync all providers.
- * @param extras a Map of SyncAdapter specific information to control
- * syncs of a specific provider. Can be null. Is ignored
- */
- public void startSync(Uri url, Bundle extras) {
- scheduleSync(url, extras, 0 /* no delay */);
+ public SyncAdapterType[] getSyncAdapterTypes() {
+ final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos =
+ mSyncAdapters.getAllServices();
+ SyncAdapterType[] types = new SyncAdapterType[serviceInfos.size()];
+ int i = 0;
+ for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
+ types[i] = serviceInfo.type;
+ ++i;
+ }
+ return types;
}
public void updateHeartbeatTime() {
@@ -725,17 +723,22 @@ class SyncManager implements OnAccountsUpdatedListener {
}
/**
- * Cancel the active sync if it matches the uri. The uri corresponds to the one passed
- * in to startSync().
- * @param uri If non-null, the active sync is only canceled if it matches the uri.
- * If null, any active sync is canceled.
+ * Cancel the active sync if it matches the authority and account.
+ * @param account limit the cancelations to syncs with this account, if non-null
+ * @param authority limit the cancelations to syncs with this authority, if non-null
*/
- public void cancelActiveSync(Uri uri) {
+ public void cancelActiveSync(Account account, String authority) {
ActiveSyncContext activeSyncContext = mActiveSyncContext;
if (activeSyncContext != null) {
- // if a Uri was specified then only cancel the sync if it matches the the uri
- if (uri != null) {
- if (!uri.getAuthority().equals(activeSyncContext.mSyncOperation.authority)) {
+ // if an authority was specified then only cancel the sync if it matches
+ if (account != null) {
+ if (!account.equals(activeSyncContext.mSyncOperation.account)) {
+ return;
+ }
+ }
+ // if an account was specified then only cancel the sync if it matches
+ if (authority != null) {
+ if (!authority.equals(activeSyncContext.mSyncOperation.authority)) {
return;
}
}
@@ -787,14 +790,13 @@ class SyncManager implements OnAccountsUpdatedListener {
}
/**
- * Remove any scheduled sync operations that match uri. The uri corresponds to the one passed
- * in to startSync().
- * @param uri If non-null, only operations that match the uri are cleared.
- * If null, all operations are cleared.
+ * Remove scheduled sync operations.
+ * @param account limit the removals to operations with this account, if non-null
+ * @param authority limit the removals to operations with this authority, if non-null
*/
- public void clearScheduledSyncOperations(Uri uri) {
+ public void clearScheduledSyncOperations(Account account, String authority) {
synchronized (mSyncQueue) {
- mSyncQueue.clear(null, uri != null ? uri.getAuthority() : null);
+ mSyncQueue.clear(account, authority);
}
}
@@ -1558,14 +1560,14 @@ class SyncManager implements OnAccountsUpdatedListener {
// Otherwise consume SyncOperations from the head of the SyncQueue until one is
// found that is runnable (not disabled, etc). If that one is ready to run then
// start it, otherwise just get out.
- SyncOperation syncOperation;
+ SyncOperation op;
final ConnectivityManager connManager = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- final boolean backgroundDataSetting = connManager.getBackgroundDataSetting();
+ final boolean backgroundDataUsageAllowed = connManager.getBackgroundDataSetting();
synchronized (mSyncQueue) {
while (true) {
- syncOperation = mSyncQueue.head();
- if (syncOperation == null) {
+ op = mSyncQueue.head();
+ if (op == null) {
if (isLoggable) {
Log.v(TAG, "runStateIdle: no more sync operations, returning");
}
@@ -1575,39 +1577,40 @@ class SyncManager implements OnAccountsUpdatedListener {
// Sync is disabled, drop this operation.
if (!isSyncEnabled()) {
if (isLoggable) {
- Log.v(TAG, "runStateIdle: sync disabled, dropping " + syncOperation);
+ Log.v(TAG, "runStateIdle: sync disabled, dropping " + op);
}
mSyncQueue.popHead();
continue;
}
- // skip the sync if it isn't a force and the settings are off for this provider
- final boolean force = syncOperation.extras.getBoolean(
- ContentResolver.SYNC_EXTRAS_FORCE, false);
- if (!force && (!backgroundDataSetting
- || !mSyncStorageEngine.getListenForNetworkTickles()
- || !mSyncStorageEngine.getSyncProviderAutomatically(
- null, syncOperation.authority))) {
+ // skip the sync if it isn't manual and auto sync is disabled
+ final boolean manualSync = op.extras.getBoolean(
+ ContentResolver.SYNC_EXTRAS_MANUAL, false);
+ final boolean syncAutomatically =
+ mSyncStorageEngine.getSyncAutomatically(op.account, op.authority)
+ || mSyncStorageEngine.getMasterSyncAutomatically();
+ boolean syncAllowed =
+ manualSync || (backgroundDataUsageAllowed && syncAutomatically);
+ if (!syncAllowed) {
if (isLoggable) {
- Log.v(TAG, "runStateIdle: sync off, dropping " + syncOperation);
+ Log.v(TAG, "runStateIdle: sync off, dropping " + op);
}
mSyncQueue.popHead();
continue;
}
// skip the sync if the account of this operation no longer exists
- if (!ArrayUtils.contains(accounts, syncOperation.account)) {
+ if (!ArrayUtils.contains(accounts, op.account)) {
mSyncQueue.popHead();
if (isLoggable) {
- Log.v(TAG, "runStateIdle: account not present, dropping "
- + syncOperation);
+ Log.v(TAG, "runStateIdle: account not present, dropping " + op);
}
continue;
}
// go ahead and try to sync this syncOperation
if (isLoggable) {
- Log.v(TAG, "runStateIdle: found sync candidate: " + syncOperation);
+ Log.v(TAG, "runStateIdle: found sync candidate: " + op);
}
break;
}
@@ -1615,11 +1618,10 @@ class SyncManager implements OnAccountsUpdatedListener {
// If the first SyncOperation isn't ready to run schedule a wakeup and
// get out.
final long now = SystemClock.elapsedRealtime();
- if (syncOperation.earliestRunTime > now) {
+ if (op.earliestRunTime > now) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "runStateIdle: the time is " + now + " yet the next "
- + "sync operation is for " + syncOperation.earliestRunTime
- + ": " + syncOperation);
+ + "sync operation is for " + op.earliestRunTime + ": " + op);
}
return;
}
@@ -1627,14 +1629,14 @@ class SyncManager implements OnAccountsUpdatedListener {
// We will do this sync. Remove it from the queue and run it outside of the
// synchronized block.
if (isLoggable) {
- Log.v(TAG, "runStateIdle: we are going to sync " + syncOperation);
+ Log.v(TAG, "runStateIdle: we are going to sync " + op);
}
mSyncQueue.popHead();
}
// connect to the sync adapter
- SyncAdapterType syncAdapterType = new SyncAdapterType(syncOperation.authority,
- syncOperation.account.mType);
+ SyncAdapterType syncAdapterType = new SyncAdapterType(op.authority,
+ op.account.mType);
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
mSyncAdapters.getServiceInfo(syncAdapterType);
if (syncAdapterInfo == null) {
@@ -1646,7 +1648,7 @@ class SyncManager implements OnAccountsUpdatedListener {
}
ActiveSyncContext activeSyncContext =
- new ActiveSyncContext(syncOperation, insertStartSyncEvent(syncOperation));
+ new ActiveSyncContext(op, insertStartSyncEvent(op));
mActiveSyncContext = activeSyncContext;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "runStateIdle: setting mActiveSyncContext to " + mActiveSyncContext);
@@ -1776,21 +1778,21 @@ class SyncManager implements OnAccountsUpdatedListener {
*/
private int syncResultToErrorNumber(SyncResult syncResult) {
if (syncResult.syncAlreadyInProgress)
- return SyncStorageEngine.ERROR_SYNC_ALREADY_IN_PROGRESS;
+ return ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
if (syncResult.stats.numAuthExceptions > 0)
- return SyncStorageEngine.ERROR_AUTHENTICATION;
+ return ContentResolver.SYNC_ERROR_AUTHENTICATION;
if (syncResult.stats.numIoExceptions > 0)
- return SyncStorageEngine.ERROR_IO;
+ return ContentResolver.SYNC_ERROR_IO;
if (syncResult.stats.numParseExceptions > 0)
- return SyncStorageEngine.ERROR_PARSE;
+ return ContentResolver.SYNC_ERROR_PARSE;
if (syncResult.stats.numConflictDetectedExceptions > 0)
- return SyncStorageEngine.ERROR_CONFLICT;
+ return ContentResolver.SYNC_ERROR_CONFLICT;
if (syncResult.tooManyDeletions)
- return SyncStorageEngine.ERROR_TOO_MANY_DELETIONS;
+ return ContentResolver.SYNC_ERROR_TOO_MANY_DELETIONS;
if (syncResult.tooManyRetries)
- return SyncStorageEngine.ERROR_TOO_MANY_RETRIES;
+ return ContentResolver.SYNC_ERROR_TOO_MANY_RETRIES;
if (syncResult.databaseError)
- return SyncStorageEngine.ERROR_INTERNAL;
+ return ContentResolver.SYNC_ERROR_INTERNAL;
throw new IllegalStateException("we are not in an error state, " + syncResult);
}
@@ -1831,9 +1833,10 @@ class SyncManager implements OnAccountsUpdatedListener {
} else {
final boolean timeToShowNotification =
now > mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY;
- final boolean syncIsForced = syncOperation.extras
- .getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
- shouldInstall = timeToShowNotification || syncIsForced;
+ // show the notification immediately if this is a manual sync
+ final boolean manualSync = syncOperation.extras
+ .getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+ shouldInstall = timeToShowNotification || manualSync;
}
}
@@ -2088,9 +2091,9 @@ class SyncManager implements OnAccountsUpdatedListener {
SyncOperation existingOperation = mOpsByKey.get(operationKey);
// if this operation matches an existing operation that is being retried (delay > 0)
- // and this operation isn't forced, ignore this operation
+ // and this isn't a manual sync operation, ignore this operation
if (existingOperation != null && existingOperation.delay > 0) {
- if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)) {
+ if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) {
return false;
}
}
diff --git a/core/java/android/content/SyncStatusObserver.java b/core/java/android/content/SyncStatusObserver.java
new file mode 100644
index 0000000..663378a
--- /dev/null
+++ b/core/java/android/content/SyncStatusObserver.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+public interface SyncStatusObserver {
+ void onStatusChanged(int which);
+}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index aaa763d..aaba7c7 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -49,8 +49,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.TimeZone;
-import com.google.android.collect.Sets;
-
/**
* Singleton that tracks the sync data and overall sync
* history on the device.
@@ -89,6 +87,9 @@ public class SyncStorageEngine extends Handler {
/** Enum value for a user-initiated sync. */
public static final int SOURCE_USER = 3;
+ private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
+ new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
+
// TODO: i18n -- grab these out of resources.
/** String names for the sync source types. */
public static final String[] SOURCES = { "SERVER",
@@ -96,26 +97,10 @@ public class SyncStorageEngine extends Handler {
"POLL",
"USER" };
- // Error types
- public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
- public static final int ERROR_AUTHENTICATION = 2;
- public static final int ERROR_IO = 3;
- public static final int ERROR_PARSE = 4;
- public static final int ERROR_CONFLICT = 5;
- public static final int ERROR_TOO_MANY_DELETIONS = 6;
- public static final int ERROR_TOO_MANY_RETRIES = 7;
- public static final int ERROR_INTERNAL = 8;
-
// The MESG column will contain one of these or one of the Error types.
public static final String MESG_SUCCESS = "success";
public static final String MESG_CANCELED = "canceled";
- public static final int CHANGE_SETTINGS = 1<<0;
- public static final int CHANGE_PENDING = 1<<1;
- public static final int CHANGE_ACTIVE = 1<<2;
- public static final int CHANGE_STATUS = 1<<3;
- public static final int CHANGE_ALL = 0x7fffffff;
-
public static final int MAX_HISTORY = 15;
private static final int MSG_WRITE_STATUS = 1;
@@ -166,7 +151,7 @@ public class SyncStorageEngine extends Handler {
final String authority;
final int ident;
boolean enabled;
-
+
AuthorityInfo(Account account, String authority, int ident) {
this.account = account;
this.authority = authority;
@@ -259,7 +244,7 @@ public class SyncStorageEngine extends Handler {
private int mNumPendingFinished = 0;
private int mNextHistoryId = 0;
- private boolean mListenForTickles = true;
+ private boolean mMasterSyncAutomatically = true;
private SyncStorageEngine(Context context) {
mContext = context;
@@ -356,14 +341,14 @@ public class SyncStorageEngine extends Handler {
}
}
- public boolean getSyncProviderAutomatically(Account account, String providerName) {
+ public boolean getSyncAutomatically(Account account, String providerName) {
synchronized (mAuthorities) {
if (account != null) {
AuthorityInfo authority = getAuthorityLocked(account, providerName,
- "getSyncProviderAutomatically");
- return authority != null ? authority.enabled : false;
+ "getSyncAutomatically");
+ return authority != null && authority.enabled;
}
-
+
int i = mAuthorities.size();
while (i > 0) {
i--;
@@ -377,42 +362,31 @@ public class SyncStorageEngine extends Handler {
}
}
- public void setSyncProviderAutomatically(Account account, String providerName,
- boolean sync) {
+ public void setSyncAutomatically(Account account, String providerName, boolean sync) {
synchronized (mAuthorities) {
- if (account != null) {
- AuthorityInfo authority = getAuthorityLocked(account, providerName,
- "setSyncProviderAutomatically");
- if (authority != null) {
- authority.enabled = sync;
- }
- } else {
- int i = mAuthorities.size();
- while (i > 0) {
- i--;
- AuthorityInfo authority = mAuthorities.get(i);
- if (authority.authority.equals(providerName)) {
- authority.enabled = sync;
- }
- }
+ AuthorityInfo authority = getAuthorityLocked(account, providerName,
+ "setSyncAutomatically");
+ if (authority != null) {
+ authority.enabled = sync;
}
writeAccountInfoLocked();
}
- reportChange(CHANGE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
}
- public void setListenForNetworkTickles(boolean flag) {
+ public void setMasterSyncAutomatically(boolean flag) {
synchronized (mAuthorities) {
- mListenForTickles = flag;
+ mMasterSyncAutomatically = flag;
writeAccountInfoLocked();
}
- reportChange(CHANGE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
}
- public boolean getListenForNetworkTickles() {
+ public boolean getMasterSyncAutomatically() {
synchronized (mAuthorities) {
- return mListenForTickles;
+ return mMasterSyncAutomatically;
}
}
@@ -481,7 +455,7 @@ public class SyncStorageEngine extends Handler {
status.pending = true;
}
- reportChange(CHANGE_PENDING);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
return op;
}
@@ -527,7 +501,7 @@ public class SyncStorageEngine extends Handler {
}
}
- reportChange(CHANGE_PENDING);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
return res;
}
@@ -543,7 +517,7 @@ public class SyncStorageEngine extends Handler {
}
writePendingOperationsLocked();
}
- reportChange(CHANGE_PENDING);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
return num;
}
@@ -650,14 +624,14 @@ public class SyncStorageEngine extends Handler {
}
}
- reportChange(CHANGE_ACTIVE);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
}
/**
* To allow others to send active change reports, to poke clients.
*/
public void reportActiveChange() {
- reportChange(CHANGE_ACTIVE);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
}
/**
@@ -689,7 +663,7 @@ public class SyncStorageEngine extends Handler {
if (DEBUG) Log.v(TAG, "returning historyId " + id);
}
- reportChange(CHANGE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
return id;
}
@@ -793,7 +767,7 @@ public class SyncStorageEngine extends Handler {
}
}
- reportChange(CHANGE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
}
/**
@@ -851,7 +825,7 @@ public class SyncStorageEngine extends Handler {
/**
* Return true if the pending status is true of any matching authorities.
*/
- public boolean isAuthorityPending(Account account, String authority) {
+ public boolean isSyncPending(Account account, String authority) {
synchronized (mAuthorities) {
final int N = mSyncStatus.size();
for (int i=0; i<N; i++) {
@@ -907,7 +881,7 @@ public class SyncStorageEngine extends Handler {
*/
public long getInitialSyncFailureTime() {
synchronized (mAuthorities) {
- if (!mListenForTickles) {
+ if (!mMasterSyncAutomatically) {
return 0;
}
@@ -1041,7 +1015,7 @@ public class SyncStorageEngine extends Handler {
if ("accounts".equals(tagName)) {
String listen = parser.getAttributeValue(
null, "listen-for-tickles");
- mListenForTickles = listen == null
+ mMasterSyncAutomatically = listen == null
|| Boolean.parseBoolean(listen);
eventType = parser.next();
do {
@@ -1122,7 +1096,7 @@ public class SyncStorageEngine extends Handler {
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
out.startTag(null, "accounts");
- if (!mListenForTickles) {
+ if (!mMasterSyncAutomatically) {
out.attribute(null, "listen-for-tickles", "false");
}
@@ -1262,13 +1236,18 @@ public class SyncStorageEngine extends Handler {
String value = c.getString(c.getColumnIndex("value"));
if (name == null) continue;
if (name.equals("listen_for_tickles")) {
- setListenForNetworkTickles(value == null
- || Boolean.parseBoolean(value));
+ setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
} else if (name.startsWith("sync_provider_")) {
String provider = name.substring("sync_provider_".length(),
name.length());
- setSyncProviderAutomatically(null, provider,
- value == null || Boolean.parseBoolean(value));
+ int i = mAuthorities.size();
+ while (i > 0) {
+ i--;
+ AuthorityInfo authority = mAuthorities.get(i);
+ if (authority.authority.equals(provider)) {
+ authority.enabled = value == null || Boolean.parseBoolean(value);
+ }
+ }
}
}
diff --git a/core/java/android/content/TempProviderSyncAdapter.java b/core/java/android/content/TempProviderSyncAdapter.java
index 0cbe01e..fb05fe7 100644
--- a/core/java/android/content/TempProviderSyncAdapter.java
+++ b/core/java/android/content/TempProviderSyncAdapter.java
@@ -63,12 +63,10 @@ public abstract class TempProviderSyncAdapter extends SyncAdapter {
*
* @param context allows you to publish status and interact with the
* @param account the account to sync
- * @param forced if true then the sync was forced
+ * @param manualSync true if this sync was requested manually by the user
* @param result information to track what happened during this sync attempt
- * @return true, if the sync was successfully started. One reason it can
- * fail to start is if there is no user configured on the device.
*/
- public abstract void onSyncStarting(SyncContext context, Account account, boolean forced,
+ public abstract void onSyncStarting(SyncContext context, Account account, boolean manualSync,
SyncResult result);
/**
@@ -229,12 +227,12 @@ public abstract class TempProviderSyncAdapter extends SyncAdapter {
mAdapterSyncStarted = false;
String message = null;
- boolean syncForced = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
+ boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
try {
mProvider.onSyncStart(syncContext, account);
mProviderSyncStarted = true;
- onSyncStarting(syncContext, account, syncForced, mResult);
+ onSyncStarting(syncContext, account, manualSync, mResult);
if (mResult.hasError()) {
message = "SyncAdapter failed while trying to start sync";
return;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 680fef8..179b9bd 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -17,8 +17,15 @@
package android.content.res;
import android.content.pm.ApplicationInfo;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
/**
* CompatibilityInfo class keeps the information about compatibility mode that the application is
@@ -27,6 +34,9 @@ import android.view.Gravity;
* {@hide}
*/
public class CompatibilityInfo {
+ private static final boolean DBG = false;
+ private static final String TAG = "CompatibilityInfo";
+
/** default compatibility info object for compatible applications */
public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo();
@@ -41,36 +51,75 @@ public class CompatibilityInfo {
public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
/**
- * Application's scale.
+ * The x-shift mode that controls the position of the content or the window under
+ * compatibility mode.
+ * {@see getTranslator}
+ * {@see Translator#mShiftMode}
*/
- public final float mApplicationScale;
+ private static final int X_SHIFT_NONE = 0;
+ private static final int X_SHIFT_CONTENT = 1;
+ private static final int X_SHIFT_AND_CLIP_CONTENT = 2;
+ private static final int X_SHIFT_WINDOW = 3;
+
/**
- * Application's inverted scale.
+ * A compatibility flags
*/
- public final float mApplicationInvertedScale;
+ private int compatibilityFlags;
/**
- * A boolean flag to indicates that the application can expand over the original size.
+ * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
+ * {@see compatibilityFlag}
+ */
+ private static final int SCALING_REQUIRED = 1;
+
+ /**
+ * A flag mask to indicates that the application can expand over the original size.
* The flag is set to true if
* 1) Application declares its expandable in manifest file using <expandable /> or
* 2) The screen size is same as (320 x 480) * density.
+ * {@see compatibilityFlag}
+ */
+ private static final int EXPANDABLE = 2;
+
+ /**
+ * A flag mask to tell if the application is configured to be expandable. This differs
+ * from EXPANDABLE in that the application that is not expandable will be
+ * marked as expandable if it runs in (320x 480) * density screen size.
+ */
+ private static final int CONFIGURED_EXPANDABLE = 4;
+
+ private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE;
+
+ /**
+ * Application's scale.
*/
- public boolean mExpandable;
+ public final float applicationScale;
/**
- * A expandable flag in the configuration.
+ * Application's inverted scale.
*/
- public final boolean mConfiguredExpandable;
+ public final float applicationInvertedScale;
+
+
+ /**
+ * Window size in Compatibility Mode, in real pixels. This is updated by
+ * {@link DisplayMetrics#updateMetrics}.
+ */
+ private int mWidth;
+ private int mHeight;
/**
- * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+ * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added
+ * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset
+ * is used to translate the Canvas.
*/
- public final boolean mScalingRequired;
+ private int mXOffset;
public CompatibilityInfo(ApplicationInfo appInfo) {
- mExpandable = mConfiguredExpandable =
- (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0;
+ if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+ compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+ }
float packageDensityScale = -1.0f;
if (appInfo.supportsDensities != null) {
@@ -93,23 +142,323 @@ public class CompatibilityInfo {
}
}
if (packageDensityScale > 0.0f) {
- mApplicationScale = packageDensityScale;
+ applicationScale = packageDensityScale;
} else {
- mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+ applicationScale =
+ DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+ }
+ applicationInvertedScale = 1.0f / applicationScale;
+ if (applicationScale != 1.0f) {
+ compatibilityFlags |= SCALING_REQUIRED;
}
- mApplicationInvertedScale = 1.0f / mApplicationScale;
- mScalingRequired = mApplicationScale != 1.0f;
}
private CompatibilityInfo() {
- mApplicationScale = mApplicationInvertedScale = 1.0f;
- mExpandable = mConfiguredExpandable = true;
- mScalingRequired = false;
+ applicationScale = applicationInvertedScale = 1.0f;
+ compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
}
+ /**
+ * Sets the application's visible rect in compatibility mode.
+ * @param xOffset the application's x offset that is added to center the content.
+ * @param widthPixels the application's width in real pixels on the screen.
+ * @param heightPixels the application's height in real pixels on the screen.
+ */
+ public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) {
+ this.mXOffset = xOffset;
+ mWidth = widthPixels;
+ mHeight = heightPixels;
+ }
+
+ /**
+ * Sets expandable bit in the compatibility flag.
+ */
+ public void setExpandable(boolean expandable) {
+ if (expandable) {
+ compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+ } else {
+ compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+ }
+ }
+
+ /**
+ * @return true if the application is configured to be expandable.
+ */
+ public boolean isConfiguredExpandable() {
+ return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+ }
+
+ /**
+ * @return true if the scaling is required
+ */
+ public boolean isScalingRequired() {
+ return (compatibilityFlags & SCALING_REQUIRED) != 0;
+ }
+
@Override
public String toString() {
- return "CompatibilityInfo{scale=" + mApplicationScale +
- ", expandable=" + mExpandable + "}";
+ return "CompatibilityInfo{scale=" + applicationScale +
+ ", compatibility flag=" + compatibilityFlags + "}";
+ }
+
+ /**
+ * Returns the translator which can translate the coordinates of the window.
+ * There are five different types of Translator.
+ *
+ * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT}
+ * Shift and clip the content of the window at drawing time. Used for activities'
+ * main window (with no gravity).
+ * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT}
+ * Shift the content of the window at drawing time. Used for windows that is created by
+ * an application and expected to be aligned with the application window.
+ * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW}
+ * Create the window with adjusted x- coordinates. This is typically used
+ * in popup window, where it has to be placed relative to main window.
+ * 4) {@link CompatibilityInfo#X_SHIFT_NONE}
+ * No adjustment required, such as dialog.
+ * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which
+ * does not require scaling, but its window's location has to be adjusted.
+ *
+ * @param params the window's parameter
+ */
+ public Translator getTranslator(WindowManager.LayoutParams params) {
+ if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+ == CompatibilityInfo.EXPANDABLE) {
+ if (DBG) Log.d(TAG, "no translation required");
+ return null;
+ }
+
+ if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
+ if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
+ if (DBG) Log.d(TAG, "translation for surface view selected");
+ return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
+ } else {
+ int shiftMode;
+ if (params.gravity == Gravity.NO_GRAVITY) {
+ // For Regular Application window
+ shiftMode = X_SHIFT_AND_CLIP_CONTENT;
+ if (DBG) Log.d(TAG, "shift and clip translator");
+ } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) {
+ // For Regular Application window
+ shiftMode = X_SHIFT_CONTENT;
+ if (DBG) Log.d(TAG, "shift content translator");
+ } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) {
+ shiftMode = X_SHIFT_WINDOW;
+ if (DBG) Log.d(TAG, "shift window translator");
+ } else {
+ shiftMode = X_SHIFT_NONE;
+ if (DBG) Log.d(TAG, "no content/window translator");
+ }
+ return new Translator(shiftMode);
+ }
+ } else if (isScalingRequired()) {
+ return new Translator();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * A helper object to translate the screen and window coordinates back and forth.
+ * @hide
+ */
+ public class Translator {
+ final private int mShiftMode;
+ final public boolean scalingRequired;
+ final public float applicationScale;
+ final public float applicationInvertedScale;
+
+ private Rect mContentInsetsBuffer = null;
+ private Rect mVisibleInsets = null;
+
+ Translator(int shiftMode, boolean scalingRequired, float applicationScale,
+ float applicationInvertedScale) {
+ mShiftMode = shiftMode;
+ this.scalingRequired = scalingRequired;
+ this.applicationScale = applicationScale;
+ this.applicationInvertedScale = applicationInvertedScale;
+ }
+
+ Translator(int shiftMode) {
+ this(shiftMode,
+ isScalingRequired(),
+ CompatibilityInfo.this.applicationScale,
+ CompatibilityInfo.this.applicationInvertedScale);
+ }
+
+ Translator() {
+ this(X_SHIFT_NONE);
+ }
+
+ /**
+ * Translate the screen rect to the application frame.
+ */
+ public void translateRectInScreenToAppWinFrame(Rect rect) {
+ if (rect.isEmpty()) return; // skip if the window size is empty.
+ switch (mShiftMode) {
+ case X_SHIFT_AND_CLIP_CONTENT:
+ rect.intersect(0, 0, mWidth, mHeight);
+ break;
+ case X_SHIFT_CONTENT:
+ rect.intersect(0, 0, mWidth + mXOffset, mHeight);
+ break;
+ case X_SHIFT_WINDOW:
+ case X_SHIFT_NONE:
+ break;
+ }
+ if (scalingRequired) {
+ rect.scale(applicationInvertedScale);
+ }
+ }
+
+ /**
+ * Translate the region in window to screen.
+ */
+ public void translateRegionInWindowToScreen(Region transparentRegion) {
+ switch (mShiftMode) {
+ case X_SHIFT_AND_CLIP_CONTENT:
+ case X_SHIFT_CONTENT:
+ transparentRegion.scale(applicationScale);
+ transparentRegion.translate(mXOffset, 0);
+ break;
+ case X_SHIFT_WINDOW:
+ case X_SHIFT_NONE:
+ transparentRegion.scale(applicationScale);
+ }
+ }
+
+ /**
+ * Apply translation to the canvas that is necessary to draw the content.
+ */
+ public void translateCanvas(Canvas canvas) {
+ if (mShiftMode == X_SHIFT_CONTENT ||
+ mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+ // TODO: clear outside when rotation is changed.
+
+ // Translate x-offset only when the content is shifted.
+ canvas.translate(mXOffset, 0);
+ }
+ if (scalingRequired) {
+ canvas.scale(applicationScale, applicationScale);
+ }
+ }
+
+ /**
+ * Translate the motion event captured on screen to the application's window.
+ */
+ public void translateEventInScreenToAppWindow(MotionEvent event) {
+ if (mShiftMode == X_SHIFT_CONTENT ||
+ mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+ event.translate(-mXOffset, 0);
+ }
+ if (scalingRequired) {
+ event.scale(applicationInvertedScale);
+ }
+ }
+
+ /**
+ * Translate the window's layout parameter, from application's view to
+ * Screen's view.
+ */
+ public void translateWindowLayout(WindowManager.LayoutParams params) {
+ switch (mShiftMode) {
+ case X_SHIFT_NONE:
+ case X_SHIFT_AND_CLIP_CONTENT:
+ case X_SHIFT_CONTENT:
+ params.scale(applicationScale);
+ break;
+ case X_SHIFT_WINDOW:
+ params.scale(applicationScale);
+ params.x += mXOffset;
+ break;
+ }
+ }
+
+ /**
+ * Translate a Rect in application's window to screen.
+ */
+ public void translateRectInAppWindowToScreen(Rect rect) {
+ // TODO Auto-generated method stub
+ if (scalingRequired) {
+ rect.scale(applicationScale);
+ }
+ switch(mShiftMode) {
+ case X_SHIFT_NONE:
+ case X_SHIFT_WINDOW:
+ break;
+ case X_SHIFT_CONTENT:
+ case X_SHIFT_AND_CLIP_CONTENT:
+ rect.offset(mXOffset, 0);
+ break;
+ }
+ }
+
+ /**
+ * Translate a Rect in screen coordinates into the app window's coordinates.
+ */
+ public void translateRectInScreenToAppWindow(Rect rect) {
+ switch (mShiftMode) {
+ case X_SHIFT_NONE:
+ case X_SHIFT_WINDOW:
+ break;
+ case X_SHIFT_CONTENT: {
+ rect.intersects(mXOffset, 0, rect.right, rect.bottom);
+ int dx = Math.min(mXOffset, rect.left);
+ rect.offset(-dx, 0);
+ break;
+ }
+ case X_SHIFT_AND_CLIP_CONTENT: {
+ rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight);
+ int dx = Math.min(mXOffset, rect.left);
+ rect.offset(-dx, 0);
+ break;
+ }
+ }
+ if (scalingRequired) {
+ rect.scale(applicationInvertedScale);
+ }
+ }
+
+ /**
+ * Translate the location of the sub window.
+ * @param params
+ */
+ public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
+ if (scalingRequired) {
+ params.scale(applicationScale);
+ }
+ switch (mShiftMode) {
+ // the window location on these mode does not require adjustmenet.
+ case X_SHIFT_NONE:
+ case X_SHIFT_WINDOW:
+ break;
+ case X_SHIFT_CONTENT:
+ case X_SHIFT_AND_CLIP_CONTENT:
+ params.x += mXOffset;
+ break;
+ }
+ }
+
+ /**
+ * Translate the content insets in application window to Screen. This uses
+ * the internal buffer for content insets to avoid extra object allocation.
+ */
+ public Rect getTranslatedContentInsets(Rect contentInsets) {
+ if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
+ mContentInsetsBuffer.set(contentInsets);
+ translateRectInAppWindowToScreen(mContentInsetsBuffer);
+ return mContentInsetsBuffer;
+ }
+
+ /**
+ * Translate the visible insets in application window to Screen. This uses
+ * the internal buffer for content insets to avoid extra object allocation.
+ */
+ public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
+ if (mVisibleInsets == null) mVisibleInsets = new Rect();
+ mVisibleInsets.set(visibleInsets);
+ translateRectInAppWindowToScreen(mVisibleInsets);
+ return mVisibleInsets;
+ }
}
-}
+} \ No newline at end of file
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 71dbd38..cb9d46e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -158,10 +158,10 @@ public class Resources {
}
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
- if (!mCompatibilityInfo.mScalingRequired) {
- mPreloadedDrawables = sPreloadedDrawables;
- } else {
+ if (mCompatibilityInfo.isScalingRequired()) {
mPreloadedDrawables = emptySparseArray();
+ } else {
+ mPreloadedDrawables = sPreloadedDrawables;
}
}
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index c26810a..cf30dd9 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -247,9 +247,11 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
try {
return mBulkCursor.respond(extras);
} catch (RemoteException e) {
- // This should never happen because the system kills processes that are using remote
- // cursors when the provider process is killed.
- throw new RuntimeException(e);
+ // the system kills processes that are using remote cursors when the provider process
+ // is killed, but this can still happen if this is being called from the system process,
+ // so, better to log and return an empty bundle.
+ Log.w(TAG, "respond() threw RemoteException, returning an empty bundle.", e);
+ return Bundle.EMPTY;
}
}
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index d9612af..b0fc78e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -21,6 +21,7 @@ import com.android.internal.util.TypedProperties;
import android.util.Config;
import android.util.Log;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
@@ -378,6 +379,20 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
}
/**
+ * Like startMethodTracing(String, int, int), but taking an already-opened
+ * FileDescriptor in which the trace is written. The file name is also
+ * supplied simply for logging. Makes a dup of the file descriptor.
+ *
+ * Not exposed in the SDK unless we are really comfortable with supporting
+ * this and find it would be useful.
+ * @hide
+ */
+ public static void startMethodTracing(String traceName, FileDescriptor fd,
+ int bufferSize, int flags) {
+ VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
+ }
+
+ /**
* Determine whether method tracing is currently active.
* @hide
*/
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 94254de..2490b8a 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -172,6 +172,7 @@ public class Browser {
/**
* Return a cursor pointing to a list of all the bookmarks.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
*/
public static final Cursor getAllBookmarks(ContentResolver cr) throws
@@ -183,6 +184,7 @@ public class Browser {
/**
* Return a cursor pointing to a list of all visited site urls.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
*/
public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
@@ -194,6 +196,8 @@ public class Browser {
/**
* Update the visited history to acknowledge that a site has been
* visited.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param url The site being visited.
* @param real Whether this is an actual visit, and should be added to the
@@ -243,6 +247,8 @@ public class Browser {
* of them. This is used to keep our history table to a
* reasonable size. Note: it does not prune bookmarks. If the
* user wants 1000 bookmarks, the user gets 1000 bookmarks.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
*
* @param cr The ContentResolver used to access the database.
*/
@@ -276,6 +282,7 @@ public class Browser {
/**
* Returns whether there is any history to clear.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @return boolean True if the history can be cleared.
*/
@@ -301,6 +308,7 @@ public class Browser {
/**
* Delete all entries from the bookmarks/history table which are
* not bookmarks. Also set all visited bookmarks to unvisited.
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
*/
public static final void clearHistory(ContentResolver cr) {
@@ -310,6 +318,8 @@ public class Browser {
/**
* Helper function to delete all history items and revert all
* bookmarks to zero visits which meet the criteria provided.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param whereClause String to limit the items affected.
* null means all items.
@@ -372,6 +382,7 @@ public class Browser {
/**
* Delete all history items from begin to end.
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param begin First date to remove. If -1, all dates before end.
* Inclusive.
@@ -399,6 +410,7 @@ public class Browser {
/**
* Remove a specific url from the history database.
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param url url to remove.
*/
@@ -412,6 +424,8 @@ public class Browser {
/**
* Add a search string to the searches database.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param search The string to add to the searches database.
*/
@@ -441,6 +455,7 @@ public class Browser {
}
/**
* Remove all searches from the search database.
+ * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
*/
public static final void clearSearches(ContentResolver cr) {
@@ -455,6 +470,7 @@ public class Browser {
/**
* Request all icons from the database.
+ * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
* @param cr The ContentResolver used to access the database.
* @param where Clause to be used to limit the query from the database.
* Must be an allowable string to be passed into a database query.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5aa2174..ebe54fc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2545,6 +2545,16 @@ public final class Settings {
public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op";
/**
+ * the transcoder URL for mobile devices.
+ */
+ public static final String TRANSCODER_URL = "mobile_transcoder_url";
+
+ /**
+ * URL that points to the privacy terms of the Google Talk service.
+ */
+ public static final String GTALK_TERMS_OF_SERVICE_URL = "gtalk_terms_of_service_url";
+
+ /**
* Hostname of the GTalk server.
*/
public static final String GTALK_SERVICE_HOSTNAME = "gtalk_hostname";
diff --git a/core/java/android/provider/Sync.java b/core/java/android/provider/Sync.java
deleted file mode 100644
index c9bde0e..0000000
--- a/core/java/android/provider/Sync.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-import android.accounts.Account;
-import android.text.TextUtils;
-
-import java.util.Map;
-
-/**
- * The Sync provider stores information used in managing the syncing of the device,
- * including the history and pending syncs.
- *
- * @hide
- */
-public final class Sync {
- // utility class
- private Sync() {}
-
- /**
- * The content url for this provider.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync");
-
- /**
- * Columns from the stats table.
- */
- public interface StatsColumns {
- /**
- * The sync account.
- * <P>Type: TEXT</P>
- */
- public static final String ACCOUNT = "account";
-
- /**
- * The sync account type.
- * <P>Type: TEXT</P>
- */
- public static final String ACCOUNT_TYPE = "account_type";
-
- /**
- * The content authority (contacts, calendar, etc.).
- * <P>Type: TEXT</P>
- */
- public static final String AUTHORITY = "authority";
- }
-
- /**
- * Provides constants and utility methods to access and use the stats table.
- */
- public static final class Stats implements BaseColumns, StatsColumns {
-
- // utility class
- private Stats() {}
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sync/stats");
-
- /** Projection for the _id column in the stats table. */
- public static final String[] SYNC_STATS_PROJECTION = {_ID};
- }
-
- /**
- * Columns from the history table.
- */
- public interface HistoryColumns {
- /**
- * The ID of the stats row corresponding to this event.
- * <P>Type: INTEGER</P>
- */
- public static final String STATS_ID = "stats_id";
-
- /**
- * The source of the sync event (LOCAL, POLL, USER, SERVER).
- * <P>Type: INTEGER</P>
- */
- public static final String SOURCE = "source";
-
- /**
- * The type of sync event (START, STOP).
- * <P>Type: INTEGER</P>
- */
- public static final String EVENT = "event";
-
- /**
- * The time of the event.
- * <P>Type: INTEGER</P>
- */
- public static final String EVENT_TIME = "eventTime";
-
- /**
- * How long this event took. This is only valid if the EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String ELAPSED_TIME = "elapsedTime";
-
- /**
- * Any additional message associated with this event.
- * <P>Type: TEXT</P>
- */
- public static final String MESG = "mesg";
-
- /**
- * How much activity was performed sending data to the server. This is sync adapter
- * specific, but usually is something like how many record update/insert/delete attempts
- * were carried out. This is only valid if the EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String UPSTREAM_ACTIVITY = "upstreamActivity";
-
- /**
- * How much activity was performed while receiving data from the server.
- * This is sync adapter specific, but usually is something like how many
- * records were received from the server. This is only valid if the
- * EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String DOWNSTREAM_ACTIVITY = "downstreamActivity";
- }
-
- /**
- * Columns from the history table.
- */
- public interface StatusColumns {
- /**
- * How many syncs were completed for this account and authority.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SYNCS = "numSyncs";
-
- /**
- * How long all the events for this account and authority took.
- * <P>Type: INTEGER</P>
- */
- public static final String TOTAL_ELAPSED_TIME = "totalElapsedTime";
-
- /**
- * The number of syncs with SOURCE_POLL.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_POLL = "numSourcePoll";
-
- /**
- * The number of syncs with SOURCE_SERVER.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_SERVER = "numSourceServer";
-
- /**
- * The number of syncs with SOURCE_LOCAL.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_LOCAL = "numSourceLocal";
-
- /**
- * The number of syncs with SOURCE_USER.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_USER = "numSourceUser";
-
- /**
- * The time in ms that the last successful sync ended. Will be null if
- * there are no successful syncs. A successful sync is defined as one having
- * MESG=MESG_SUCCESS.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_SUCCESS_TIME = "lastSuccessTime";
-
- /**
- * The SOURCE of the last successful sync. Will be null if
- * there are no successful syncs. A successful sync is defined
- * as one having MESG=MESG_SUCCESS.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_SUCCESS_SOURCE = "lastSuccessSource";
-
- /**
- * The end time in ms of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_FAILURE_TIME = "lastFailureTime";
-
- /**
- * The SOURCE of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_FAILURE_SOURCE = "lastFailureSource";
-
- /**
- * The MESG of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: STRING</P>
- */
- public static final String LAST_FAILURE_MESG = "lastFailureMesg";
-
- /**
- * Is set to 1 if a sync is pending, 0 if not.
- * <P>Type: INTEGER</P>
- */
- public static final String PENDING = "pending";
- }
-
- /**
- * Provides constants and utility methods to access and use the history
- * table.
- */
- public static class History implements BaseColumns,
- StatsColumns,
- HistoryColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sync/history");
-
- /** Enum value for a sync start event. */
- public static final int EVENT_START = 0;
-
- /** Enum value for a sync stop event. */
- public static final int EVENT_STOP = 1;
-
- // TODO: i18n -- grab these out of resources.
- /** String names for the sync event types. */
- public static final String[] EVENTS = { "START", "STOP" };
-
- /** Enum value for a server-initiated sync. */
- public static final int SOURCE_SERVER = 0;
-
- /** Enum value for a local-initiated sync. */
- public static final int SOURCE_LOCAL = 1;
- /**
- * Enum value for a poll-based sync (e.g., upon connection to
- * network)
- */
- public static final int SOURCE_POLL = 2;
-
- /** Enum value for a user-initiated sync. */
- public static final int SOURCE_USER = 3;
-
- // TODO: i18n -- grab these out of resources.
- /** String names for the sync source types. */
- public static final String[] SOURCES = { "SERVER",
- "LOCAL",
- "POLL",
- "USER" };
-
- // Error types
- public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
- public static final int ERROR_AUTHENTICATION = 2;
- public static final int ERROR_IO = 3;
- public static final int ERROR_PARSE = 4;
- public static final int ERROR_CONFLICT = 5;
- public static final int ERROR_TOO_MANY_DELETIONS = 6;
- public static final int ERROR_TOO_MANY_RETRIES = 7;
- public static final int ERROR_INTERNAL = 8;
-
- // The MESG column will contain one of these or one of the Error types.
- public static final String MESG_SUCCESS = "success";
- public static final String MESG_CANCELED = "canceled";
-
- private static final String FINISHED_SINCE_WHERE_CLAUSE = EVENT + "=" + EVENT_STOP
- + " AND " + EVENT_TIME + ">? AND " + ACCOUNT + "=? AND " + ACCOUNT_TYPE + "=?"
- + " AND " + AUTHORITY + "=?";
-
- public static String mesgToString(String mesg) {
- if (MESG_SUCCESS.equals(mesg)) return mesg;
- if (MESG_CANCELED.equals(mesg)) return mesg;
- switch (Integer.parseInt(mesg)) {
- case ERROR_SYNC_ALREADY_IN_PROGRESS: return "already in progress";
- case ERROR_AUTHENTICATION: return "bad authentication";
- case ERROR_IO: return "network error";
- case ERROR_PARSE: return "parse error";
- case ERROR_CONFLICT: return "conflict detected";
- case ERROR_TOO_MANY_DELETIONS: return "too many deletions";
- case ERROR_TOO_MANY_RETRIES: return "too many retries";
- case ERROR_INTERNAL: return "internal error";
- default: return "unknown error";
- }
- }
-
- // utility class
- private History() {}
-
- /**
- * returns a cursor that queries the sync history in descending event time order
- * @param contentResolver the ContentResolver to use for the query
- * @return the cursor on the History table
- */
- public static Cursor query(ContentResolver contentResolver) {
- return contentResolver.query(CONTENT_URI, null, null, null, EVENT_TIME + " desc");
- }
-
- public static boolean hasNewerSyncFinished(ContentResolver contentResolver,
- Account account, String authority, long when) {
- Cursor c = contentResolver.query(CONTENT_URI, new String[]{_ID},
- FINISHED_SINCE_WHERE_CLAUSE,
- new String[]{Long.toString(when), account.mName, account.mType, authority},
- null);
- try {
- return c.getCount() > 0;
- } finally {
- c.close();
- }
- }
- }
-
- /**
- * Provides constants and utility methods to access and use the authority history
- * table, which contains information about syncs aggregated by account and authority.
- * All the HistoryColumns except for EVENT are present, plus the AuthorityHistoryColumns.
- */
- public static class Status extends History implements StatusColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/status");
-
- // utility class
- private Status() {}
-
- /**
- * returns a cursor that queries the authority sync history in descending event order of
- * ACCOUNT, AUTHORITY
- * @param contentResolver the ContentResolver to use for the query
- * @return the cursor on the AuthorityHistory table
- */
- public static Cursor query(ContentResolver contentResolver) {
- return contentResolver.query(CONTENT_URI, null, null, null,
- ACCOUNT_TYPE + "," + ACCOUNT + "," + AUTHORITY);
- }
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver,
- boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null),
- _ID, keepUpdated, handlerForUpdateNotifications);
- }
-
- public ContentValues get(Account account, String authority) {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- if (values.getAsString(ACCOUNT).equals(account.mName)
- && values.getAsString(ACCOUNT_TYPE).equals(account.mType)
- && values.getAsString(AUTHORITY).equals(authority)) {
- return values;
- }
- }
- return null;
- }
- }
- }
-
- /**
- * Provides constants and utility methods to access and use the pending syncs table
- */
- public static final class Pending implements BaseColumns,
- StatsColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/pending");
-
- // utility class
- private Pending() {}
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
- handlerForUpdateNotifications);
- }
-
- public boolean isPending(Account account, String authority) {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- if (values.getAsString(ACCOUNT).equals(account.mName)
- && values.getAsString(ACCOUNT_TYPE).equals(account.mType)
- && values.getAsString(AUTHORITY).equals(authority)) {
- return true;
- }
- }
- return false;
- }
- }
- }
-
- /**
- * Columns from the history table.
- */
- public interface ActiveColumns {
- /**
- * The wallclock time of when the active sync started.
- * <P>Type: INTEGER</P>
- */
- public static final String START_TIME = "startTime";
- }
-
- /**
- * Provides constants and utility methods to access and use the pending syncs table
- */
- public static final class Active implements BaseColumns,
- StatsColumns,
- ActiveColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/active");
-
- // utility class
- private Active() {}
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
- handlerForUpdateNotifications);
- }
-
- public ContentValues getActiveSyncInfo() {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- return values;
- }
- return null;
- }
-
- public Account getSyncingAccount() {
- ContentValues values = getActiveSyncInfo();
- if (values == null || TextUtils.isEmpty(values.getAsString(ACCOUNT))) {
- return null;
- }
- return new Account(values.getAsString(ACCOUNT), values.getAsString(ACCOUNT_TYPE));
- }
-
- public String getSyncingAuthority() {
- ContentValues values = getActiveSyncInfo();
- return (values == null) ? null : values.getAsString(AUTHORITY);
- }
-
- public long getSyncStartTime() {
- ContentValues values = getActiveSyncInfo();
- return (values == null) ? -1 : values.getAsLong(START_TIME);
- }
- }
- }
-
- /**
- * Columns in the settings table, which holds key/value pairs of settings.
- */
- public interface SettingsColumns {
- /**
- * The key of the setting
- * <P>Type: TEXT</P>
- */
- public static final String KEY = "name";
-
- /**
- * The value of the settings
- * <P>Type: TEXT</P>
- */
- public static final String VALUE = "value";
- }
-
- /**
- * Provides constants and utility methods to access and use the settings
- * table.
- */
- public static final class Settings implements BaseColumns, SettingsColumns {
- /**
- * The Uri of the settings table. This table behaves a little differently than
- * normal tables. Updates are not allowed, only inserts, and inserts cause a replace
- * to be performed, which first deletes the row if it is already present.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/settings");
-
- /** controls whether or not the device listens for sync tickles */
- public static final String SETTING_LISTEN_FOR_TICKLES = "listen_for_tickles";
-
- /** controls whether or not the individual provider is synced when tickles are received */
- public static final String SETTING_SYNC_PROVIDER_PREFIX = "sync_provider_";
-
- /** query column project */
- private static final String[] PROJECTION = { KEY, VALUE };
-
- /**
- * Convenience function for updating a single settings value as a
- * boolean. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param name The name of the setting to modify.
- * @param val The new value for the setting.
- */
- static private void putBoolean(ContentResolver contentResolver, String name, boolean val) {
- ContentValues values = new ContentValues();
- values.put(KEY, name);
- values.put(VALUE, Boolean.toString(val));
- // this insert is translated into an update by the underlying Sync provider
- contentResolver.insert(CONTENT_URI, values);
- }
-
- /**
- * Convenience function for getting a setting value as a boolean without using the
- * QueryMap for light-weight setting querying.
- * @param contentResolver The ContentResolver for querying the setting.
- * @param name The name of the setting to query
- * @param def The default value for the setting.
- * @return The value of the setting.
- */
- static public boolean getBoolean(ContentResolver contentResolver,
- String name, boolean def) {
- Cursor cursor = contentResolver.query(
- CONTENT_URI,
- PROJECTION,
- KEY + "=?",
- new String[] { name },
- null);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- return Boolean.parseBoolean(cursor.getString(1));
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- return def;
- }
-
- /**
- * A convenience method to set whether or not the provider is synced when
- * it receives a network tickle.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param providerName the provider whose behavior is being controlled
- * @param sync true if the provider should be synced when tickles are received for it
- */
- static public void setSyncProviderAutomatically(ContentResolver contentResolver,
- String providerName, boolean sync) {
- putBoolean(contentResolver, SETTING_SYNC_PROVIDER_PREFIX + providerName, sync);
- }
-
- /**
- * A convenience method to set whether or not the device should listen to tickles.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param flag true if it should listen.
- */
- static public void setListenForNetworkTickles(ContentResolver contentResolver,
- boolean flag) {
- putBoolean(contentResolver, SETTING_LISTEN_FOR_TICKLES, flag);
- }
-
- public static class QueryMap extends ContentQueryMap {
- private ContentResolver mContentResolver;
-
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), KEY, keepUpdated,
- handlerForUpdateNotifications);
- mContentResolver = contentResolver;
- }
-
- /**
- * Check if the provider should be synced when a network tickle is received
- * @param providerName the provider whose setting we are querying
- * @return true of the provider should be synced when a network tickle is received
- */
- public boolean getSyncProviderAutomatically(String providerName) {
- return getBoolean(SETTING_SYNC_PROVIDER_PREFIX + providerName, true);
- }
-
- /**
- * Set whether or not the provider is synced when it receives a network tickle.
- *
- * @param providerName the provider whose behavior is being controlled
- * @param sync true if the provider should be synced when tickles are received for it
- */
- public void setSyncProviderAutomatically(String providerName, boolean sync) {
- Settings.setSyncProviderAutomatically(mContentResolver, providerName, sync);
- }
-
- /**
- * Set whether or not the device should listen for tickles.
- *
- * @param flag true if it should listen.
- */
- public void setListenForNetworkTickles(boolean flag) {
- Settings.setListenForNetworkTickles(mContentResolver, flag);
- }
-
- /**
- * Check if the device should listen to tickles.
-
- * @return true if it should
- */
- public boolean getListenForNetworkTickles() {
- return getBoolean(SETTING_LISTEN_FOR_TICKLES, true);
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a boolean.
- *
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- * @return The setting's current value, or 'def' if it is not defined.
- */
- private boolean getBoolean(String name, boolean def) {
- ContentValues values = getValues(name);
- return values != null ? values.getAsBoolean(VALUE) : def;
- }
- }
- }
-}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0d96ec3..a301d7b 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -247,7 +247,7 @@ public final class Telephony {
if (uri == null) {
return false;
}
-
+
boolean markAsUnread = false;
boolean markAsRead = false;
switch(folder) {
@@ -274,7 +274,7 @@ public final class Telephony {
} else if (markAsRead) {
values.put(READ, Integer.valueOf(1));
}
-
+
return 1 == SqliteWrapper.update(context, context.getContentResolver(),
uri, values, null, null);
}
@@ -1422,6 +1422,8 @@ public final class Telephony {
*/
public static final String _DATA = "_data";
+ public static final String TEXT = "text";
+
}
public static final class Rate {
@@ -1498,10 +1500,10 @@ public final class Telephony {
public static final Uri CONTENT_DRAFT_URI = Uri.parse(
"content://mms-sms/draft");
-
+
/***
* Pass in a query parameter called "pattern" which is the text
- * to search for.
+ * to search for.
* The sort order is fixed to be thread_id ASC,date DESC.
*/
public static final Uri SEARCH_URI = Uri.parse(
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index a27667b..c7cc8ed 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -57,6 +57,11 @@ public class Searchables {
private SearchableInfo mDefaultSearchable = null;
private SearchableInfo mDefaultSearchableForWebSearch = null;
+ public static String GOOGLE_SEARCH_COMPONENT_NAME =
+ "com.android.googlesearch/.GoogleSearch";
+ public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
+ "com.google.android.providers.enhancedgooglesearch/.Launcher";
+
/**
*
* @param context Context to use for looking up activities etc.
@@ -341,6 +346,18 @@ public class Searchables {
return component;
}
}
+ } else {
+ // If the current preferred activity is GoogleSearch, and we detect
+ // EnhancedGoogleSearch installed as well, set the latter as preferred since that
+ // is a superset and provides more functionality.
+ ComponentName cn = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+ if (cn.flattenToShortString().equals(GOOGLE_SEARCH_COMPONENT_NAME)) {
+ ComponentName enhancedGoogleSearch = ComponentName.unflattenFromString(
+ ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME);
+ if (setPreferredActivity(enhancedGoogleSearch, Intent.ACTION_WEB_SEARCH)) {
+ return enhancedGoogleSearch;
+ }
+ }
}
if (ri == null) return null;
diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl
index 02211fd..75c3b30 100755
--- a/core/java/android/speech/tts/ITts.aidl
+++ b/core/java/android/speech/tts/ITts.aidl
@@ -29,6 +29,8 @@ import android.content.Intent;
interface ITts {
void setSpeechRate(in int speechRate);
+ void setPitch(in int pitch);
+
void speak(in String text, in int queueMode, in String[] params);
boolean isSpeaking();
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 9fc143d..c064284 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -450,7 +450,6 @@ public class TextToSpeech {
}
-
/**
* Sets the speech rate for the TTS engine.
*
@@ -483,6 +482,37 @@ public class TextToSpeech {
/**
+ * Sets the speech pitch for the TTS engine.
+ *
+ * Note that the pitch is not universally supported by all engines and
+ * will be treated as a hint. The TTS library will try to use the specified
+ * pitch, but there is no guarantee.
+ * This has no effect on any pre-recorded speech.
+ *
+ * @param pitch
+ * The pitch for the TTS engine. 1 is the normal pitch,
+ * lower values lower the tone of the synthesized voice,
+ * greater values increase it.
+ */
+ public void setPitch(float pitch) {
+ synchronized (mStartLock) {
+ if (!mStarted) {
+ return;
+ }
+ try {
+ if (pitch > 0) {
+ mITts.setPitch((int)(pitch*100));
+ }
+ } catch (RemoteException e) {
+ // TTS died; restart it.
+ mStarted = false;
+ initTts();
+ }
+ }
+ }
+
+
+ /**
* Sets the language for the TTS engine.
*
* Note that the language is not universally supported by all engines and
diff --git a/core/java/android/syncml/pim/vcard/ContactStruct.java b/core/java/android/syncml/pim/vcard/ContactStruct.java
index 5a29112..4b4c394 100644
--- a/core/java/android/syncml/pim/vcard/ContactStruct.java
+++ b/core/java/android/syncml/pim/vcard/ContactStruct.java
@@ -38,6 +38,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -181,6 +182,34 @@ public class ContactStruct {
organizationList.add(organizationData);
}
+ /**
+ * Set "position" value to the appropriate data. If there's more than one
+ * OrganizationData objects, the value is set to the last one. If there's no
+ * OrganizationData object, a new OrganizationData is created, whose company name is
+ * empty.
+ *
+ * TODO: incomplete logic. fix this:
+ *
+ * e.g. This assumes ORG comes earlier, but TITLE may come earlier like this, though we do not
+ * know how to handle it in general cases...
+ * ----
+ * TITLE:Software Engineer
+ * ORG:Google
+ * ----
+ */
+ public void setPosition(String positionValue) {
+ if (organizationList == null) {
+ organizationList = new ArrayList<OrganizationData>();
+ }
+ int size = organizationList.size();
+ if (size == 0) {
+ addOrganization(Contacts.OrganizationColumns.TYPE_OTHER, "", null, false);
+ size = 1;
+ }
+ OrganizationData lastData = organizationList.get(size - 1);
+ lastData.positionName = positionValue;
+ }
+
public void addExtension(PropertyNode propertyNode) {
if (propertyNode.propValue.length() == 0) {
return;
@@ -427,8 +456,6 @@ public class ContactStruct {
} 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) {
@@ -442,29 +469,20 @@ public class ContactStruct {
}
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(", ");
- }
+ int size = list.size();
+ StringBuilder builder = new StringBuilder();
+ for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
+ builder.append(iter.next());
+ if (iter.hasNext()) {
+ builder.append(' ');
}
- positionName = builder.toString();
- } else if (size == 1) {
- companyName = propertyNode.propValue;
- positionName = "";
}
- contact.addOrganization(type, companyName, positionName, isPrimary);
+
+ contact.addOrganization(type, builder.toString(), "", isPrimary);
} else if (name.equals("TITLE")) {
- contact.title = propertyNode.propValue;
- // XXX: What to do this? Isn't ORG enough?
- contact.addExtension(propertyNode);
+ contact.setPosition(propertyNode.propValue);
} else if (name.equals("ROLE")) {
- // XXX: What to do this? Isn't ORG enough?
- contact.addExtension(propertyNode);
+ contact.setPosition(propertyNode.propValue);
} else if (name.equals("PHOTO")) {
// We prefer PHOTO to LOGO.
String valueType = propertyNode.paramMap.getAsString("VALUE");
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index a095913..d89ada0 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -106,16 +106,8 @@ public class DisplayMetrics {
* {@hide}
*/
public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
- if (compatibilityInfo.mScalingRequired) {
- float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
- density *= invertedRatio;
- scaledDensity *= invertedRatio;
- xdpi *= invertedRatio;
- ydpi *= invertedRatio;
- widthPixels *= invertedRatio;
- heightPixels *= invertedRatio;
- }
- if (!compatibilityInfo.mConfiguredExpandable) {
+ int xOffset = 0;
+ if (!compatibilityInfo.isConfiguredExpandable()) {
// Note: this assume that configuration is updated before calling
// updateMetrics method.
int defaultWidth;
@@ -141,11 +133,13 @@ public class DisplayMetrics {
if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
// the screen size is same as expected size. make it expandable
- compatibilityInfo.mExpandable = true;
+ compatibilityInfo.setExpandable(true);
} else {
- compatibilityInfo.mExpandable = false;
+ compatibilityInfo.setExpandable(false);
// adjust the size only when the device's screen is bigger.
if (defaultWidth < widthPixels) {
+ // content/window's x offset in original pixels
+ xOffset = ((widthPixels - defaultWidth) / 2);
widthPixels = defaultWidth;
}
if (defaultHeight < heightPixels) {
@@ -153,8 +147,19 @@ public class DisplayMetrics {
}
}
}
+ compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
+ if (compatibilityInfo.isScalingRequired()) {
+ float invertedRatio = compatibilityInfo.applicationInvertedScale;
+ density *= invertedRatio;
+ scaledDensity *= invertedRatio;
+ xdpi *= invertedRatio;
+ ydpi *= invertedRatio;
+ widthPixels *= invertedRatio;
+ heightPixels *= invertedRatio;
+ }
}
+ @Override
public String toString() {
return "DisplayMetrics{density=" + density + ", width=" + widthPixels +
", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 69c6a7c..0e37b26 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -270,28 +270,47 @@ public final class MotionEvent implements Parcelable {
}
/**
- * Scales down the cood of this event by the given scale.
+ * Scales down the coordination of this event by the given scale.
*
* @hide
*/
public void scale(float scale) {
- if (scale != 1.0f) {
- mX *= scale;
- mY *= scale;
- mRawX *= scale;
- mRawY *= scale;
- mSize *= scale;
- mXPrecision *= scale;
- mYPrecision *= scale;
- if (mHistory != null) {
- float[] history = mHistory;
- int length = history.length;
- for (int i = 0; i < length; i += 4) {
- history[i] *= scale; // X
- // history[i + 2] == pressure
- history[i + 1] *= scale; // Y
- history[i + 3] *= scale; // Size, TODO: square this?
- }
+ mX *= scale;
+ mY *= scale;
+ mRawX *= scale;
+ mRawY *= scale;
+ mSize *= scale;
+ mXPrecision *= scale;
+ mYPrecision *= scale;
+ if (mHistory != null) {
+ float[] history = mHistory;
+ int length = history.length;
+ for (int i = 0; i < length; i += 4) {
+ history[i] *= scale; // X
+ history[i + 1] *= scale; // Y
+ // no need to scale pressure ([i+2])
+ history[i + 3] *= scale; // Size, TODO: square this?
+ }
+ }
+ }
+
+ /**
+ * Translate the coordination of the event by given x and y.
+ *
+ * @hide
+ */
+ public void translate(float dx, float dy) {
+ mX += dx;
+ mY += dy;
+ mRawX += dx;
+ mRawY += dx;
+ if (mHistory != null) {
+ float[] history = mHistory;
+ int length = history.length;
+ for (int i = 0; i < length; i += 4) {
+ history[i] += dx; // X
+ history[i + 1] += dy; // Y
+ // no need to translate pressure (i+2) and size (i+3)
}
}
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6519852..1e2bc1f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -18,6 +18,7 @@ package android.view;
import android.content.Context;
import android.content.res.CompatibilityInfo;
+import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
@@ -139,24 +140,21 @@ public class SurfaceView extends View {
int mFormat = -1;
int mType = -1;
final Rect mSurfaceFrame = new Rect();
- private final CompatibilityInfo mCompatibilityInfo;
+ private Translator mTranslator;
public SurfaceView(Context context) {
super(context);
setWillNotDraw(true);
- mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
public SurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(true);
- mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(true);
- mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
/**
@@ -259,9 +257,9 @@ public class SurfaceView extends View {
public boolean dispatchTouchEvent(MotionEvent event) {
// SurfaceView uses pre-scaled size unless fixed size is requested. This hook
// scales the event back to the pre-scaled coordinates for such surface.
- if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {
+ if (mRequestedWidth < 0 && mTranslator != null) {
MotionEvent scaledBack = MotionEvent.obtain(event);
- scaledBack.scale(mCompatibilityInfo.mApplicationScale);
+ scaledBack.scale(mTranslator.applicationScale);
try {
return super.dispatchTouchEvent(scaledBack);
} finally {
@@ -298,15 +296,18 @@ public class SurfaceView extends View {
if (!mHaveFrame) {
return;
}
- float appScale = mCompatibilityInfo.mApplicationScale;
+ mTranslator = ((ViewRoot)getRootView().getParent()).mTranslator;
+
+ float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale;
int myWidth = mRequestedWidth;
if (myWidth <= 0) myWidth = getWidth();
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
- // Use original size for surface unless fixed size is requested.
- if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) {
+ // Use original size if the app specified the size of the view,
+ // and let the flinger to scale up.
+ if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) {
myWidth *= appScale;
myHeight *= appScale;
}
@@ -326,7 +327,7 @@ public class SurfaceView extends View {
+ " visible=" + visibleChanged
+ " left=" + (mLeft != mLocation[0])
+ " top=" + (mTop != mLocation[1]));
-
+
try {
final boolean visible = mVisible = mRequestedVisible;
mLeft = mLocation[0];
@@ -336,16 +337,23 @@ public class SurfaceView extends View {
mFormat = mRequestedFormat;
mType = mRequestedType;
- // Scaling window's layout here because mLayout is not used elsewhere.
- mLayout.x = (int) (mLeft * appScale);
- mLayout.y = (int) (mTop * appScale);
- mLayout.width = (int) (getWidth() * appScale);
- mLayout.height = (int) (getHeight() * appScale);
+ // Scaling/Translate window's layout here because mLayout is not used elsewhere.
+
+ // Places the window relative
+ mLayout.x = mLeft;
+ mLayout.y = mTop;
+ mLayout.width = getWidth();
+ mLayout.height = getHeight();
+ if (mTranslator != null) {
+ mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
+ }
+
mLayout.format = mRequestedFormat;
mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_SCALED
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING
;
mLayout.memoryType = mRequestedType;
@@ -372,13 +380,6 @@ public class SurfaceView extends View {
visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
mVisibleInsets, mSurface);
- if (mCompatibilityInfo.mScalingRequired) {
- float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
- mContentInsets.scale(invertedScale);
- mVisibleInsets.scale(invertedScale);
- mWinFrame.scale(invertedScale);
- }
-
if (localLOGV) Log.i(TAG, "New surface: " + mSurface
+ ", vis=" + visible + ", frame=" + mWinFrame);
mSurfaceFrame.left = 0;
@@ -447,24 +448,14 @@ public class SurfaceView extends View {
private static class MyWindow extends IWindow.Stub {
private final WeakReference<SurfaceView> mSurfaceView;
- private final CompatibilityInfo mCompatibilityInfo;
public MyWindow(SurfaceView surfaceView) {
mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
- mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();
}
public void resized(int w, int h, Rect coveredInsets,
Rect visibleInsets, boolean reportDraw) {
SurfaceView surfaceView = mSurfaceView.get();
- if (mCompatibilityInfo.mScalingRequired) {
- float scale = mCompatibilityInfo.mApplicationInvertedScale;
- w *= scale;
- h *= scale;
- coveredInsets.scale(scale);
- visibleInsets.scale(scale);
- }
-
if (surfaceView != null) {
if (localLOGV) Log.v(
"SurfaceView", surfaceView + " got resized: w=" +
@@ -627,9 +618,6 @@ public class SurfaceView extends View {
Canvas c = null;
if (!mDrawingStopped && mWindow != null) {
Rect frame = dirty != null ? dirty : mSurfaceFrame;
- if (mCompatibilityInfo.mScalingRequired) {
- frame.scale(mCompatibilityInfo.mApplicationScale);
- }
try {
c = mSurface.lockCanvas(frame);
} catch (Exception e) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ec8fd96..3bfdde8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1934,11 +1934,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
viewFlagMasks |= SOUND_EFFECTS_ENABLED;
}
+ break;
case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
if (!a.getBoolean(attr, true)) {
viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
}
+ break;
case R.styleable.View_scrollbars:
final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
if (scrollbars != SCROLLBARS_NONE) {
@@ -6541,7 +6543,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
boolean changed = false;
if (DBG) {
- System.out.println(this + " View.setFrame(" + left + "," + top + ","
+ Log.d("View", this + " View.setFrame(" + left + "," + top + ","
+ right + "," + bottom + ")");
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index fe5edc2..a12b14a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -131,13 +131,12 @@ public final class ViewRoot extends Handler implements ViewParent,
Rect mDirty; // will be a graphics.Region soon
boolean mIsAnimating;
- private CompatibilityInfo mCompatibilityInfo;
+ CompatibilityInfo.Translator mTranslator;
final View.AttachInfo mAttachInfo;
final Rect mTempRect; // used in the transaction to not thrash the heap.
final Rect mVisRect; // used to retrieve visible rect of focused view.
- final Point mVisPoint; // used to retrieve global offset of focused view.
boolean mTraversalScheduled;
boolean mWillDrawSoon;
@@ -225,7 +224,6 @@ public final class ViewRoot extends Handler implements ViewParent,
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
- mVisPoint = new Point();
mWinFrame = new Rect();
mWindow = new W(this, context);
mInputMethodCallback = new InputMethodCallback(this);
@@ -394,20 +392,25 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mView == null) {
mView = view;
mWindowAttributes.copyFrom(attrs);
- mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo();
+
+ CompatibilityInfo compatibilityInfo =
+ mView.getContext().getResources().getCompatibilityInfo();
+ mTranslator = compatibilityInfo.getTranslator(attrs);
boolean restore = false;
- if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) {
+ if (attrs != null && mTranslator != null) {
restore = true;
- mWindowAttributes.backup();
- }
- if (!mCompatibilityInfo.mExpandable) {
- adjustWindowAttributesForCompatibleMode(mWindowAttributes);
+ attrs.backup();
+ mTranslator.translateWindowLayout(attrs);
}
+ if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
+
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
mAttachInfo.mRootView = view;
- mAttachInfo.mScalingRequired = mCompatibilityInfo.mScalingRequired;
- mAttachInfo.mApplicationScale = mCompatibilityInfo.mApplicationScale;
+ mAttachInfo.mScalingRequired =
+ mTranslator == null ? false : mTranslator.scalingRequired;
+ mAttachInfo.mApplicationScale =
+ mTranslator == null ? 1.0f : mTranslator.applicationScale;
if (panelParentView != null) {
mAttachInfo.mPanelParentWindowToken
= panelParentView.getApplicationWindowToken();
@@ -428,15 +431,14 @@ public final class ViewRoot extends Handler implements ViewParent,
mAttachInfo.mRootView = null;
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
+ } finally {
+ if (restore) {
+ attrs.restore();
+ }
}
- if (restore) {
- mWindowAttributes.restore();
- }
-
- if (mCompatibilityInfo.mScalingRequired) {
- mAttachInfo.mContentInsets.scale(
- mCompatibilityInfo.mApplicationInvertedScale);
+ if (mTranslator != null) {
+ mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
}
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
@@ -548,14 +550,14 @@ public final class ViewRoot extends Handler implements ViewParent,
public void invalidateChild(View child, Rect dirty) {
checkThread();
- if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
- if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
+ if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+ if (mCurScrollY != 0 || mTranslator != null) {
mTempRect.set(dirty);
if (mCurScrollY != 0) {
mTempRect.offset(0, -mCurScrollY);
}
- if (mCompatibilityInfo.mScalingRequired) {
- mTempRect.scale(mCompatibilityInfo.mApplicationScale);
+ if (mTranslator != null) {
+ mTranslator.translateRectInAppWindowToScreen(mTempRect);
}
dirty = mTempRect;
}
@@ -574,7 +576,7 @@ public final class ViewRoot extends Handler implements ViewParent,
return null;
}
- public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
+ public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
if (child != mView) {
throw new RuntimeException("child is not mine, honest!");
}
@@ -635,14 +637,14 @@ public final class ViewRoot extends Handler implements ViewParent,
boolean viewVisibilityChanged = mViewVisibility != viewVisibility
|| mNewSurfaceNeeded;
- float appScale = mCompatibilityInfo.mApplicationScale;
+ float appScale = mAttachInfo.mApplicationScale;
WindowManager.LayoutParams params = null;
if (mWindowAttributesChanged) {
mWindowAttributesChanged = false;
params = lp;
}
-
+ Rect frame = mWinFrame;
if (mFirst) {
fullRedrawNeeded = true;
mLayoutRequested = true;
@@ -667,11 +669,11 @@ public final class ViewRoot extends Handler implements ViewParent,
//Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
} else {
- desiredWindowWidth = mWinFrame.width();
- desiredWindowHeight = mWinFrame.height();
+ desiredWindowWidth = frame.width();
+ desiredWindowHeight = frame.height();
if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
if (DEBUG_ORIENTATION) Log.v("ViewRoot",
- "View " + host + " resized to: " + mWinFrame);
+ "View " + host + " resized to: " + frame);
fullRedrawNeeded = true;
mLayoutRequested = true;
windowResizesToFitContent = true;
@@ -817,7 +819,6 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
- final Rect frame = mWinFrame;
boolean initialized = false;
boolean contentInsetsChanged = false;
boolean visibleInsetsChanged;
@@ -890,7 +891,7 @@ public final class ViewRoot extends Handler implements ViewParent,
} catch (RemoteException e) {
}
if (DEBUG_ORIENTATION) Log.v(
- "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface);
+ "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface);
attachInfo.mWindowLeft = frame.left;
attachInfo.mWindowTop = frame.top;
@@ -965,7 +966,6 @@ public final class ViewRoot extends Handler implements ViewParent,
if (Config.DEBUG && ViewDebug.profileLayout) {
startTime = SystemClock.elapsedRealtime();
}
-
host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -992,7 +992,10 @@ public final class ViewRoot extends Handler implements ViewParent,
mTmpLocation[1] + host.mBottom - host.mTop);
host.gatherTransparentRegion(mTransparentRegion);
- mTransparentRegion.scale(appScale);
+ if (mTranslator != null) {
+ mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
+ }
+
if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
mPreviousTransparentRegion.set(mTransparentRegion);
// reconfigure window manager
@@ -1023,15 +1026,17 @@ public final class ViewRoot extends Handler implements ViewParent,
= givenContent.bottom = givenVisible.left = givenVisible.top
= givenVisible.right = givenVisible.bottom = 0;
attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
- if (mCompatibilityInfo.mScalingRequired) {
- insets.contentInsets.scale(appScale);
- insets.visibleInsets.scale(appScale);
+ Rect contentInsets = insets.contentInsets;
+ Rect visibleInsets = insets.visibleInsets;
+ if (mTranslator != null) {
+ contentInsets = mTranslator.getTranslatedContentInsets(contentInsets);
+ visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets);
}
if (insetsPending || !mLastGivenInsets.equals(insets)) {
mLastGivenInsets.set(insets);
try {
sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
- insets.contentInsets, insets.visibleInsets);
+ contentInsets, visibleInsets);
} catch (RemoteException e) {
}
}
@@ -1174,8 +1179,8 @@ public final class ViewRoot extends Handler implements ViewParent,
mCurScrollY = yoff;
fullRedrawNeeded = true;
}
- float appScale = mCompatibilityInfo.mApplicationScale;
- boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+ float appScale = mAttachInfo.mApplicationScale;
+ boolean scalingRequired = mAttachInfo.mScalingRequired;
Rect dirty = mDirty;
if (mUseGL) {
@@ -1194,8 +1199,8 @@ public final class ViewRoot extends Handler implements ViewParent,
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scalingRequired) {
- canvas.scale(appScale, appScale);
+ if (mTranslator != null) {
+ mTranslator.translateCanvas(canvas);
}
mView.draw(canvas);
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1246,7 +1251,6 @@ public final class ViewRoot extends Handler implements ViewParent,
int top = dirty.top;
int right = dirty.right;
int bottom = dirty.bottom;
-
canvas = surface.lockCanvas(dirty);
if (left != dirty.left || top != dirty.top || right != dirty.right ||
@@ -1302,8 +1306,8 @@ public final class ViewRoot extends Handler implements ViewParent,
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scalingRequired) {
- canvas.scale(appScale, appScale);
+ if (mTranslator != null) {
+ mTranslator.translateCanvas(canvas);
}
mView.draw(canvas);
} finally {
@@ -1616,10 +1620,9 @@ public final class ViewRoot extends Handler implements ViewParent,
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
- if (event != null && mCompatibilityInfo.mScalingRequired) {
- event.scale(mCompatibilityInfo.mApplicationInvertedScale);
+ if (event != null && mTranslator != null) {
+ mTranslator.translateEventInScreenToAppWindow(event);
}
-
try {
boolean handled;
if (mView != null && mAdded && event != null) {
@@ -1711,6 +1714,7 @@ public final class ViewRoot extends Handler implements ViewParent,
case RESIZED:
Rect coveredInsets = ((Rect[])msg.obj)[0];
Rect visibleInsets = ((Rect[])msg.obj)[1];
+
if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
&& mPendingContentInsets.equals(coveredInsets)
&& mPendingVisibleInsets.equals(visibleInsets)) {
@@ -1745,7 +1749,7 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
- float appScale = mCompatibilityInfo.mApplicationScale;
+ float appScale = mAttachInfo.mApplicationScale;
mGlCanvas.setViewport(
(int) (mWidth * appScale), (int) (mHeight * appScale));
}
@@ -2379,18 +2383,16 @@ public final class ViewRoot extends Handler implements ViewParent,
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
+
+ float appScale = mAttachInfo.mApplicationScale;
boolean restore = false;
- float appScale = mCompatibilityInfo.mApplicationScale;
- boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
- if (params != null && !mCompatibilityInfo.mExpandable) {
+ if (params != null && mTranslator != null) {
restore = true;
params.backup();
- adjustWindowAttributesForCompatibleMode(params);
+ mTranslator.translateWindowLayout(params);
}
- if (params != null && scalingRequired) {
- if (!restore) params.backup();
- restore = true;
- params.scale(appScale);
+ if (params != null) {
+ if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
}
int relayoutResult = sWindowSession.relayout(
mWindow, params,
@@ -2401,44 +2403,16 @@ public final class ViewRoot extends Handler implements ViewParent,
if (restore) {
params.restore();
}
- if (scalingRequired) {
- float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
- mPendingContentInsets.scale(invertedScale);
- mPendingVisibleInsets.scale(invertedScale);
- mWinFrame.scale(invertedScale);
+
+ if (mTranslator != null) {
+ mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+ mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
+ mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
}
return relayoutResult;
}
/**
- * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
- * with the default window size, and centers if the window wanted to fill
- * horizontally.
- *
- * @param attrs the window's layout params to adjust
- */
- private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
- // fix app windows only
- if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
- // TODO: improve gravity logic
- if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
- attrs.width = metrics.widthPixels;
- attrs.gravity |= Gravity.CENTER_HORIZONTAL;
- mWindowAttributesChanged = attrs == mWindowAttributes;
- }
- if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
- attrs.height = metrics.heightPixels;
- attrs.gravity |= Gravity.TOP;
- mWindowAttributesChanged = attrs == mWindowAttributes;
- }
- if (DEBUG_LAYOUT) {
- Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs);
- }
- }
- }
-
- /**
* {@inheritDoc}
*/
public void playSoundEffect(int effectId) {
@@ -2541,16 +2515,14 @@ public final class ViewRoot extends Handler implements ViewParent,
+ " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw);
Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
- if (mCompatibilityInfo.mScalingRequired) {
- float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
- coveredInsets.scale(invertedScale);
- visibleInsets.scale(invertedScale);
- msg.arg1 = (int) (w * invertedScale);
- msg.arg2 = (int) (h * invertedScale);
- } else {
- msg.arg1 = w;
- msg.arg2 = h;
- }
+ if (mTranslator != null) {
+ mTranslator.translateRectInScreenToAppWindow(coveredInsets);
+ mTranslator.translateRectInScreenToAppWindow(visibleInsets);
+ w *= mTranslator.applicationInvertedScale;
+ h *= mTranslator.applicationInvertedScale;
+ }
+ msg.arg1 = w;
+ msg.arg2 = h;
msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
sendMessage(msg);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e1c4687..bdb86d7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -18,7 +18,6 @@ package android.view;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -484,6 +483,12 @@ public interface WindowManager extends ViewManager {
* {@hide} */
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
+ /** Window flag: special flag to let a window ignore the compatibility scaling.
+ * This is used by SurfaceView to create a window that does not scale the content.
+ *
+ * {@hide} */
+ public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000;
+
/** Window flag: a special option intended for system dialogs. When
* this flag is set, the window will demand focus unconditionally when
* it is created.
@@ -805,6 +810,7 @@ public interface WindowManager extends ViewManager {
screenOrientation = in.readInt();
}
+ @SuppressWarnings({"PointlessBitwiseExpression"})
public static final int LAYOUT_CHANGED = 1<<0;
public static final int TYPE_CHANGED = 1<<1;
public static final int FLAGS_CHANGED = 1<<2;
@@ -978,8 +984,9 @@ public interface WindowManager extends ViewManager {
/**
* Scale the layout params' coordinates and size.
+ * @hide
*/
- void scale(float scale) {
+ public void scale(float scale) {
x *= scale;
y *= scale;
if (width > 0) {
@@ -997,14 +1004,13 @@ public interface WindowManager extends ViewManager {
void backup() {
int[] backup = mCompatibilityParamsBackup;
if (backup == null) {
- // we backup 5 elements, x, y, width, height and gravity.
- backup = mCompatibilityParamsBackup = new int[5];
+ // we backup 4 elements, x, y, width, height
+ backup = mCompatibilityParamsBackup = new int[4];
}
backup[0] = x;
backup[1] = y;
backup[2] = width;
backup[3] = height;
- backup[4] = gravity;
}
/**
@@ -1018,7 +1024,6 @@ public interface WindowManager extends ViewManager {
y = backup[1];
width = backup[2];
height = backup[3];
- gravity = backup[4];
}
}
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 11de3e2..9a0f467 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -297,6 +297,10 @@ public class BaseInputConnection implements InputConnection {
b = tmp;
}
+ if (a <= 0) {
+ return "";
+ }
+
if (length > a) {
length = a;
}
@@ -488,12 +492,12 @@ public class BaseInputConnection implements InputConnection {
} else {
a = Selection.getSelectionStart(content);
b = Selection.getSelectionEnd(content);
- if (a >=0 && b>= 0 && a != b) {
- if (b < a) {
- int tmp = a;
- a = b;
- b = tmp;
- }
+ if (a < 0) a = 0;
+ if (b < 0) b = 0;
+ if (b < a) {
+ int tmp = a;
+ a = b;
+ b = tmp;
}
}
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index cbe337a..7c071be 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -227,7 +227,8 @@ final class JWebCoreJavaBridge extends Handler {
}
private String getSignedPublicKey(int index, String challenge, String url) {
- return Keystore.getInstance().generateKeyPair(index, challenge, url);
+ // generateKeyPair expects organizations which we don't have. Ignore url.
+ return Keystore.getInstance().generateKeyPair(index, challenge, null);
}
private native void nativeConstructor();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2d8950e..186e1d1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1759,9 +1759,6 @@ public class WebView extends AbsoluteLayout
private Rect sendOurVisibleRect() {
Rect rect = new Rect();
calcOurContentVisibleRect(rect);
- if (mFindIsUp) {
- rect.bottom -= viewToContent(FIND_HEIGHT);
- }
// Rect.equals() checks for null input.
if (!rect.equals(mLastVisibleRectSent)) {
Point pos = new Point(rect.left, rect.top);
@@ -1772,6 +1769,11 @@ public class WebView extends AbsoluteLayout
Rect globalRect = new Rect();
if (getGlobalVisibleRect(globalRect)
&& !globalRect.equals(mLastGlobalRect)) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "sendOurVisibleRect=(" + globalRect.left + ","
+ + globalRect.top + ",r=" + globalRect.right + ",b="
+ + globalRect.bottom);
+ }
// TODO: the global offset is only used by windowRect()
// in ChromeClientAndroid ; other clients such as touch
// and mouse events could return view + screen relative points.
@@ -1786,6 +1788,9 @@ public class WebView extends AbsoluteLayout
Point p = new Point();
getGlobalVisibleRect(r, p);
r.offset(-p.x, -p.y);
+ if (mFindIsUp) {
+ r.bottom -= FIND_HEIGHT;
+ }
}
// Sets r to be our visible rectangle in content coordinates
@@ -3006,7 +3011,8 @@ public class WebView extends AbsoluteLayout
mTextGeneration = 0;
}
mWebTextView.setTextSize(contentToView(nativeFocusCandidateTextSize()));
- Rect visibleRect = sendOurVisibleRect();
+ Rect visibleRect = new Rect();
+ calcOurContentVisibleRect(visibleRect);
// Note that sendOurVisibleRect calls viewToContent, so the coordinates
// should be in content coordinates.
Rect bounds = nativeFocusCandidateNodeBounds();
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 1c66803..96cc2fd 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -80,6 +80,7 @@ import com.android.internal.R;
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownSelector
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
+ * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
*/
public class AutoCompleteTextView extends EditText implements Filter.FilterListener {
static final boolean DEBUG = false;
@@ -101,6 +102,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
private int mDropDownAnchorId;
private View mDropDownAnchorView; // view is retrieved lazily from id once needed
private int mDropDownWidth;
+ private int mDropDownHeight;
private Drawable mDropDownListHighlight;
@@ -166,6 +168,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
// (for full screen width) or WRAP_CONTENT (to match the width of the anchored view).
mDropDownWidth = a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownWidth,
ViewGroup.LayoutParams.WRAP_CONTENT);
+ mDropDownHeight = a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownHeight,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
mHintResource = a.getResourceId(R.styleable.AutoCompleteTextView_completionHintView,
R.layout.simple_dropdown_hint);
@@ -254,6 +258,34 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
public void setDropDownWidth(int width) {
mDropDownWidth = width;
}
+
+ /**
+ * <p>Returns the current height for the auto-complete drop down list. This can
+ * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill
+ * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height
+ * of the drop down's content.</p>
+ *
+ * @return the height for the drop down list
+ *
+ * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
+ */
+ public int getDropDownHeight() {
+ return mDropDownHeight;
+ }
+
+ /**
+ * <p>Sets the current height for the auto-complete drop down list. This can
+ * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill
+ * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height
+ * of the drop down's content.</p>
+ *
+ * @param height the height to use
+ *
+ * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
+ */
+ public void setDropDownHeight(int height) {
+ mDropDownHeight = height;
+ }
/**
* <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p>
@@ -571,7 +603,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
if (isPopupShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
- if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && !mDropDownAlwaysVisible) {
dismissDropDown();
return true;
}
@@ -621,7 +653,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
// event to prevent focus from moving.
clearListSelection();
mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
- mPopup.update();
+ showDropDown();
return true;
} else {
// WARNING: Please read the comment where mListSelectionHidden
@@ -641,7 +673,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
// by ensuring it has focus and getting its window out
// of touch mode.
mDropDownList.requestFocusFromTouch();
- mPopup.update();
+ showDropDown();
switch (keyCode) {
// avoid passing the focus from the text view to the
@@ -741,7 +773,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
} else {
// drop down is automatically dismissed when enough characters
// are deleted from the text view
- dismissDropDown();
+ if (!mDropDownAlwaysVisible) dismissDropDown();
if (mFilter != null) {
mFilter.filter(null);
}
@@ -882,7 +914,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
}
}
- if (mDropDownDismissedOnCompletion) {
+ if (mDropDownDismissedOnCompletion && !mDropDownAlwaysVisible) {
dismissDropDown();
}
}
@@ -963,7 +995,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
if (hasFocus() && hasWindowFocus()) {
showDropDown();
}
- } else {
+ } else if (!mDropDownAlwaysVisible) {
dismissDropDown();
}
}
@@ -972,7 +1004,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
performValidation();
- if (!hasWindowFocus) {
+ if (!hasWindowFocus && !mDropDownAlwaysVisible) {
dismissDropDown();
}
}
@@ -981,7 +1013,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
performValidation();
- if (!focused) {
+ if (!focused && !mDropDownAlwaysVisible) {
dismissDropDown();
}
}
@@ -1038,8 +1070,13 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
*/
public void showDropDown() {
int height = buildDropDown();
+
+ int widthSpec = 0;
+ int heightSpec = 0;
+
+ boolean noInputMethod = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
+
if (mPopup.isShowing()) {
- int widthSpec;
if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
// The call to PopupWindow's update method below can accept -1 for any
// value you do not want to update.
@@ -1049,20 +1086,51 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
} else {
widthSpec = mDropDownWidth;
}
+
+ if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
+ // The call to PopupWindow's update method below can accept -1 for any
+ // value you do not want to update.
+ heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.FILL_PARENT;
+ if (noInputMethod) {
+ mPopup.setWindowLayoutMode(
+ mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
+ ViewGroup.LayoutParams.FILL_PARENT : 0, 0);
+ } else {
+ mPopup.setWindowLayoutMode(
+ mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
+ ViewGroup.LayoutParams.FILL_PARENT : 0,
+ ViewGroup.LayoutParams.FILL_PARENT);
+ }
+ } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
+ heightSpec = height;
+ } else {
+ heightSpec = mDropDownHeight;
+ }
+
mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset,
- mDropDownVerticalOffset, widthSpec, height);
+ mDropDownVerticalOffset, widthSpec, heightSpec);
} else {
if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
- mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, 0);
+ widthSpec = ViewGroup.LayoutParams.FILL_PARENT;
} else {
- mPopup.setWindowLayoutMode(0, 0);
if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
mPopup.setWidth(getDropDownAnchorView().getWidth());
} else {
mPopup.setWidth(mDropDownWidth);
}
}
- mPopup.setHeight(height);
+
+ if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
+ heightSpec = ViewGroup.LayoutParams.FILL_PARENT;
+ } else {
+ if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
+ mPopup.setHeight(height);
+ } else {
+ mPopup.setHeight(mDropDownHeight);
+ }
+ }
+
+ mPopup.setWindowLayoutMode(widthSpec, heightSpec);
mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
mPopup.setOutsideTouchable(true);
mPopup.setTouchInterceptor(new PopupTouchIntercepter());
@@ -1178,10 +1246,12 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
final int maxHeight = mPopup.getMaxAvailableHeight(
getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
- final int measuredHeight = mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
- 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
+ if (mDropDownAlwaysVisible) {
+ return maxHeight;
+ }
- return mDropDownAlwaysVisible ? maxHeight : measuredHeight;
+ return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
+ 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
}
private View getHintView(Context context) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 6532125..f8a6f89 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3264,9 +3264,13 @@ public class ListView extends AbsListView {
if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
mCheckStates.put(position, value);
} else {
- boolean oldValue = mCheckStates.get(position, false);
+ // Clear the old value: if something was selected and value == false
+ // then it is unselected
mCheckStates.clear();
- if (!oldValue) {
+ // If value == true, select the appropriate position
+ // this may end up selecting the value we just cleared but this way
+ // we don't have to first to a get(position)
+ if (value) {
mCheckStates.put(position, true);
}
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 68764a5..0c2cd55 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -49,7 +49,7 @@ import java.lang.ref.WeakReference;
*/
public class PopupWindow {
/**
- * Mode for {@link #setInputMethodMode(int): the requirements for the
+ * Mode for {@link #setInputMethodMode(int)}: the requirements for the
* input method should be based on the focusability of the popup. That is
* if it is focusable than it needs to work with the input method, else
* it doesn't.
@@ -57,16 +57,15 @@ public class PopupWindow {
public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
/**
- * Mode for {@link #setInputMethodMode(int): this popup always needs to
+ * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
* work with an input method, regardless of whether it is focusable. This
* means that it will always be displayed so that the user can also operate
* the input method while it is shown.
*/
-
public static final int INPUT_METHOD_NEEDED = 1;
/**
- * Mode for {@link #setInputMethodMode(int): this popup never needs to
+ * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
* work with an input method, regardless of whether it is focusable. This
* means that it will always be displayed to use as much space on the
* screen as needed, regardless of whether this covers the input method.
@@ -823,6 +822,7 @@ public class PopupWindow {
p.flags = computeFlags(p.flags);
p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
p.token = token;
+ p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
return p;
@@ -990,7 +990,7 @@ public class PopupWindow {
int bottomEdge = displayFrame.bottom;
if (ignoreBottomDecorations) {
- bottomEdge = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight();
+ bottomEdge = anchor.getContext().getResources().getDisplayMetrics().heightPixels;
}
final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
@@ -1130,8 +1130,7 @@ public class PopupWindow {
return;
}
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
+ WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
boolean update = force;
@@ -1218,8 +1217,7 @@ public class PopupWindow {
registerForScrollChanged(anchor, xoff, yoff);
}
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
+ WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
if (updateDimension) {
if (width == -1) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 84cf2c8..955475e 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -20,8 +20,15 @@ import com.android.internal.R;
import android.content.Context;
import android.content.res.TypedArray;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.Pools;
+import android.util.PoolableManager;
+import static android.util.Log.d;
import android.view.Gravity;
import android.view.View;
import android.view.ViewDebug;
@@ -32,6 +39,8 @@ import android.widget.RemoteViews.RemoteView;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.LinkedList;
+import java.util.HashSet;
/**
* A Layout where the positions of the children can be described in relation to each other or to the
@@ -55,6 +64,10 @@ import java.util.TreeSet;
*/
@RemoteView
public class RelativeLayout extends ViewGroup {
+ private static final String LOG_TAG = "RelativeLayout";
+
+ private static final boolean DEBUG_GRAPH = false;
+
public static final int TRUE = -1;
/**
@@ -142,7 +155,12 @@ public class RelativeLayout extends ViewGroup {
private final Rect mSelfBounds = new Rect();
private int mIgnoreGravity;
- private static SortedSet<View> mTopToBottomLeftToRightSet = null;
+ private SortedSet<View> mTopToBottomLeftToRightSet = null;
+
+ private boolean mDirtyHierarchy;
+ private View[] mSortedHorizontalChildren = new View[0];
+ private View[] mSortedVerticalChildren = new View[0];
+ private final DependencyGraph mGraph = new DependencyGraph();
public RelativeLayout(Context context) {
super(context);
@@ -232,7 +250,54 @@ public class RelativeLayout extends ViewGroup {
}
@Override
+ public void requestLayout() {
+ super.requestLayout();
+ mDirtyHierarchy = true;
+ }
+
+ private void sortChildren() {
+ int count = getChildCount();
+ if (mSortedVerticalChildren.length != count) mSortedVerticalChildren = new View[count];
+ if (mSortedHorizontalChildren.length != count) mSortedHorizontalChildren = new View[count];
+
+ final DependencyGraph graph = mGraph;
+ graph.clear();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ graph.add(child);
+ }
+
+ if (DEBUG_GRAPH) {
+ d(LOG_TAG, "=== Sorted vertical children");
+ graph.log(getResources(), ABOVE, BELOW, ALIGN_BASELINE, ALIGN_TOP, ALIGN_BOTTOM);
+ d(LOG_TAG, "=== Sorted horizontal children");
+ graph.log(getResources(), LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT);
+ }
+
+ graph.getSortedViews(mSortedVerticalChildren, ABOVE, BELOW, ALIGN_BASELINE,
+ ALIGN_TOP, ALIGN_BOTTOM);
+ graph.getSortedViews(mSortedHorizontalChildren, LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT);
+
+ if (DEBUG_GRAPH) {
+ d(LOG_TAG, "=== Ordered list of vertical children");
+ for (View view : mSortedVerticalChildren) {
+ DependencyGraph.printViewId(getResources(), view);
+ }
+ d(LOG_TAG, "=== Ordered list of horizontal children");
+ for (View view : mSortedHorizontalChildren) {
+ DependencyGraph.printViewId(getResources(), view);
+ }
+ }
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mDirtyHierarchy) {
+ mDirtyHierarchy = false;
+ sortChildren();
+ }
+
int myWidth = -1;
int myHeight = -1;
@@ -261,7 +326,6 @@ public class RelativeLayout extends ViewGroup {
height = myHeight;
}
- int len = this.getChildCount();
mHasBaselineAlignedChild = false;
View ignore = null;
@@ -279,13 +343,29 @@ public class RelativeLayout extends ViewGroup {
ignore = findViewById(mIgnoreGravity);
}
- for (int i = 0; i < len; i++) {
- View child = getChildAt(i);
+ View[] views = mSortedVerticalChildren;
+ int count = views.length;
+ for (int i = 0; i < count; i++) {
+ View child = views[i];
+ if (child.getVisibility() != GONE) {
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
+
+ applyHorizontalSizeRules(params, myWidth);
+ measureChildHorizontal(child, params, myWidth);
+ positionChildHorizontal(child, params, myWidth);
+ }
+ }
+
+ views = mSortedHorizontalChildren;
+ count = views.length;
+ for (int i = 0; i < count; i++) {
+ View child = views[i];
if (child.getVisibility() != GONE) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
- applySizeRules(params, myWidth, myHeight);
+
+ applyVerticalSizeRules(params, myHeight);
measureChild(child, params, myWidth, myHeight);
- positionChild(child, params, myWidth, myHeight);
+ positionChildVertical(child, params, myHeight);
if (widthMode != MeasureSpec.EXACTLY) {
width = Math.max(width, params.mRight);
@@ -307,15 +387,15 @@ public class RelativeLayout extends ViewGroup {
}
if (mHasBaselineAlignedChild) {
- for (int i = 0; i < len; i++) {
+ for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
alignBaseline(child, params);
if (child != ignore || verticalGravity) {
- left = Math.min(left, params.mLeft - params.leftMargin);
- top = Math.min(top, params.mTop - params.topMargin);
+ left = Math.min(left, params.mLeft - params.leftMargin);
+ top = Math.min(top, params.mTop - params.topMargin);
}
if (child != ignore || horizontalGravity) {
@@ -362,7 +442,7 @@ public class RelativeLayout extends ViewGroup {
final int horizontalOffset = contentBounds.left - left;
final int verticalOffset = contentBounds.top - top;
if (horizontalOffset != 0 || verticalOffset != 0) {
- for (int i = 0; i < len; i++) {
+ for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE && child != ignore) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
@@ -416,9 +496,7 @@ public class RelativeLayout extends ViewGroup {
* @param myWidth Width of the the RelativeLayout
* @param myHeight Height of the RelativeLayout
*/
- private void measureChild(View child, LayoutParams params, int myWidth,
- int myHeight) {
-
+ private void measureChild(View child, LayoutParams params, int myWidth, int myHeight) {
int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
params.mRight, params.width,
params.leftMargin, params.rightMargin,
@@ -432,6 +510,16 @@ public class RelativeLayout extends ViewGroup {
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
+ private void measureChildHorizontal(View child, LayoutParams params, int myWidth) {
+ int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
+ params.mRight, params.width,
+ params.leftMargin, params.rightMargin,
+ mPaddingLeft, mPaddingRight,
+ myWidth);
+ int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
/**
* Get a measure spec that accounts for all of the constraints on this view.
* This includes size contstraints imposed by the RelativeLayout as well as
@@ -511,19 +599,7 @@ public class RelativeLayout extends ViewGroup {
return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode);
}
- /**
- * After the child has been measured, assign it a position. Some views may
- * already have final values for l,t,r,b. Others may have one or both edges
- * unfixed (i.e. set to -1) in each dimension. These will get positioned
- * based on which edge is fixed, the view's desired dimension, and whether
- * or not it is centered.
- *
- * @param child Child to position
- * @param params LayoutParams associated with child
- * @param myWidth Width of the the RelativeLayout
- * @param myHeight Height of the RelativeLayout
- */
- private void positionChild(View child, LayoutParams params, int myWidth, int myHeight) {
+ private void positionChildHorizontal(View child, LayoutParams params, int myWidth) {
int[] rules = params.getRules();
if (params.mLeft < 0 && params.mRight >= 0) {
@@ -541,6 +617,10 @@ public class RelativeLayout extends ViewGroup {
params.mRight = params.mLeft + child.getMeasuredWidth();
}
}
+ }
+
+ private void positionChildVertical(View child, LayoutParams params, int myHeight) {
+ int[] rules = params.getRules();
if (params.mTop < 0 && params.mBottom >= 0) {
// Bottom is fixed, but top varies
@@ -559,17 +639,7 @@ public class RelativeLayout extends ViewGroup {
}
}
- /**
- * Set l,t,r,b values in the LayoutParams for one view based on its layout rules.
- * Big assumption #1: All antecedents of this view have been sized & positioned
- * Big assumption #2: The dimensions of the parent view (the RelativeLayout)
- * are already known if they are needed.
- *
- * @param childParams LayoutParams for the view being positioned
- * @param myWidth Width of the the RelativeLayout
- * @param myHeight Height of the RelativeLayout
- */
- private void applySizeRules(LayoutParams childParams, int myWidth, int myHeight) {
+ private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
int[] rules = childParams.getRules();
RelativeLayout.LayoutParams anchorParams;
@@ -629,6 +699,11 @@ public class RelativeLayout extends ViewGroup {
// FIXME uh oh...
}
}
+ }
+
+ private void applyVerticalSizeRules(LayoutParams childParams, int myHeight) {
+ int[] rules = childParams.getRules();
+ RelativeLayout.LayoutParams anchorParams;
childParams.mTop = -1;
childParams.mBottom = -1;
@@ -691,18 +766,16 @@ public class RelativeLayout extends ViewGroup {
private View getRelatedView(int[] rules, int relation) {
int id = rules[relation];
if (id != 0) {
- View v = findViewById(id);
- if (v == null) {
- return null;
- }
+ DependencyGraph.Node node = mGraph.mNodes.get(id);
+ if (node == null) return null;
+ View v = node.view;
// Find the first non-GONE view up the chain
while (v.getVisibility() == View.GONE) {
rules = ((LayoutParams) v.getLayoutParams()).getRules();
- v = v.findViewById(rules[relation]);
- if (v == null) {
- return null;
- }
+ node = mGraph.mNodes.get((rules[relation]));
+ if (node == null) return null;
+ v = node.view;
}
return v;
@@ -1033,4 +1106,265 @@ public class RelativeLayout extends ViewGroup {
return mRules;
}
}
+
+ private static class DependencyGraph {
+ /**
+ * List of nodes in the graph. Each node is identified by its
+ * view id (see View#getId()).
+ */
+ private SparseArray<Node> mNodes = new SparseArray<Node>();
+
+ /**
+ * Temporary data structure used to build the list of roots
+ * for this graph.
+ */
+ private LinkedList<Node> mRoots = new LinkedList<Node>();
+
+ /**
+ * Clears the graph.
+ */
+ void clear() {
+ final SparseArray<Node> nodes = mNodes;
+ final int count = nodes.size();
+
+ for (int i = 0; i < count; i++) {
+ nodes.valueAt(i).release();
+ }
+ nodes.clear();
+
+ mRoots.clear();
+ }
+
+ /**
+ * Adds a view to the graph.
+ *
+ * @param view The view to be added as a node to the graph.
+ */
+ void add(View view) {
+ mNodes.put(view.getId(), Node.acquire(view));
+ }
+
+ /**
+ * Builds a sorted list of views. The sorting order depends on the dependencies
+ * between the view. For instance, if view C needs view A to be processed first
+ * and view A needs view B to be processed first, the dependency graph
+ * is: B -> A -> C. The sorted array will contain views B, A and C in this order.
+ *
+ * @param sorted The sorted list of views. The length of this array must
+ * be equal to getChildCount().
+ * @param rules The list of rules to take into account.
+ */
+ void getSortedViews(View[] sorted, int... rules) {
+ final LinkedList<Node> roots = findRoots(rules);
+ int index = 0;
+
+ while (roots.size() > 0) {
+ final Node node = roots.removeFirst();
+ final View view = node.view;
+ final int key = view.getId();
+
+ sorted[index++] = view;
+
+ final HashSet<Node> dependents = node.dependents;
+ for (Node dependent : dependents) {
+ final SparseArray<Node> dependencies = dependent.dependencies;
+
+ dependencies.remove(key);
+ if (dependencies.size() == 0) {
+ roots.add(dependent);
+ }
+ }
+ }
+
+ if (index < sorted.length) {
+ throw new IllegalStateException("Circular dependencies cannot exist"
+ + " in RelativeLayout");
+ }
+ }
+
+ /**
+ * Finds the roots of the graph. A root is a node with no dependency and
+ * with [0..n] dependents.
+ *
+ * @param rulesFilter The list of rules to consider when building the
+ * dependencies
+ *
+ * @return A list of node, each being a root of the graph
+ */
+ private LinkedList<Node> findRoots(int[] rulesFilter) {
+ final SparseArray<Node> nodes = mNodes;
+ final int count = nodes.size();
+
+ // Find roots can be invoked several times, so make sure to clear
+ // all dependents and dependencies before running the algorithm
+ for (int i = 0; i < count; i++) {
+ final Node node = nodes.valueAt(i);
+ node.dependents.clear();
+ node.dependencies.clear();
+ }
+
+ // Builds up the dependents and dependencies for each node of the graph
+ for (int i = 0; i < count; i++) {
+ final Node node = nodes.valueAt(i);
+
+ final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams();
+ final int[] rules = layoutParams.mRules;
+ final int rulesCount = rulesFilter.length;
+
+ // Look only the the rules passed in parameter, this way we build only the
+ // dependencies for a specific set of rules
+ for (int j = 0; j < rulesCount; j++) {
+ final int rule = rules[rulesFilter[j]];
+ if (rule > 0) {
+ // The node this node depends on
+ final Node dependency = nodes.get(rule);
+ if (dependency == node) {
+ throw new IllegalStateException("A view cannot have a dependency" +
+ " on itself");
+ }
+ // Add the current node as a dependent
+ dependency.dependents.add(node);
+ // Add a dependency to the current node
+ node.dependencies.put(rule, dependency);
+ }
+ }
+ }
+
+ final LinkedList<Node> roots = mRoots;
+ roots.clear();
+
+ // Finds all the roots in the graph: all nodes with no dependencies
+ for (int i = 0; i < count; i++) {
+ final Node node = nodes.valueAt(i);
+ if (node.dependencies.size() == 0) roots.add(node);
+ }
+
+ return roots;
+ }
+
+ /**
+ * Prints the dependency graph for the specified rules.
+ *
+ * @param resources The context's resources to print the ids.
+ * @param rules The list of rules to take into account.
+ */
+ void log(Resources resources, int... rules) {
+ final LinkedList<Node> roots = findRoots(rules);
+ for (Node node : roots) {
+ printNode(resources, node);
+ }
+ }
+
+ static void printViewId(Resources resources, View view) {
+ if (view.getId() != View.NO_ID) {
+ d(LOG_TAG, resources.getResourceEntryName(view.getId()));
+ } else {
+ d(LOG_TAG, "NO_ID");
+ }
+ }
+
+ private static void appendViewId(Resources resources, Node node, StringBuilder buffer) {
+ if (node.view.getId() != View.NO_ID) {
+ buffer.append(resources.getResourceEntryName(node.view.getId()));
+ } else {
+ buffer.append("NO_ID");
+ }
+ }
+
+ private static void printNode(Resources resources, Node node) {
+ if (node.dependents.size() == 0) {
+ printViewId(resources, node.view);
+ } else {
+ for (Node dependent : node.dependents) {
+ StringBuilder buffer = new StringBuilder();
+ appendViewId(resources, node, buffer);
+ printdependents(resources, dependent, buffer);
+ }
+ }
+ }
+
+ private static void printdependents(Resources resources, Node node, StringBuilder buffer) {
+ buffer.append(" -> ");
+ appendViewId(resources, node, buffer);
+
+ if (node.dependents.size() == 0) {
+ d(LOG_TAG, buffer.toString());
+ } else {
+ for (Node dependent : node.dependents) {
+ StringBuilder subBuffer = new StringBuilder(buffer);
+ printdependents(resources, dependent, subBuffer);
+ }
+ }
+ }
+
+ /**
+ * A node in the dependency graph. A node is a view, its list of dependencies
+ * and its list of dependents.
+ *
+ * A node with no dependent is considered a root of the graph.
+ */
+ static class Node implements Poolable<Node> {
+ /**
+ * The view representing this node in the layout.
+ */
+ View view;
+
+ /**
+ * The list of dependents for this node; a dependent is a node
+ * that needs this node to be processed first.
+ */
+ final HashSet<Node> dependents = new HashSet<Node>();
+
+ /**
+ * The list of dependencies for this node.
+ */
+ final SparseArray<Node> dependencies = new SparseArray<Node>();
+
+ /*
+ * START POOL IMPLEMENTATION
+ */
+ private static final int POOL_LIMIT = 12;
+ private static final Pool<Node> sPool = Pools.synchronizedPool(
+ Pools.finitePool(new PoolableManager<Node>() {
+ public Node newInstance() {
+ return new Node();
+ }
+
+ public void onAcquired(Node element) {
+ }
+
+ public void onReleased(Node element) {
+ }
+ }, POOL_LIMIT)
+ );
+
+ private Node mNext;
+
+ public void setNextPoolable(Node element) {
+ mNext = element;
+ }
+
+ public Node getNextPoolable() {
+ return mNext;
+ }
+
+ static Node acquire(View view) {
+ final Node node = sPool.acquire();
+ node.view = view;
+
+ return node;
+ }
+
+ void release() {
+ view = null;
+ dependents.clear();
+ dependencies.clear();
+
+ sPool.release(this);
+ }
+ /*
+ * END POOL IMPLEMENTATION
+ */
+ }
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1678f9a..d8ed4f0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3681,12 +3681,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected boolean isPaddingOffsetRequired() {
- return mShadowRadius != 0;
+ return mShadowRadius != 0 || mDrawables != null;
}
@Override
protected int getLeftPaddingOffset() {
- return (int) Math.min(0, mShadowDx - mShadowRadius);
+ return getCompoundPaddingLeft() - mPaddingLeft +
+ (int) Math.min(0, mShadowDx - mShadowRadius);
}
@Override
@@ -3701,7 +3702,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected int getRightPaddingOffset() {
- return (int) Math.max(0, mShadowDx + mShadowRadius);
+ return -(getCompoundPaddingRight() - mPaddingRight) +
+ (int) Math.max(0, mShadowDx + mShadowRadius);
}
@Override
@@ -6469,6 +6471,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode != InputMethodManager.RESULT_SHOWN) {
+ final int len = mText.length();
+ if (mNewStart > len) {
+ mNewStart = len;
+ }
+ if (mNewEnd > len) {
+ mNewEnd = len;
+ }
Selection.setSelection((Spannable)mText, mNewStart, mNewEnd);
}
}
@@ -6658,9 +6667,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else if (getLineCount() == 1) {
switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
- return (mLayout.getLineRight(0) - mScrollX - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight()) /
- getHorizontalFadingEdgeLength();
+ final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
+ getCompoundPaddingRight();
+ final float lineWidth = mLayout.getLineWidth(0);
+ return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
case Gravity.RIGHT:
return 0.0f;
case Gravity.CENTER_HORIZONTAL:
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index ce32754..4bac593 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -37,6 +37,7 @@ interface IBatteryStats {
void notePhoneOff();
void notePhoneSignalStrength(in SignalStrength signalStrength);
void notePhoneDataConnectionState(int dataType, boolean hasData);
+ void noteAirplaneMode(boolean isAirplaneMode);
void noteWifiOn(int uid);
void noteWifiOff(int uid);
void noteWifiRunning();
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 84ed729..ec63528 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -54,63 +54,70 @@ interface IBackupTransport {
long requestBackupTime();
/**
- * Establish a connection to the back-end data repository, if necessary. If the transport
- * needs to initialize state that is not tied to individual applications' backup operations,
- * this is where it should be done.
- *
- * @return Zero on success; a nonzero error code on failure.
- */
- int startSession();
-
- /**
- * Send one application's data to the backup destination.
+ * Send one application's data to the backup destination. The transport may send
+ * the data immediately, or may buffer it. After this is called, {@link #finishBackup}
+ * must be called to ensure the data is sent and recorded successfully.
*
* @param packageInfo The identity of the application whose data is being backed up.
* This specifically includes the signature list for the package.
* @param data The data stream that resulted from invoking the application's
* BackupService.doBackup() method. This may be a pipe rather than a file on
* persistent media, so it may not be seekable.
- * @return Zero on success; a nonzero error code on failure.
+ * @return false if errors occurred (the backup should be aborted and rescheduled),
+ * true if everything is OK so far (but {@link #finishBackup} must be called).
*/
- int performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor data);
+ boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
+
+ /**
+ * Finish sending application data to the backup destination. This must be
+ * called after {@link #performBackup} to ensure that all data is sent. Only
+ * when this method returns true can the backup be assumed to have succeeded.
+ *
+ * @return false if errors occurred (the backup should be aborted and rescheduled),
+ * true if everything is OK so far (but {@link #finishBackup} must be called).
+ */
+ boolean finishBackup();
/**
* Get the set of backups currently available over this transport.
*
- * @return Descriptions of the set of restore images available for this device.
+ * @return Descriptions of the set of restore images available for this device,
+ * or null if an error occurred (the attempt should be rescheduled).
**/
RestoreSet[] getAvailableRestoreSets();
/**
- * Get the set of applications from a given restore image.
+ * Start restoring application data from backup. After calling this function,
+ * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
+ * to walk through the actual application data.
*
* @param token A backup token as returned by {@link #getAvailableRestoreSets}.
- * @return An array of PackageInfo objects describing all of the applications
- * available for restore from this restore image. This should include the list
- * of signatures for each package so that the Backup Manager can filter using that
- * information.
+ * @param packages List of applications to restore (if data is available).
+ * Application data will be restored in the order given.
+ * @return false if errors occurred (the restore should be aborted and rescheduled),
+ * true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
*/
- PackageInfo[] getAppSet(int token);
+ boolean startRestore(long token, in PackageInfo[] packages);
/**
- * Retrieve one application's data from the backing store.
- *
- * @param token The backup record from which a restore is being requested.
- * @param packageInfo The identity of the application whose data is being restored.
- * This must include the signature list for the package; it is up to the transport
- * to verify that the requested app's signatures match the saved backup record
- * because the transport cannot necessarily trust the client device.
- * @param data An open, writable file into which the backup image should be stored.
- * @return Zero on success; a nonzero error code on failure.
+ * Get the package name of the next application with data in the backup store.
+ * @return The name of one of the packages supplied to {@link #startRestore},
+ * or "" (the empty string) if no more backup data is available,
+ * or null if an error occurred (the restore should be aborted and rescheduled).
*/
- int getRestoreData(int token, in PackageInfo packageInfo, in ParcelFileDescriptor data);
+ String nextRestorePackage();
/**
- * Terminate the backup session, closing files, freeing memory, and cleaning up whatever
- * other state the transport required.
- *
- * @return Zero on success; a nonzero error code on failure. Even on failure, the session
- * is torn down and must be restarted if another backup is attempted.
+ * Get the data for the application returned by {@link #nextRestorePackage}.
+ * @param data An open, writable file into which the backup data should be stored.
+ * @return false if errors occurred (the restore should be aborted and rescheduled),
+ * true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
+ */
+ boolean getRestoreData(in ParcelFileDescriptor outFd);
+
+ /**
+ * End a restore session (aborting any in-process data transfer as necessary),
+ * freeing any resources and connections used during the restore process.
*/
- int endSession();
+ void finishRestore();
}
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 3ef8666..0fbbb3f 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -33,11 +33,8 @@ public class LocalTransport extends IBackupTransport.Stub {
private Context mContext;
private PackageManager mPackageManager;
private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
- private FileFilter mDirFileFilter = new FileFilter() {
- public boolean accept(File f) {
- return f.isDirectory();
- }
- };
+ private PackageInfo[] mRestorePackages = null;
+ private int mRestorePackage = -1; // Index into mRestorePackages
public LocalTransport(Context context) {
@@ -51,21 +48,9 @@ public class LocalTransport extends IBackupTransport.Stub {
return 0;
}
- public int startSession() throws RemoteException {
- if (DEBUG) Log.v(TAG, "session started");
- mDataDir.mkdirs();
- return 0;
- }
-
- public int endSession() throws RemoteException {
- if (DEBUG) Log.v(TAG, "session ended");
- return 0;
- }
-
- public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
+ public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
throws RemoteException {
if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
- int err = 0;
File packageDir = new File(mDataDir, packageInfo.packageName);
packageDir.mkdirs();
@@ -101,9 +86,8 @@ public class LocalTransport extends IBackupTransport.Stub {
try {
entity.write(buf, 0, dataSize);
} catch (IOException e) {
- Log.e(TAG, "Unable to update key file "
- + entityFile.getAbsolutePath());
- err = -1;
+ Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
+ return false;
} finally {
entity.close();
}
@@ -111,14 +95,17 @@ public class LocalTransport extends IBackupTransport.Stub {
entityFile.delete();
}
}
+ return true;
} catch (IOException e) {
// oops, something went wrong. abort the operation and return error.
- Log.v(TAG, "Exception reading backup input:");
- e.printStackTrace();
- err = -1;
+ Log.v(TAG, "Exception reading backup input:", e);
+ return false;
}
+ }
- return err;
+ public boolean finishBackup() throws RemoteException {
+ if (DEBUG) Log.v(TAG, "finishBackup()");
+ return true;
}
// Restore handling
@@ -129,65 +116,66 @@ public class LocalTransport extends IBackupTransport.Stub {
return array;
}
- public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
- if (DEBUG) Log.v(TAG, "getting app set " + token);
- // the available packages are the extant subdirs of mDatadir
- File[] packageDirs = mDataDir.listFiles(mDirFileFilter);
- ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
- for (File dir : packageDirs) {
- try {
- PackageInfo pkg = mPackageManager.getPackageInfo(dir.getName(),
- PackageManager.GET_SIGNATURES);
- if (pkg != null) {
- packages.add(pkg);
- }
- } catch (NameNotFoundException e) {
- // restore set contains data for a package not installed on the
- // phone -- just ignore it.
- }
- }
+ public boolean startRestore(long token, PackageInfo[] packages) {
+ if (DEBUG) Log.v(TAG, "start restore " + token);
+ mRestorePackages = packages;
+ mRestorePackage = -1;
+ return true;
+ }
- if (DEBUG) {
- Log.v(TAG, "Built app set of " + packages.size() + " entries:");
- for (PackageInfo p : packages) {
- Log.v(TAG, " + " + p.packageName);
+ public String nextRestorePackage() {
+ if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+ while (++mRestorePackage < mRestorePackages.length) {
+ String name = mRestorePackages[mRestorePackage].packageName;
+ if (new File(mDataDir, name).isDirectory()) {
+ if (DEBUG) Log.v(TAG, " nextRestorePackage() = " + name);
+ return name;
}
}
- PackageInfo[] result = new PackageInfo[packages.size()];
- return packages.toArray(result);
+ if (DEBUG) Log.v(TAG, " no more packages to restore");
+ return "";
}
- public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor outFd)
- throws android.os.RemoteException {
- if (DEBUG) Log.v(TAG, "getting restore data " + token + " : " + packageInfo.packageName);
- // we only support one hardcoded restore set
- if (token != 0) return -1;
-
- // the data for a given package is at a known location
- File packageDir = new File(mDataDir, packageInfo.packageName);
+ public boolean getRestoreData(ParcelFileDescriptor outFd) {
+ if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+ if (mRestorePackage < 0) throw new IllegalStateException("nextRestorePackage not called");
+ File packageDir = new File(mDataDir, mRestorePackages[mRestorePackage].packageName);
// The restore set is the concatenation of the individual record blobs,
// each of which is a file in the package's directory
File[] blobs = packageDir.listFiles();
- int err = 0;
- if (blobs != null && blobs.length > 0) {
- BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
- try {
- for (File f : blobs) {
- FileInputStream in = new FileInputStream(f);
+ if (blobs == null) {
+ Log.e(TAG, "Error listing directory: " + packageDir);
+ return false; // nextRestorePackage() ensures the dir exists, so this is an error
+ }
+
+ // We expect at least some data if the directory exists in the first place
+ if (DEBUG) Log.v(TAG, " getRestoreData() found " + blobs.length + " key files");
+ BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
+ try {
+ for (File f : blobs) {
+ FileInputStream in = new FileInputStream(f);
+ try {
int size = (int) f.length();
byte[] buf = new byte[size];
in.read(buf);
String key = new String(Base64.decode(f.getName()));
+ if (DEBUG) Log.v(TAG, " ... key=" + key + " size=" + size);
out.writeEntityHeader(key, size);
out.writeEntityData(buf, size);
+ } finally {
+ in.close();
}
- } catch (Exception e) {
- Log.e(TAG, "Unable to read backup records");
- err = -1;
}
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to read backup records", e);
+ return false;
}
- return err;
+ }
+
+ public void finishRestore() {
+ if (DEBUG) Log.v(TAG, "finishRestore()");
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 16a3bad..fc4a9c4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -191,6 +191,8 @@ public final class BatteryStatsImpl extends BatteryStats {
private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
new HashMap<String, KernelWakelockStats>();
+ private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
+
// For debugging
public BatteryStatsImpl() {
mFile = mBackupFile = null;
@@ -714,6 +716,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ boolean isRunningLocked() {
+ return mNesting > 0;
+ }
+
void stopRunningLocked(BatteryStatsImpl stats) {
// Ignore attempt to stop a timer that isn't running
if (mNesting == 0) {
@@ -984,11 +990,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void noteStartGps(int uid) {
- mUidStats.get(uid).noteStartGps();
+ getUidStatsLocked(uid).noteStartGps();
}
public void noteStopGps(int uid) {
- mUidStats.get(uid).noteStopGps();
+ getUidStatsLocked(uid).noteStopGps();
}
public void noteScreenOnLocked() {
@@ -1032,10 +1038,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void noteUserActivityLocked(int uid, int event) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteUserActivityLocked(event);
- }
+ getUidStatsLocked(uid).noteUserActivityLocked(event);
}
public void notePhoneOnLocked() {
@@ -1051,7 +1054,24 @@ public final class BatteryStatsImpl extends BatteryStats {
mPhoneOnTimer.stopRunningLocked(this);
}
}
-
+
+ public void noteAirplaneModeLocked(boolean isAirplaneMode) {
+ final int bin = mPhoneSignalStrengthBin;
+ if (bin >= 0) {
+ if (!isAirplaneMode) {
+ if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
+ mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
+ }
+ } else {
+ for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) {
+ while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
+ mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
+ }
+ }
+ }
+ }
+ }
+
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
// Bin the strength.
int bin;
@@ -1115,16 +1135,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
if (mWifiOnUid != uid) {
if (mWifiOnUid >= 0) {
- Uid u = mUidStats.get(mWifiOnUid);
- if (u != null) {
- u.noteWifiTurnedOffLocked();
- }
+ getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
}
mWifiOnUid = uid;
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteWifiTurnedOnLocked();
- }
+ getUidStatsLocked(uid).noteWifiTurnedOnLocked();
}
}
@@ -1134,10 +1148,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiOnTimer.stopRunningLocked(this);
}
if (mWifiOnUid >= 0) {
- Uid u = mUidStats.get(mWifiOnUid);
- if (u != null) {
- u.noteWifiTurnedOffLocked();
- }
+ getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
mWifiOnUid = -1;
}
}
@@ -1147,10 +1158,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mAudioOn = true;
mAudioOnTimer.startRunningLocked(this);
}
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteAudioTurnedOnLocked();
- }
+ getUidStatsLocked(uid).noteAudioTurnedOnLocked();
}
public void noteAudioOffLocked(int uid) {
@@ -1158,10 +1166,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mAudioOn = false;
mAudioOnTimer.stopRunningLocked(this);
}
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteAudioTurnedOffLocked();
- }
+ getUidStatsLocked(uid).noteAudioTurnedOffLocked();
}
public void noteVideoOnLocked(int uid) {
@@ -1169,10 +1174,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mVideoOn = true;
mVideoOnTimer.startRunningLocked(this);
}
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteVideoTurnedOnLocked();
- }
+ getUidStatsLocked(uid).noteVideoTurnedOnLocked();
}
public void noteVideoOffLocked(int uid) {
@@ -1180,10 +1182,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mVideoOn = false;
mVideoOnTimer.stopRunningLocked(this);
}
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteVideoTurnedOffLocked();
- }
+ getUidStatsLocked(uid).noteVideoTurnedOffLocked();
}
public void noteWifiRunningLocked() {
@@ -1215,45 +1214,27 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void noteFullWifiLockAcquiredLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteFullWifiLockAcquiredLocked();
- }
+ getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked();
}
public void noteFullWifiLockReleasedLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteFullWifiLockReleasedLocked();
- }
+ getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
}
public void noteScanWifiLockAcquiredLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteScanWifiLockAcquiredLocked();
- }
+ getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
}
public void noteScanWifiLockReleasedLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteScanWifiLockReleasedLocked();
- }
+ getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
}
public void noteWifiMulticastEnabledLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteWifiMulticastEnabledLocked();
- }
+ getUidStatsLocked(uid).noteWifiMulticastEnabledLocked();
}
public void noteWifiMulticastDisabledLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u != null) {
- u.noteWifiMulticastDisabledLocked();
- }
+ getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
}
@Override public long getScreenOnTime(long batteryRealtime, int which) {
@@ -2839,7 +2820,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public void removeUidStatsLocked(int uid) {
mUidStats.remove(uid);
}
-
+
/**
* Retrieve the statistics object for a particular process, creating
* if needed.
@@ -2850,6 +2831,26 @@ public final class BatteryStatsImpl extends BatteryStats {
}
/**
+ * Retrieve the statistics object for a particular process, given
+ * the name of the process.
+ * @param name process name
+ * @return the statistics object for the process
+ */
+ public Uid.Proc getProcessStatsLocked(String name) {
+ int uid;
+ if (mUidCache.containsKey(name)) {
+ uid = mUidCache.get(name);
+ } else {
+ // TODO: Find the actual uid from /proc/pid/status. For now use the hashcode of the
+ // process name
+ uid = name.hashCode();
+ mUidCache.put(name, uid);
+ }
+ Uid u = getUidStatsLocked(uid);
+ return u.getProcessStatsLocked(name);
+ }
+
+ /**
* Retrieve the statistics object for a particular process, creating
* if needed.
*/
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index a37bf6e..4a8d8b1 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -219,12 +219,12 @@ public class PowerProfile {
public double getAveragePower(String type, int level) {
if (sPowerMap.containsKey(type)) {
Object data = sPowerMap.get(type);
- if (data instanceof double[]) {
- final double[] values = (double[]) data;
- if (values.length > level) {
+ if (data instanceof Double[]) {
+ final Double[] values = (Double[]) data;
+ if (values.length > level && level >= 0) {
return values[level];
- } else if (values.length < 0) {
- return values[0];
+ } else if (level < 0) {
+ return 0;
} else {
return values[values.length - 1];
}
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
index d2a41f1..74af765 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/core/java/com/google/android/mms/pdu/PduPersister.java
@@ -31,6 +31,7 @@ import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
+import android.provider.Telephony;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Threads;
@@ -54,6 +55,8 @@ import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
+import com.google.android.mms.pdu.EncodedStringValue;
+
/**
* This class is the high-level manager of PDU storage.
*/
@@ -159,6 +162,7 @@ public class PduPersister {
Part.CONTENT_TYPE,
Part.FILENAME,
Part.NAME,
+ Part.TEXT
};
private static final int PART_COLUMN_ID = 0;
@@ -169,6 +173,7 @@ public class PduPersister {
private static final int PART_COLUMN_CONTENT_TYPE = 5;
private static final int PART_COLUMN_FILENAME = 6;
private static final int PART_COLUMN_NAME = 7;
+ private static final int PART_COLUMN_TEXT = 8;
private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP;
// These map are used for convenience in persist() and load().
@@ -414,26 +419,36 @@ public class PduPersister {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
- try {
- is = mContentResolver.openInputStream(partURI);
-
- byte[] buffer = new byte[256];
- int len = is.read(buffer);
- while (len >= 0) {
- baos.write(buffer, 0, len);
- len = is.read(buffer);
- }
- } catch (IOException e) {
- Log.e(TAG, "Failed to load part data", e);
- c.close();
- throw new MmsException(e);
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to close stream", e);
- } // Ignore
+ // Store simple string values directly in the database instead of an
+ // external file. This makes the text searchable and retrieval slightly
+ // faster.
+ if ("text/plain".equals(type) || "application/smil".equals(type)) {
+ String text = c.getString(PART_COLUMN_TEXT);
+ byte [] blob = new EncodedStringValue(text).getTextString();
+ baos.write(blob, 0, blob.length);
+ } else {
+
+ try {
+ is = mContentResolver.openInputStream(partURI);
+
+ byte[] buffer = new byte[256];
+ int len = is.read(buffer);
+ while (len >= 0) {
+ baos.write(buffer, 0, len);
+ len = is.read(buffer);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to load part data", e);
+ c.close();
+ throw new MmsException(e);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to close stream", e);
+ } // Ignore
+ }
}
}
part.setData(baos.toByteArray());
@@ -719,29 +734,37 @@ public class PduPersister {
InputStream is = null;
try {
- os = mContentResolver.openOutputStream(uri);
byte[] data = part.getData();
- if (data == null) {
- Uri dataUri = part.getDataUri();
- if ((dataUri == null) || (dataUri == uri)) {
- Log.w(TAG, "Can't find data for this part.");
- return;
- }
- is = mContentResolver.openInputStream(dataUri);
-
- if (LOCAL_LOGV) {
- Log.v(TAG, "Saving data to: " + uri);
- }
-
- byte[] buffer = new byte[256];
- for (int len = 0; (len = is.read(buffer)) != -1; ) {
- os.write(buffer, 0, len);
+ if ("text/plain".equals(contentType) || "application/smil".equals(contentType)) {
+ ContentValues cv = new ContentValues();
+ cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString());
+ if (mContentResolver.update(uri, cv, null, null) != 1) {
+ throw new MmsException("unable to update " + uri.toString());
}
} else {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Saving data to: " + uri);
+ os = mContentResolver.openOutputStream(uri);
+ if (data == null) {
+ Uri dataUri = part.getDataUri();
+ if ((dataUri == null) || (dataUri == uri)) {
+ Log.w(TAG, "Can't find data for this part.");
+ return;
+ }
+ is = mContentResolver.openInputStream(dataUri);
+
+ if (LOCAL_LOGV) {
+ Log.v(TAG, "Saving data to: " + uri);
+ }
+
+ byte[] buffer = new byte[256];
+ for (int len = 0; (len = is.read(buffer)) != -1; ) {
+ os.write(buffer, 0, len);
+ }
+ } else {
+ if (LOCAL_LOGV) {
+ Log.v(TAG, "Saving data to: " + uri);
+ }
+ os.write(data);
}
- os.write(data);
}
} catch (FileNotFoundException e) {
Log.e(TAG, "Failed to open Input/Output stream.", e);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 251bc84..b5d3b26 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -123,8 +123,7 @@ LOCAL_SRC_FILES:= \
com_android_internal_graphics_NativeUtils.cpp \
android_backup_BackupDataInput.cpp \
android_backup_BackupDataOutput.cpp \
- android_backup_FileBackupHelper.cpp \
- android_backup_RestoreHelperBase.cpp
+ android_backup_FileBackupHelperBase.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1a1ebb4..f8a4df0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -155,8 +155,7 @@ extern int register_android_util_Base64(JNIEnv* env);
extern int register_android_location_GpsLocationProvider(JNIEnv* env);
extern int register_android_backup_BackupDataInput(JNIEnv *env);
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
-extern int register_android_backup_FileBackupHelper(JNIEnv *env);
-extern int register_android_backup_RestoreHelperBase(JNIEnv *env);
+extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -1241,8 +1240,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_location_GpsLocationProvider),
REG_JNI(register_android_backup_BackupDataInput),
REG_JNI(register_android_backup_BackupDataOutput),
- REG_JNI(register_android_backup_FileBackupHelper),
- REG_JNI(register_android_backup_RestoreHelperBase),
+ REG_JNI(register_android_backup_FileBackupHelperBase),
};
/*
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 29d8d3c..957b825 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -28,7 +28,7 @@ typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
static void FromColor_D32(void* dst, const SkColor src[], int width,
int, int) {
SkPMColor* d = (SkPMColor*)dst;
-
+
for (int i = 0; i < width; i++) {
*d++ = SkPreMultiplyColor(*src++);
}
@@ -37,7 +37,7 @@ static void FromColor_D32(void* dst, const SkColor src[], int width,
static void FromColor_D565(void* dst, const SkColor src[], int width,
int x, int y) {
uint16_t* d = (uint16_t*)dst;
-
+
DITHER_565_SCAN(y);
for (int stop = x + width; x < stop; x++) {
SkColor c = *src++;
@@ -49,7 +49,7 @@ static void FromColor_D565(void* dst, const SkColor src[], int width,
static void FromColor_D4444(void* dst, const SkColor src[], int width,
int x, int y) {
SkPMColor16* d = (SkPMColor16*)dst;
-
+
DITHER_4444_SCAN(y);
for (int stop = x + width; x < stop; x++) {
SkPMColor c = SkPreMultiplyColor(*src++);
@@ -80,14 +80,14 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
SkAutoLockPixels alp(dstBitmap);
void* dst = dstBitmap.getPixels();
FromColorProc proc = ChooseFromColorProc(dstBitmap.config());
-
+
if (NULL == dst || NULL == proc) {
return false;
}
-
+
const jint* array = env->GetIntArrayElements(srcColors, NULL);
const SkColor* src = (const SkColor*)array + srcOffset;
-
+
// reset to to actual choice from caller
dst = dstBitmap.getAddr(x, y);
// now copy/convert each scanline
@@ -96,7 +96,7 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
src += srcStride;
dst = (char*)dst + dstBitmap.rowBytes();
}
-
+
env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
JNI_ABORT);
return true;
@@ -212,7 +212,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
doThrowIAE(env, "width and height must be > 0");
return NULL;
}
-
+
if (NULL != jColors) {
size_t n = env->GetArrayLength(jColors);
if (n < SkAbs32(stride) * (size_t)height) {
@@ -222,7 +222,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
SkBitmap bitmap;
-
+
bitmap.setConfig(config, width, height);
if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) {
return NULL;
@@ -232,7 +232,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
GraphicsJNI::SetPixels(env, jColors, offset, stride,
0, 0, width, height, bitmap);
}
-
+
return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), isMutable,
NULL);
}
@@ -245,7 +245,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
if (!src->copyTo(&result, dstConfig, &allocator)) {
return NULL;
}
-
+
return GraphicsJNI::createBitmap(env, new SkBitmap(result), isMutable,
NULL);
}
@@ -324,15 +324,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
SkDebugf("-------- unparcel parcel is NULL\n");
return NULL;
}
-
+
android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
+
const bool isMutable = p->readInt32() != 0;
const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
const int width = p->readInt32();
const int height = p->readInt32();
const int rowBytes = p->readInt32();
-
+
if (SkBitmap::kARGB_8888_Config != config &&
SkBitmap::kRGB_565_Config != config &&
SkBitmap::kARGB_4444_Config != config &&
@@ -355,7 +355,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
ctable = new SkColorTable(src, count);
}
}
-
+
if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) {
ctable->safeUnref();
delete bitmap;
@@ -368,7 +368,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
bitmap->lockPixels();
memcpy(bitmap->getPixels(), p->readInplace(size), size);
bitmap->unlockPixels();
-
+
return GraphicsJNI::createBitmap(env, bitmap, isMutable, NULL);
}
@@ -381,7 +381,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
}
android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
+
p->writeInt32(isMutable);
p->writeInt32(bitmap->config());
p->writeInt32(bitmap->width());
@@ -413,7 +413,7 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
jintArray offsetXY) {
SkIPoint offset;
SkBitmap* dst = new SkBitmap;
-
+
src->extractAlpha(dst, paint, &offset);
if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
int* array = env->GetIntArrayElements(offsetXY, NULL);
@@ -421,7 +421,7 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
array[1] = offset.fY;
env->ReleaseIntArrayElements(offsetXY, array, 0);
}
-
+
return GraphicsJNI::createBitmap(env, dst, true, NULL);
}
@@ -439,7 +439,7 @@ static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
if (NULL == src) {
return 0;
}
-
+
SkColor dst[1];
proc(dst, src, 1, bitmap->getColorTable());
return dst[0];
@@ -449,7 +449,7 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
jintArray pixelArray, int offset, int stride,
int x, int y, int width, int height) {
SkAutoLockPixels alp(*bitmap);
-
+
ToColorProc proc = ChooseToColorProc(*bitmap);
if (NULL == proc) {
return;
@@ -498,7 +498,7 @@ static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
const SkBitmap* bitmap, jobject jbuffer) {
SkAutoLockPixels alp(*bitmap);
const void* src = bitmap->getPixels();
-
+
if (NULL != src) {
android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
@@ -511,7 +511,7 @@ static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
const SkBitmap* bitmap, jobject jbuffer) {
SkAutoLockPixels alp(*bitmap);
void* dst = bitmap->getPixels();
-
+
if (NULL != dst) {
android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
// the java side has already checked that buffer is large enough
@@ -519,6 +519,11 @@ static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
}
}
+static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {
+ bitmap->lockPixels();
+ bitmap->unlockPixels();
+}
+
///////////////////////////////////////////////////////////////////////////////
#include <android_runtime/AndroidRuntime.h>
@@ -552,7 +557,8 @@ static JNINativeMethod gBitmapMethods[] = {
{ "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
(void*)Bitmap_copyPixelsToBuffer },
{ "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
- (void*)Bitmap_copyPixelsFromBuffer }
+ (void*)Bitmap_copyPixelsFromBuffer },
+ { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw }
};
#define kClassPathName "android/graphics/Bitmap"
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 93d68cb..c61b2ed 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -23,6 +23,7 @@
#include "SkGLCanvas.h"
#include "SkGraphics.h"
#include "SkImageRef_GlobalPool.h"
+#include "SkPorterDuff.h"
#include "SkShader.h"
#include "SkTemplates.h"
@@ -324,7 +325,7 @@ public:
static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
jint color, SkPorterDuff::Mode mode) {
- canvas->drawColor(color, mode);
+ canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
}
static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index b6ec4a2..ebfb209 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -21,6 +21,7 @@
#include "SkColorFilter.h"
#include "SkColorMatrixFilter.h"
+#include "SkPorterDuff.h"
namespace android {
@@ -32,8 +33,9 @@ public:
}
static SkColorFilter* CreatePorterDuffFilter(JNIEnv* env, jobject,
- jint srcColor, SkPorterDuff::Mode porterDuffMode) {
- return SkColorFilter::CreatePorterDuffFilter(srcColor, porterDuffMode);
+ jint srcColor, SkPorterDuff::Mode mode) {
+ return SkColorFilter::CreateModeFilter(srcColor,
+ SkPorterDuff::ToXfermodeMode(mode));
}
static SkColorFilter* CreateLightingFilter(JNIEnv* env, jobject,
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index 6362439..d02590e 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -87,11 +87,26 @@ writeEntityData_native(JNIEnv* env, jobject clazz, int w, jbyteArray data, int s
return err;
}
+static void
+setKeyPrefix_native(JNIEnv* env, jobject clazz, int w, jstring keyPrefixObj)
+{
+ int err;
+ BackupDataWriter* writer = (BackupDataWriter*)w;
+
+ const char* keyPrefixUTF = env->GetStringUTFChars(keyPrefixObj, NULL);
+ String8 keyPrefix(keyPrefixUTF ? keyPrefixUTF : "");
+
+ writer->SetKeyPrefix(keyPrefix);
+
+ env->ReleaseStringUTFChars(keyPrefixObj, keyPrefixUTF);
+}
+
static const JNINativeMethod g_methods[] = {
{ "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
{ "dtor", "(I)V", (void*)dtor_native },
{ "writeEntityHeader_native", "(ILjava/lang/String;I)I", (void*)writeEntityHeader_native },
{ "writeEntityData_native", "(I[BI)I", (void*)writeEntityData_native },
+ { "setKeyPrefix_native", "(ILjava/lang/String;)V", (void*)setKeyPrefix_native },
};
int register_android_backup_BackupDataOutput(JNIEnv* env)
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp
index 418db8a..8225a36 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelperBase.cpp
@@ -29,6 +29,18 @@ namespace android
static jfieldID s_descriptorField = 0;
static int
+ctor(JNIEnv* env, jobject clazz)
+{
+ return (int)new RestoreHelperBase();
+}
+
+static void
+dtor(JNIEnv* env, jobject clazz, jint ptr)
+{
+ delete (RestoreHelperBase*)ptr;
+}
+
+static int
performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
jobject newState, jobjectArray files, jobjectArray keys)
{
@@ -66,13 +78,48 @@ performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
return err;
}
+
+static int
+writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
+{
+ int err;
+ RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+ BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
+ char const* filename;
+
+ filename = env->GetStringUTFChars(filenameObj, NULL);
+
+ err = restore->WriteFile(String8(filename), reader);
+
+ env->ReleaseStringUTFChars(filenameObj, filename);
+
+ return err;
+}
+
+static int
+writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
+{
+ int err;
+
+ RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+ int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+
+ err = restore->WriteSnapshot(fd);
+
+ return err;
+}
+
static const JNINativeMethod g_methods[] = {
+ { "ctor", "()I", (void*)ctor },
+ { "dtor", "(I)V", (void*)dtor },
{ "performBackup_native",
"(Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;[Ljava/lang/String;)I",
(void*)performBackup_native },
+ { "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
+ { "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
};
-int register_android_backup_FileBackupHelper(JNIEnv* env)
+int register_android_backup_FileBackupHelperBase(JNIEnv* env)
{
jclass clazz;
@@ -82,7 +129,7 @@ int register_android_backup_FileBackupHelper(JNIEnv* env)
LOG_FATAL_IF(s_descriptorField == NULL,
"Unable to find descriptor field in java.io.FileDescriptor");
- return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelper",
+ return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelperBase",
g_methods, NELEM(g_methods));
}
diff --git a/core/jni/android_backup_RestoreHelperBase.cpp b/core/jni/android_backup_RestoreHelperBase.cpp
deleted file mode 100644
index 3173420..0000000
--- a/core/jni/android_backup_RestoreHelperBase.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "FileBackupHelper_native"
-#include <utils/Log.h>
-
-#include "JNIHelp.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <utils/BackupHelpers.h>
-
-namespace android
-{
-
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
-static int
-ctor(JNIEnv* env, jobject clazz)
-{
- return (int)new RestoreHelperBase();
-}
-
-static void
-dtor(JNIEnv* env, jobject clazz, jint ptr)
-{
- delete (RestoreHelperBase*)ptr;
-}
-
-static int
-writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
-{
- int err;
- RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
- BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
- char const* filename;
-
- filename = env->GetStringUTFChars(filenameObj, NULL);
-
- err = restore->WriteFile(String8(filename), reader);
-
- env->ReleaseStringUTFChars(filenameObj, filename);
-
- return err;
-}
-
-static int
-writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
-{
- int err;
-
- RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
- int fd = env->GetIntField(fileDescriptor, s_descriptorField);
-
- err = restore->WriteSnapshot(fd);
-
- return err;
-}
-
-static const JNINativeMethod g_methods[] = {
- { "ctor", "()I", (void*)ctor },
- { "dtor", "(I)V", (void*)dtor },
- { "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
- { "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
-};
-
-int register_android_backup_RestoreHelperBase(JNIEnv* env)
-{
- jclass clazz;
-
- clazz = env->FindClass("java/io/FileDescriptor");
- LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
- s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
- LOG_FATAL_IF(s_descriptorField == NULL,
- "Unable to find descriptor field in java.io.FileDescriptor");
-
- return AndroidRuntime::registerNativeMethods(env, "android/backup/RestoreHelperBase",
- g_methods, NELEM(g_methods));
-}
-
-}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 217e649..c7cc9b3 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -53,19 +53,33 @@ struct fields_t {
static fields_t fields;
static Mutex sLock;
-struct camera_context_t {
+// provides persistent context for calls from native code to Java
+class JNICameraContext: public CameraListener
+{
+public:
+ JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera);
+ ~JNICameraContext() { release(); }
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
+ sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
+ void release();
+
+private:
+ void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
+
jobject mCameraJObjectWeak; // weak reference to java object
jclass mCameraJClass; // strong reference to java class
sp<Camera> mCamera; // strong reference to native object
+ Mutex mLock;
};
-sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, camera_context_t** pContext)
+sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
{
sp<Camera> camera;
Mutex::Autolock _l(sLock);
- camera_context_t* context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+ JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
if (context != NULL) {
- camera = context->mCamera;
+ camera = context->getCamera();
}
LOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
if (camera == 0) {
@@ -76,30 +90,140 @@ sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, camera_context_t** pCont
return camera;
}
-static void err_callback(status_t err, void *cookie)
+JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
{
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
- if ((context == NULL) || (context->mCamera == 0)) return;
+ mCameraJObjectWeak = env->NewGlobalRef(weak_this);
+ mCameraJClass = (jclass)env->NewGlobalRef(clazz);
+ mCamera = camera;
+}
- LOGV("err_callback: context=%p, camera=%p", context, context->mCamera.get());
+void JNICameraContext::release()
+{
+ LOGV("release");
+ Mutex::Autolock _l(mLock);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
- int error;
- switch (err) {
- case DEAD_OBJECT:
- error = kCameraErrorMediaServer;
+ if (mCameraJObjectWeak != NULL) {
+ env->DeleteGlobalRef(mCameraJObjectWeak);
+ mCameraJObjectWeak = NULL;
+ }
+ if (mCameraJClass != NULL) {
+ env->DeleteGlobalRef(mCameraJClass);
+ mCameraJClass = NULL;
+ }
+ mCamera.clear();
+}
+
+void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+ LOGV("notify");
+
+ // VM pointer will be NULL if object is released
+ Mutex::Autolock _l(mLock);
+ if (mCameraJObjectWeak == NULL) {
+ LOGW("callback on dead camera object");
+ return;
+ }
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ // parse message
+ switch (msgType) {
+ case CAMERA_MSG_ERROR:
+ LOGV("errorCallback");
+ int error;
+ switch (ext1) {
+ case DEAD_OBJECT:
+ error = kCameraErrorMediaServer;
+ break;
+ default:
+ error = kCameraErrorUnknown;
+ break;
+ }
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, kErrorCallback, error, 0, NULL);
+ break;
+ case CAMERA_MSG_FOCUS:
+ LOGV("autoFocusCallback");
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, kAutoFocusCallback, ext1, 0, NULL);
+ break;
+ case CAMERA_MSG_SHUTTER:
+ LOGV("shutterCallback");
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, kShutterCallback, 0, 0, NULL);
break;
default:
- error = kCameraErrorUnknown;
+ LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2);
break;
}
+}
+
+void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
+{
+ jbyteArray obj = NULL;
+
+ // allocate Java byte array and copy data
+ if (dataPtr != NULL) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
+ LOGV("postData: off=%d, size=%d", offset, size);
+ uint8_t *heapBase = (uint8_t*)heap->base();
+
+ if (heapBase != NULL) {
+ uint8_t *data = heapBase + offset;
+ obj = env->NewByteArray(size);
+ if (obj == NULL) {
+ LOGE("Couldn't allocate byte array for JPEG data");
+ env->ExceptionClear();
+ } else {
+ jbyte *bytes = env->GetByteArrayElements(obj, NULL);
+ memcpy(bytes, data, size);
+ env->ReleaseByteArrayElements(obj, bytes, 0);
+
+ }
+ } else {
+ LOGE("image heap is NULL");
+ }
+ }
+ // post image data to Java
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, 0, 0, obj);
+ if (obj) {
+ env->DeleteLocalRef(obj);
+ }
+}
+
+void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
+{
+ // VM pointer will be NULL if object is released
+ Mutex::Autolock _l(mLock);
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("err_callback on dead VM");
- return;
+
+ // return data based on callback type
+ switch(msgType) {
+ case CAMERA_MSG_PREVIEW_FRAME:
+ LOGV("previewCallback");
+ copyAndPost(env, dataPtr, kPreviewCallback);
+ break;
+ case CAMERA_MSG_VIDEO_FRAME:
+ LOGV("recordingCallback");
+ break;
+ case CAMERA_MSG_RAW_IMAGE:
+ LOGV("rawCallback");
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, kRawCallback, 0, 0, NULL);
+ break;
+ case CAMERA_MSG_COMPRESSED_IMAGE:
+ LOGV("jpegCallback");
+ copyAndPost(env, dataPtr, kJpegCallback);
+ break;
+ default:
+ LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+ break;
}
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kErrorCallback, error, 0, NULL);
+
}
// connect to camera service
@@ -127,19 +251,12 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
- camera_context_t* context = new camera_context_t;
- context->mCameraJObjectWeak = env->NewGlobalRef(weak_this);
- context->mCameraJClass = (jclass)env->NewGlobalRef(clazz);
- context->mCamera = camera;
+ sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
+ context->incStrong(thiz);
+ camera->setListener(context);
// save context in opaque field
- env->SetIntField(thiz, fields.context, (int)context);
-
- LOGV("native_setup: mCameraJObjectWeak=%x, camera_obj=%x, context=%p",
- (int)context->mCameraJObjectWeak, (int)thiz, context);
-
- // set error callback
- camera->setErrorCallback(err_callback, context);
+ env->SetIntField(thiz, fields.context, (int)context.get());
}
// disconnect from camera service
@@ -148,11 +265,11 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj
// finalizer is invoked later.
static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
{
- camera_context_t* context = NULL;
+ JNICameraContext* context = NULL;
sp<Camera> camera;
{
Mutex::Autolock _l(sLock);
- context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+ context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
// Make sure we do not attempt to callback on a deleted Java object.
env->SetIntField(thiz, fields.context, 0);
@@ -160,21 +277,18 @@ static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
// clean up if release has not been called before
if (context != NULL) {
- camera = context->mCamera;
- context->mCamera.clear();
+ camera = context->getCamera();
+ context->release();
LOGV("native_release: context=%p camera=%p", context, camera.get());
// clear callbacks
if (camera != NULL) {
- camera->setPreviewCallback(NULL, NULL, FRAME_CALLBACK_FLAG_NOOP);
- camera->setErrorCallback(NULL, NULL);
+ camera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
camera->disconnect();
- env->DeleteGlobalRef(context->mCameraJObjectWeak);
- env->DeleteGlobalRef(context->mCameraJClass);
}
// remove context to prevent further Java access
- delete context;
+ context->decStrong(thiz);
}
}
@@ -190,48 +304,6 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz,
}
}
-static void preview_callback(const sp<IMemory>& mem, void *cookie)
-{
- LOGV("preview_callback");
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("preview_callback on dead VM");
- return;
- }
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
- if ((context == NULL) || (context->mCamera == 0)) {
- LOGW("context or camera is NULL in preview_callback");
- return;
- }
- LOGV("native_release: context=%p camera=%p", context, context->mCamera.get());
-
- int arg1 = 0, arg2 = 0;
- jobject obj = NULL;
-
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
- uint8_t *data = ((uint8_t *)heap->base()) + offset;
-
- jbyteArray array = env->NewByteArray(size);
- if (array == NULL) {
- LOGE("Couldn't allocate byte array for YUV data");
- env->ExceptionClear();
- return;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, data, size);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- obj = array;
-
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kPreviewCallback, arg1, arg2, obj);
- env->DeleteLocalRef(array);
-}
-
static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
LOGV("startPreview");
@@ -267,7 +339,7 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
// Important: Only install preview_callback if the Java code has called
// setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
// each preview frame for nothing.
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
@@ -277,130 +349,32 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
} else {
callback_flag = FRAME_CALLBACK_FLAG_NOOP;
}
- camera->setPreviewCallback(installed ? preview_callback : NULL, context, callback_flag);
-}
-
-static void autofocus_callback_impl(bool success, void *cookie)
-{
- LOGV("autoFocusCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("autofocus_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kAutoFocusCallback, success, 0, NULL);
+ camera->setPreviewCallbackFlags(callback_flag);
}
static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz)
{
LOGV("autoFocus");
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> c = get_native_camera(env, thiz, &context);
if (c == 0) return;
- c->setAutoFocusCallback(autofocus_callback_impl, context);
if (c->autoFocus() != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException", "autoFocus failed");
}
}
-static void jpeg_callback(const sp<IMemory>& mem, void *cookie)
-{
- LOGV("jpegCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("jpeg`_callback on dead VM");
- return;
- }
- int arg1 = 0, arg2 = 0;
- jobject obj = NULL;
-
- if (mem == NULL) {
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, NULL);
- return;
- }
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- LOGV("jpeg_callback: mem off=%d, size=%d", offset, size);
-
- uint8_t *heap_base = (uint8_t *)heap->base();
- if (heap_base == NULL) {
- LOGE("YUV heap is NULL");
- return;
- }
-
- uint8_t *data = heap_base + offset;
-
- jbyteArray array = env->NewByteArray(size);
- if (array == NULL) {
- LOGE("Couldn't allocate byte array for JPEG data");
- env->ExceptionClear();
- return;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, data, size);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- obj = array;
-
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, obj);
- env->DeleteLocalRef(array);
-}
-
-static void shutter_callback_impl(void *cookie)
-{
- LOGV("shutterCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("shutter_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kShutterCallback, 0, 0, NULL);
-}
-
-static void raw_callback(const sp<IMemory>& mem __attribute__((unused)),
- void *cookie)
-{
- LOGV("rawCallback");
- camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (env == NULL) {
- LOGE("raw_callback on dead VM");
- return;
- }
- env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
- context->mCameraJObjectWeak, kRawCallback, 0, 0, NULL);
-}
-
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz)
{
LOGV("takePicture");
- camera_context_t* context;
+ JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
- camera->setShutterCallback(shutter_callback_impl, context);
- camera->setRawCallback(raw_callback, context);
- camera->setJpegCallback(jpeg_callback, context);
if (camera->takePicture() != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
return;
}
-
- return;
}
static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c1017d4..0c90769 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -175,6 +175,22 @@
android:label="@string/permlab_writeDictionary"
android:description="@string/permdesc_writeDictionary" />
+ <!-- Allows an application to read (but not write) the user's
+ browsing history and bookmarks. -->
+ <permission android:name="android.permission.READ_HISTORY_BOOKMARKS"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:label="@string/permlab_readHistoryBookmarks"
+ android:description="@string/permdesc_readHistoryBookmarks"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write (but not read) the user's
+ browsing history and bookmarks. -->
+ <permission android:name="android.permission.WRITE_HISTORY_BOOKMARKS"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:label="@string/permlab_writeHistoryBookmarks"
+ android:description="@string/permdesc_writeHistoryBookmarks"
+ android:protectionLevel="dangerous" />
+
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
<!-- ======================================= -->
diff --git a/core/res/res/drawable/search_dropdown_background.9.png b/core/res/res/drawable/search_dropdown_background.9.png
index a6923b7..804260a 100755..100644
--- a/core/res/res/drawable/search_dropdown_background.9.png
+++ b/core/res/res/drawable/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable/search_dropdown_background_apps.9.png b/core/res/res/drawable/search_dropdown_background_apps.9.png
deleted file mode 100644
index 804260a..0000000
--- a/core/res/res/drawable/search_dropdown_background_apps.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 7b7f8a6..13e66aa 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -73,8 +73,10 @@
android:paddingRight="6dip"
android:drawablePadding="2dip"
android:singleLine="true"
+ android:ellipsize="end"
android:inputType="text|textAutoComplete"
android:dropDownWidth="fill_parent"
+ android:dropDownHeight="fill_parent"
android:dropDownAnchor="@id/search_plate"
android:dropDownVerticalOffset="-9dip"
android:popupBackground="@android:drawable/search_dropdown_background"
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
index cda072a..b8b50cc 100644
--- a/core/res/res/values-bg-rBG/donottranslate-cldr.xml
+++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
@@ -107,19 +107,19 @@
<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="month_year">%B %Y</string>
<string name="abbrev_month_day">%-e %b</string>
- <string name="abbrev_month">%-b</string>
- <string name="abbrev_month_year">%Y %b</string>
+ <string name="abbrev_month">%b</string>
+ <string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
<string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
<string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s, %1$s - %8$s.%7$s, %6$s</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s, %1$s - %8$s.%7$s.%9$s, %6$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
- <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s, %1$s - %10$s %8$s.%7$s.%9$s, %6$s</string>
+ <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s.%2$s, %1$s - %10$s %8$s.%7$s, %6$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string>
<string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string>
@@ -135,9 +135,9 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s, %1$s - %8$s %7$s %9$s, %6$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
<string name="same_month_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
index e933f20..41f5dea 100644
--- a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
+++ b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
index e933f20..41f5dea 100644
--- a/core/res/res/values-cs/donottranslate-cldr.xml
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-da-rDK/donottranslate-cldr.xml b/core/res/res/values-da-rDK/donottranslate-cldr.xml
index 8cef5b2..2d0db93 100644
--- a/core/res/res/values-da-rDK/donottranslate-cldr.xml
+++ b/core/res/res/values-da-rDK/donottranslate-cldr.xml
@@ -106,7 +106,7 @@
<string name="time_date">%1$s %3$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">%B</string>
<string name="month_year">%B %Y</string>
<string name="abbrev_month_day">%-e. %b</string>
<string name="abbrev_month">%b</string>
diff --git a/core/res/res/values-de-rAT/donottranslate-cldr.xml b/core/res/res/values-de-rAT/donottranslate-cldr.xml
index 559e1ee..27624a3 100644
--- a/core/res/res/values-de-rAT/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rAT/donottranslate-cldr.xml
@@ -2,10 +2,43 @@
<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_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">Jänner</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">Jän</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>
@@ -75,7 +108,7 @@
<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_day">%d. %b</string>
<string name="abbrev_month">%-b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
@@ -84,29 +117,29 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
- <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
<string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
- <string name="time_wday_date">%1$s %2$s %3$s</string>
- <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday_date">%1$s %2$s, %3$s</string>
+ <string name="wday_date">%2$s, %3$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
diff --git a/core/res/res/values-de-rCH/donottranslate-cldr.xml b/core/res/res/values-de-rCH/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rCH/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de-rDE/donottranslate-cldr.xml b/core/res/res/values-de-rDE/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rDE/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rDE/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de-rLI/donottranslate-cldr.xml b/core/res/res/values-de-rLI/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rLI/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rLI/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de/donottranslate-cldr.xml
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml
index 5d1a8f6..9811b68 100644
--- a/core/res/res/values-en-rAU/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%-e %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
- <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s/%2$s/%4$s, %5$s - %6$s, %8$s/%7$s/%9$s, %10$s</string>
+ <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
@@ -128,18 +128,18 @@
<string name="wday_date">%2$s, %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
<string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml
index 5d7300e..1e250c7 100644
--- a/core/res/res/values-en-rCA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s - %6$s, %7$s-%8$s</string>
<string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s - %6$s, %9$s-%7$s-%8$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
- <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %4$s-%2$s-%3$s, %5$s - %6$s, %9$s-%7$s-%8$s, %10$s</string>
+ <string name="numeric_md1_time1_md2_time2">%2$s-%3$s, %5$s - %7$s-%8$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s-%3$s, %5$s - %6$s, %7$s-%8$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%4$s-%2$s-%3$s, %5$s - %9$s-%7$s-%8$s, %10$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
index b115c6e..0e3e035 100644
--- a/core/res/res/values-en-rGB/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%-e %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -121,11 +121,11 @@
<string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
- <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
<string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
- <string name="time_wday_date">%1$s, %2$s, %3$s</string>
- <string name="wday_date">%2$s, %3$s</string>
+ <string name="time_wday_date">%1$s, %2$s %3$s</string>
+ <string name="wday_date">%2$s %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
<string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
@@ -135,9 +135,9 @@
<string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
<string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml
index 15fc8e8..2e59dcf 100644
--- a/core/res/res/values-en-rIE/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%-e %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -121,25 +121,25 @@
<string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
- <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
<string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
- <string name="time_wday_date">%1$s, %2$s, %3$s</string>
- <string name="wday_date">%2$s, %3$s</string>
+ <string name="time_wday_date">%1$s, %2$s %3$s</string>
+ <string name="wday_date">%2$s %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
<string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml
index 2507ee8..e39a59a 100644
--- a/core/res/res/values-en-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%-e %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -117,29 +117,29 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
- <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s/%2$s/%4$s, %5$s - %6$s %8$s/%7$s/%9$s, %10$s</string>
+ <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s %3$s/%2$s, %5$s - %6$s %8$s/%7$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
- <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
<string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
- <string name="time_wday_date">%1$s, %2$s, %3$s</string>
- <string name="wday_date">%2$s, %3$s</string>
+ <string name="time_wday_date">%1$s, %2$s %3$s</string>
+ <string name="wday_date">%2$s %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
<string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
index 07d4fe8..3a8b50b 100644
--- a/core/res/res/values-en-rNZ/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%-e %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s/%2$s/%4$s, %5$s - %6$s, %8$s/%7$s/%9$s, %10$s</string>
<string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
@@ -128,18 +128,18 @@
<string name="wday_date">%2$s, %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
<string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml
index 9e8681b..2e2d608 100644
--- a/core/res/res/values-en-rZA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
<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_day">%d %b</string>
+ <string name="abbrev_month">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
@@ -117,29 +117,29 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s - %6$s %7$s/%8$s</string>
<string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s - %9$s/%7$s/%8$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %4$s/%2$s/%3$s - %6$s %9$s/%7$s/%8$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %4$s/%2$s/%3$s, %5$s - %6$s %9$s/%7$s/%8$s, %10$s</string>
<string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s %2$s/%3$s, %5$s - %6$s %7$s/%8$s, %10$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%4$s/%2$s/%3$s, %5$s - %9$s/%7$s/%8$s, %10$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
- <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
<string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
- <string name="time_wday_date">%1$s, %2$s, %3$s</string>
- <string name="wday_date">%2$s, %3$s</string>
+ <string name="time_wday_date">%1$s, %2$s %3$s</string>
+ <string name="wday_date">%2$s %3$s</string>
<string name="time_wday">%1$s, %2$s</string>
<string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%2$s %3$s, %5$s - %7$s %8$s, %10$s</string>
<string name="same_month_md1_time1_md2_time2">%2$s %3$s, %5$s - %7$s %8$s, %10$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
index 24923c3..d6d8954 100644
--- a/core/res/res/values-es-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -108,18 +108,18 @@
<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>
+ <string name="abbrev_month_day">%-e de %b</string>
+ <string name="abbrev_month">%b</string>
+ <string name="abbrev_month_year">%b de %Y</string>
<string name="time1_time2">%1$s a el %2$s</string>
<string name="date1_date2">%2$s a el %5$s</string>
<string name="numeric_md1_md2">%2$s/%3$s - %7$s/%8$s</string>
<string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s - %6$s %7$s/%8$s</string>
<string name="numeric_mdy1_mdy2">%2$s/%3$s/%4$s - %7$s/%8$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %2$s/%3$s/%4$s - %6$s %7$s/%8$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s a el %10$s %6$s %8$s/%7$s/%9$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %2$s/%3$s/%4$s a el %10$s %6$s %7$s/%8$s/%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %2$s/%3$s a el %10$s %7$s/%8$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s-%2$s a el %10$s %6$s, %8$s-%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s/%3$s a el %10$s %6$s %7$s/%8$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %2$s/%3$s/%4$s a el %10$s %7$s/%8$s/%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s a el %6$s %4$s %5$s</string>
<string name="wday1_date1_wday2_date2">%1$s %2$s a el %4$s %5$s</string>
@@ -128,18 +128,18 @@
<string name="wday_date">%2$s %3$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%3$s de %2$s a el %8$s de %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s a el %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s de %2$s a el %6$s %8$s de %7$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s a el %10$s %8$s de %7$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s a el %10$s %8$s de %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s a el %10$s %6$s %8$s %7$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s a el %10$s %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s de %2$s a el %10$s %6$s %8$s de %7$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s de %2$s a el %10$s %6$s %8$s de %7$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s a el %10$s %8$s de %7$s de %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s a el %10$s %8$s de %7$s de %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s a el %10$s %6$s, %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s a el %10$s %6$s, %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s a el %6$s, %8$s %7$s %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s de %2$s de %4$s a el %10$s %6$s %8$s de %7$s de %9$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s de %2$s de %4$s a el %10$s %6$s %8$s de %7$s de %9$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s de %4$s a el %6$s %8$s de %7$s de %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s de %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s a el %6$s %8$s %7$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s de %2$s a el %6$s %8$s de %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s de %2$s al %8$s de %7$s de %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s al %6$s %8$s de %7$s de %9$s</string>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
index dd12e57..df3866e 100644
--- a/core/res/res/values-fi-rFI/donottranslate-cldr.xml
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -106,7 +106,7 @@
<string name="time_date">%1$s %3$s</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">%-b</string>
<string name="month_year">%-B %Y</string>
<string name="abbrev_month_day">%-e. %b</string>
<string name="abbrev_month">%-b</string>
diff --git a/core/res/res/values-fr-rBE/donottranslate-cldr.xml b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
index ea4ecf2..e190837 100644
--- a/core/res/res/values-fr-rBE/donottranslate-cldr.xml
+++ b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">du %1$s au %2$s</string>
<string name="date1_date2">du %2$s au %5$s</string>
diff --git a/core/res/res/values-fr-rCH/donottranslate-cldr.xml b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
index 0a9835f..48db6b8 100644
--- a/core/res/res/values-fr-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">du %1$s au %2$s</string>
<string name="date1_date2">du %2$s au %5$s</string>
@@ -117,29 +117,29 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s/%2$s/%4$s au %10$s %6$s %8$s/%7$s/%9$s</string>
- <string name="numeric_md1_time1_md2_time2">du %5$s %3$s/%2$s au %10$s %8$s/%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s/%2$s au %10$s %6$s %8$s/%7$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s.%2$s.%4$s au %10$s %6$s, %8$s.%7$s.%9$s</string>
+ <string name="numeric_md1_time1_md2_time2">du %5$s %3$s.%2$s au %10$s %8$s.%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s.%2$s au %10$s %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">du %5$s %3$s.%2$s.%4$s au %10$s %8$s.%7$s.%9$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s %2$s au %6$s %4$s %5$s</string>
- <string name="wday1_date1_wday2_date2">du %1$s %2$s au %4$s %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s, %2$s au %6$s %4$s, %5$s</string>
+ <string name="wday1_date1_wday2_date2">du %1$s, %2$s au %4$s, %5$s</string>
<string name="date1_time1_date2_time2">du %3$s %2$s au %6$s %5$s</string>
- <string name="time_wday_date">%1$s %2$s %3$s</string>
- <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday_date">%1$s %2$s, %3$s</string>
+ <string name="wday_date">%2$s, %3$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">du %3$s %2$s au %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
<string name="same_month_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s %4$s au %6$s %8$s %7$s %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s, %3$s %2$s %4$s au %6$s, %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s au %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s au %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
index 03da515..2a19da4 100644
--- a/core/res/res/values-hi-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
@@ -107,7 +107,7 @@
<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="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>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
index b56f520..08a70b8 100644
--- a/core/res/res/values-hu-rHU/donottranslate-cldr.xml
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -107,17 +107,17 @@
<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="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>
+ <string name="abbrev_month_year">%Y. %b</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
<string name="numeric_md1_md2">%2$s.%3$s. - %7$s.%8$s.</string>
<string name="numeric_wday1_md1_wday2_md2">%2$s.%3$s., %1$s - %7$s.%8$s., %6$s</string>
<string name="numeric_mdy1_mdy2">%4$s.%2$s.%3$s. - %9$s.%7$s.%8$s.</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%4$s.%2$s.%3$s., %1$s - %9$s.%7$s.%8$s., %6$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s.%2$s.%3$s., %1$s - %10$s %9$s.%7$s.%8$s., %6$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. - %10$s %7$s. %8$s.</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s., %1$s - %10$s %7$s. %8$s., %6$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s.%2$s.%3$s. - %10$s %9$s.%7$s.%8$s.</string>
@@ -128,18 +128,18 @@
<string name="wday_date">%3$s, %2$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%2$s %3$s. - %7$s %8$s.</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
<string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s. %2$s %3$s., %1$s - %9$s. %7$s %8$s., %6$s</string>
<string name="same_month_md1_md2">%2$s %3$s-%8$s.</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
<string name="same_year_mdy1_mdy2">%9$s. %2$s %3$s. - %7$s %8$s.</string>
<string name="same_month_mdy1_mdy2">%9$s. %2$s %3$s-%8$s.</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%9$s. %2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml
index 22860a7..6adec84 100644
--- a/core/res/res/values-id-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-id-rID/donottranslate-cldr.xml
@@ -107,7 +107,7 @@
<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="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>
diff --git a/core/res/res/values-it-rCH/donottranslate-cldr.xml b/core/res/res/values-it-rCH/donottranslate-cldr.xml
index 6d9b550..12170d6 100644
--- a/core/res/res/values-it-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-it-rCH/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
<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_standalone_august">Agosto</string>
+ <string name="month_long_standalone_september">Settembre</string>
+ <string name="month_long_standalone_october">Ottobre</string>
+ <string name="month_long_standalone_november">Novembre</string>
+ <string name="month_long_standalone_december">Dicembre</string>
<string name="month_long_january">gennaio</string>
<string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
<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_july">luglio</string>
<string name="month_long_august">agosto</string>
<string name="month_long_september">settembre</string>
<string name="month_long_october">ottobre</string>
@@ -112,29 +117,29 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
- <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
+ <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s - %10$s %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
- <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
<string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
- <string name="time_wday_date">%1$s %2$s %3$s</string>
- <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday_date">%1$s %2$s, %3$s</string>
+ <string name="wday_date">%2$s, %3$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
<string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
<string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-it-rIT/donottranslate-cldr.xml b/core/res/res/values-it-rIT/donottranslate-cldr.xml
index 1bf7992..2178bbe 100644
--- a/core/res/res/values-it-rIT/donottranslate-cldr.xml
+++ b/core/res/res/values-it-rIT/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
<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_standalone_august">Agosto</string>
+ <string name="month_long_standalone_september">Settembre</string>
+ <string name="month_long_standalone_october">Ottobre</string>
+ <string name="month_long_standalone_november">Novembre</string>
+ <string name="month_long_standalone_december">Dicembre</string>
<string name="month_long_january">gennaio</string>
<string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
<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_july">luglio</string>
<string name="month_long_august">agosto</string>
<string name="month_long_september">settembre</string>
<string name="month_long_october">ottobre</string>
@@ -112,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
index 1bf7992..2178bbe 100644
--- a/core/res/res/values-it/donottranslate-cldr.xml
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
<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_standalone_august">Agosto</string>
+ <string name="month_long_standalone_september">Settembre</string>
+ <string name="month_long_standalone_october">Ottobre</string>
+ <string name="month_long_standalone_november">Novembre</string>
+ <string name="month_long_standalone_december">Dicembre</string>
<string name="month_long_january">gennaio</string>
<string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
<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_july">luglio</string>
<string name="month_long_august">agosto</string>
<string name="month_long_september">settembre</string>
<string name="month_long_october">ottobre</string>
@@ -112,7 +117,7 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
<string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
diff --git a/core/res/res/values-ja-rJP/donottranslate-cldr.xml b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
index 10f2f79..d2510f6 100644
--- a/core/res/res/values-ja-rJP/donottranslate-cldr.xml
+++ b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
- <string name="same_month_md1_md2">%2$s月%3$s日~%8$s日</string>
+ <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
- <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s月%8$s日</string>
+ <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
<string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s月%8$s日(%6$s)</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
index 10f2f79..d2510f6 100644
--- a/core/res/res/values-ja/donottranslate-cldr.xml
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
- <string name="same_month_md1_md2">%2$s月%3$s日~%8$s日</string>
+ <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
- <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s月%8$s日</string>
+ <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
<string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s月%8$s日(%6$s)</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values-ko-rKR/donottranslate-cldr.xml b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
index 45ca90a..57cd356 100644
--- a/core/res/res/values-ko-rKR/donottranslate-cldr.xml
+++ b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
@@ -126,10 +126,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
- <string name="same_month_md1_md2">%2$s월 %3$s일 ~ %8$s일</string>
+ <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
- <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s월 %8$s일</string>
+ <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
<string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s월 %8$s일 %6$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 45ca90a..57cd356 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -126,10 +126,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
- <string name="same_month_md1_md2">%2$s월 %3$s일 ~ %8$s일</string>
+ <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
- <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s월 %8$s일</string>
+ <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
<string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s월 %8$s일 %6$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
index 636a180..20d58e0 100644
--- a/core/res/res/values-lt-rLT/donottranslate-cldr.xml
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -108,38 +108,38 @@
<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>
+ <string name="abbrev_month_day">%b %-e d.</string>
+ <string name="abbrev_month">%b</string>
+ <string name="abbrev_month_year">%Y m. %b</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
<string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string>
<string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s - %7$s-%8$s%6$s</string>
<string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s - %9$s-%7$s-%8$s%6$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s-%2$s-%3$s%1$s - %10$s %9$s-%7$s-%8$s%6$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s - %10$s %7$s-%8$s%6$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s - %10$s %9$s-%7$s-%8$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
- <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s - %6$s %5$s%4$s</string>
+ <string name="wday1_date1_wday2_date2">%2$s%1$s - %5$s%4$s</string>
<string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
- <string name="time_wday_date">%1$s %2$s %3$s</string>
- <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday_date">%1$s %3$s%2$s</string>
+ <string name="wday_date">%3$s%2$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
<string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s m. %2$s %3$s d.,%1$s - %9$s m. %7$s %8$s d.,%6$s</string>
<string name="same_month_md1_md2">%2$s %3$s d.-%8$s d.</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
<string name="same_year_mdy1_mdy2">%9$s m. %2$s %3$s d. - %7$s %8$s d.</string>
<string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s d.-%8$s d.</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d.,%1$s - %7$s %8$s d.,%6$s</string>
diff --git a/core/res/res/values-nl-rBE/donottranslate-cldr.xml b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
index 5b4cbf7..680a392 100644
--- a/core/res/res/values-nl-rBE/donottranslate-cldr.xml
+++ b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s-%2$s-%4$s - %10$s %6$s %8$s-%7$s-%9$s</string>
- <string name="numeric_md1_time1_md2_time2">%5$s %3$s-%2$s - %10$s %8$s-%7$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s-%2$s - %10$s %6$s %8$s-%7$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s - %10$s %6$s %8$s/%7$s/%9$s</string>
+ <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
<string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
index be0fdb7..f38a2d0 100644
--- a/core/res/res/values-pt-rPT/donottranslate-cldr.xml
+++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b de %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
index 2b3c6d9..16239df 100644
--- a/core/res/res/values-sk-rSK/donottranslate-cldr.xml
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
index 2b2b9c3..b4ea32f 100644
--- a/core/res/res/values-sl-rSI/donottranslate-cldr.xml
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -107,39 +107,39 @@
<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>
+ <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>
<string name="time1_time2">%1$s – %2$s</string>
<string name="date1_date2">%2$s – %5$s</string>
<string name="numeric_md1_md2">%3$s. %2$s. – %8$s. %7$s.</string>
<string name="numeric_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
<string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s – %8$s. %7$s. %9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
<string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. – %10$s %8$s. %7$s.</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
- <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
- <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s., %2$s – %6$s %4$s., %5$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s., %2$s – %4$s., %5$s</string>
<string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
- <string name="time_wday_date">%1$s %2$s %3$s</string>
- <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday_date">%1$s %2$s., %3$s</string>
+ <string name="wday_date">%2$s., %3$s</string>
<string name="time_wday">%1$s %2$s</string>
<string name="same_year_md1_md2">%3$s. %2$s – %8$s. %7$s</string>
- <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
<string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
<string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
<string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
<string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
<string name="same_month_md1_md2">%3$s.–%8$s. %2$s.</string>
- <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
<string name="same_year_mdy1_mdy2">%3$s. %2$s. – %8$s. %7$s. %9$s</string>
<string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s. %9$s</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s. %9$s</string>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
index 55d3983..c51f8d1 100644
--- a/core/res/res/values-uk-rUA/donottranslate-cldr.xml
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
<string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s – %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s – %8$s.%7$s.%9$s</string>
<string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s – %6$s, %8$s.%7$s.%9$s</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
- <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string>
+ <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s – %10$s %8$s.%7$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s – %10$s %6$s, %8$s.%7$s</string>
<string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s – %10$s %8$s.%7$s.%9$s</string>
<string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string>
<string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
index 71178cc..72ff8b6 100644
--- a/core/res/res/values-vi-rVN/donottranslate-cldr.xml
+++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
<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">%b</string>
<string name="abbrev_month_year">%b %Y</string>
<string name="time1_time2">%1$s - %2$s</string>
<string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index 8c386a4..6d52d70 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
- <string name="same_month_md1_md2">%2$s月%3$s日至%8$s日</string>
+ <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
- <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s月%8$s日</string>
+ <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
<string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s月%8$s日%6$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
index 8c386a4..6d52d70 100644
--- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
<string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
<string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
<string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
- <string name="same_month_md1_md2">%2$s月%3$s日至%8$s日</string>
+ <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
<string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
- <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s月%8$s日</string>
+ <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
<string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s月%8$s日%6$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
<string name="short_format_month">%b</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d778f5c..78567fc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1998,6 +1998,16 @@
<!-- The dropdown should fit the width of its anchor. -->
<enum name="wrap_content" value="-2" />
</attr>
+ <!-- Specifies the basic width of the dropdown. Its value may
+ be a dimension (such as "12dip") for a constant width, fill_parent
+ to fill the width of the screen, or wrap_content to match the height of
+ the content of the drop down. -->
+ <attr name="dropDownHeight" format="dimension">
+ <!-- The dropdown should fill the width of the screen. -->
+ <enum name="fill_parent" value="-1" />
+ <!-- The dropdown should fit the width of its anchor. -->
+ <enum name="wrap_content" value="-2" />
+ </attr>
<attr name="inputType" />
</declare-styleable>
<declare-styleable name="PopupWindow">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 41db0fa..079baf7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1116,7 +1116,8 @@
<public type="attr" name="allowBackup" />
<public type="attr" name="glEsVersion" />
<public type="attr" name="queryAfterZeroResults" />
-
+ <public type="attr" name="dropDownHeight" />
+
<public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
<public-padding type="id" name="donut_resource_pad" end="0x01020040" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 91b6609..88464f7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1338,6 +1338,22 @@
<!-- Title of the WebView save password dialog. If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. -->
<string name="save_password_label">Confirm</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_readHistoryBookmarks">read Browser\'s history and bookmarks</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_readHistoryBookmarks">Allows the application to read all
+ the URLs that the Browser has visited, and all of the Browser\'s bookmarks.</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_writeHistoryBookmarks">write Browser\'s history and bookmarks</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_writeHistoryBookmarks">Allows an application to modify the
+ Browser\'s history or bookmarks stored on your phone. Malicious applications
+ can use this to erase or modify your Browser\'s data.</string>
+
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Text in the save password dialog, asking if the browser should remember a password. -->
<string name="save_password_message">Do you want the browser to remember this password?</string>
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Button in the save password dialog, saying not to remember this password. -->
@@ -1792,15 +1808,15 @@
<!-- External media notification strings -->
<!-- Shown when external media is being checked -->
<string name="ext_media_checking_notification_title">Preparing SD card</string>
- <string name="ext_media_checking_notification_message">Checking for errors</string>
+ <string name="ext_media_checking_notification_message">Checking for errors.</string>
<!-- Shown when external media is blank (or unsupported filesystem) -->
<string name="ext_media_nofs_notification_title">Blank SD card</string>
- <string name="ext_media_nofs_notification_message">The SD card is blank or using an unsupported filesystem.</string>
+ <string name="ext_media_nofs_notification_message">SD card blank or has unsupported filesystem.</string>
<!-- Shown when external media is unmountable (corrupt)) -->
<string name="ext_media_unmountable_notification_title">Damaged SD card</string>
- <string name="ext_media_unmountable_notification_message">The SD card is damaged. You may have to reformat your card.</string>
+ <string name="ext_media_unmountable_notification_message">SD card damaged. You may have to reformat it.</string>
<!-- Shown when external media is unsafely removed -->
<string name="ext_media_badremoval_notification_title">SD card unexpectedly removed</string>
@@ -1808,11 +1824,11 @@
<!-- Shown when external media has been safely removed -->
<string name="ext_media_safe_unmount_notification_title">SD card safe to remove</string>
- <string name="ext_media_safe_unmount_notification_message">The SD card can now be safely removed.</string>
+ <string name="ext_media_safe_unmount_notification_message">You can safely remove SD card.</string>
<!-- Shown when external media is missing -->
<string name="ext_media_nomedia_notification_title">Removed SD card</string>
- <string name="ext_media_nomedia_notification_message">The SD has been removed. Insert a new SD card to increase your device storage.</string>
+ <string name="ext_media_nomedia_notification_message">SD card removed. Insert a new one.</string>
<!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. -->
<string name="activity_list_empty">No matching activities found</string>