diff options
author | Mathias Agopian <mathias@google.com> | 2009-06-24 18:31:21 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-06-24 18:31:21 -0700 |
commit | f31868e59fbf59a8d479587c80b648fb37a166fc (patch) | |
tree | 5a0aa67a76d6b0e48041f557eefd764e57eb97cf /core | |
parent | c6603951d45fc9b0d1776fec9444b6f31af92840 (diff) | |
parent | ecf2b68d834d334de218dc427615b4ca05c0293a (diff) | |
download | frameworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.zip frameworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.tar.gz frameworks_base-f31868e59fbf59a8d479587c80b648fb37a166fc.tar.bz2 |
merge master in master_gl
Diffstat (limited to 'core')
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 Binary files differindex a6923b7..804260a 100755..100644 --- a/core/res/res/drawable/search_dropdown_background.9.png +++ b/core/res/res/drawable/search_dropdown_background.9.png diff --git a/core/res/res/drawable/search_dropdown_background_apps.9.png b/core/res/res/drawable/search_dropdown_background_apps.9.png Binary files differdeleted file mode 100644 index 804260a..0000000 --- a/core/res/res/drawable/search_dropdown_background_apps.9.png +++ /dev/null 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> |