diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
commit | cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f (patch) | |
tree | 6510f35ad004f1a4640b48264c290926e8596d7a /core | |
parent | 4cf03d381b2dff908857fceff0bec445f8d44f36 (diff) | |
download | frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.zip frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.gz frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.bz2 |
donut snapshot
Diffstat (limited to 'core')
407 files changed, 33375 insertions, 6589 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java new file mode 100644 index 0000000..a3456c7 --- /dev/null +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -0,0 +1,225 @@ +/* + * 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.accessibilityservice; + +import com.android.internal.os.HandlerCaller; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; +import android.view.accessibility.AccessibilityEvent; + +/** + * An accessibility service runs in the background and receives callbacks by the system + * when {@link AccessibilityEvent}s are fired. Such events denote some state transition + * in the user interface, for example, the focus has changed, a button has been clicked, + * etc. + * <p> + * An accessibility service extends this class and implements its abstract methods. Such + * a service is declared as any other service in an AndroidManifest.xml but it must also + * specify that it handles the "android.accessibilityservice.AccessibilityService" + * {@link android.content.Intent}. Following is an example of such a declaration: + * <p> + * <code> + * <service android:name=".MyAccessibilityService"><br> + * <intent-filter><br> + * <action android:name="android.accessibilityservice.AccessibilityService" /><br> + * </intent-filter><br> + * </service><br> + * </code> + * <p> + * The lifecycle of an accessibility service is managed exclusively by the system. Starting + * or stopping an accessibility service is triggered by an explicit user action through + * enabling or disabling it in the device settings. After the system binds to a service it + * calls {@link AccessibilityService#onServiceConnected()}. This method can be + * overriden by clients that want to perform post binding setup. An accessibility service + * is configured though setting an {@link AccessibilityServiceInfo} by calling + * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. You can call this + * method any time to change the service configuration but it is good practice to do that + * in the overriden {@link AccessibilityService#onServiceConnected()}. + * <p> + * An accessibility service can be registered for events in specific packages to provide a + * specific type of feedback and is notified with a certain timeout after the last event + * of interest has been fired. + * <p> + * <b>Notification strategy</b> + * <p> + * For each feedback type only one accessibility service is notified. Services are notified + * in the order of registration. Hence, if two services are registered for the same + * feedback type in the same package the first one wins. It is possible however, to + * register a service as the default one for a given feedback type. In such a case this + * service is invoked if no other service was interested in the event. In other words, default + * services do not compete with other services and are notified last regardless of the + * registration order. This enables "generic" accessibility services that work reasonably + * well with most applications to coexist with "polished" ones that are targeted for + * specific applications. + * <p> + * <b>Event types</b> + * <p> + * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} + * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} + * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED} + * {@link AccessibilityEvent#TYPE_VIEW_SELECTED} + * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} + * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} + * {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} + * <p> + * <b>Feedback types</b> + * <p> + * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} + * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC} + * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE} + * {@link AccessibilityServiceInfo#FEEDBACK_VISUAL} + * {@link AccessibilityServiceInfo#FEEDBACK_GENERIC} + * + * @see AccessibilityEvent + * @see AccessibilityServiceInfo + * @see android.view.accessibility.AccessibilityManager + * + * Note: The event notification timeout is useful to avoid propagating events to the client + * too frequently since this is accomplished via an expensive interprocess call. + * One can think of the timeout as a criteria to determine when event generation has + * settled down. + */ +public abstract class AccessibilityService extends Service { + /** + * The {@link Intent} that must be declared as handled by the service. + */ + public static final String SERVICE_INTERFACE = + "android.accessibilityservice.AccessibilityService"; + + private static final String LOG_TAG = "AccessibilityService"; + + private AccessibilityServiceInfo mInfo; + + IAccessibilityServiceConnection mConnection; + + /** + * Callback for {@link android.view.accessibility.AccessibilityEvent}s. + * + * @param event An event. + */ + public abstract void onAccessibilityEvent(AccessibilityEvent event); + + /** + * Callback for interrupting the accessibility feedback. + */ + public abstract void onInterrupt(); + + /** + * This method is a part of the {@link AccessibilityService} lifecycle and is + * called after the system has successfully bound to the service. If is + * convenient to use this method for setting the {@link AccessibilityServiceInfo}. + * + * @see AccessibilityServiceInfo + * @see #setServiceInfo(AccessibilityServiceInfo) + */ + protected void onServiceConnected() { + + } + + /** + * Sets the {@link AccessibilityServiceInfo} that describes this service. + * <p> + * Note: You can call this method any time but the info will be picked up after + * the system has bound to this service and when this method is called thereafter. + * + * @param info The info. + */ + public final void setServiceInfo(AccessibilityServiceInfo info) { + mInfo = info; + sendServiceInfo(); + } + + /** + * Sets the {@link AccessibilityServiceInfo} for this service if the latter is + * properly set and there is an {@link IAccessibilityServiceConnection} to the + * AccessibilityManagerService. + */ + private void sendServiceInfo() { + if (mInfo != null && mConnection != null) { + try { + mConnection.setServiceInfo(mInfo); + } catch (RemoteException re) { + Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re); + } + } + } + + @Override + public final IBinder onBind(Intent intent) { + return new IEventListenerWrapper(this); + } + + /** + * Implements the internal {@link IEventListener} interface to convert + * incoming calls to it back to calls on an {@link AccessibilityService}. + */ + class IEventListenerWrapper extends IEventListener.Stub + implements HandlerCaller.Callback { + + private static final int DO_SET_SET_CONNECTION = 10; + private static final int DO_ON_INTERRUPT = 20; + private static final int DO_ON_ACCESSIBILITY_EVENT = 30; + + private final HandlerCaller mCaller; + + private AccessibilityService mTarget; + + public IEventListenerWrapper(AccessibilityService context) { + mTarget = context; + mCaller = new HandlerCaller(context, this); + } + + public void setConnection(IAccessibilityServiceConnection connection) { + Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection); + mCaller.sendMessage(message); + } + + public void onInterrupt() { + Message message = mCaller.obtainMessage(DO_ON_INTERRUPT); + mCaller.sendMessage(message); + } + + public void onAccessibilityEvent(AccessibilityEvent event) { + Message message = mCaller.obtainMessageO(DO_ON_ACCESSIBILITY_EVENT, event); + mCaller.sendMessage(message); + } + + public void executeMessage(Message message) { + switch (message.what) { + case DO_ON_ACCESSIBILITY_EVENT : + AccessibilityEvent event = (AccessibilityEvent) message.obj; + mTarget.onAccessibilityEvent(event); + event.recycle(); + return; + case DO_ON_INTERRUPT : + mTarget.onInterrupt(); + return; + case DO_SET_SET_CONNECTION : + mConnection = ((IAccessibilityServiceConnection) message.obj); + mTarget.onServiceConnected(); + return; + default : + Log.w(LOG_TAG, "Unknown message type " + message.what); + } + } + } +} diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl b/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl new file mode 100644 index 0000000..1f5d385 --- /dev/null +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.accessibilityservice; + +parcelable AccessibilityServiceInfo; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java new file mode 100644 index 0000000..4761f98 --- /dev/null +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -0,0 +1,145 @@ +/* + * 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.accessibilityservice; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class describes an {@link AccessibilityService}. The system + * notifies an {@link AccessibilityService} for + * {@link android.view.accessibility.AccessibilityEvent}s + * according to the information encapsulated in this class. + * + * @see AccessibilityService + * @see android.view.accessibility.AccessibilityEvent + */ +public class AccessibilityServiceInfo implements Parcelable { + + /** + * Denotes spoken feedback. + */ + public static final int FEEDBACK_SPOKEN = 0x0000001; + + /** + * Denotes haptic feedback. + */ + public static final int FEEDBACK_HAPTIC = 0x0000002; + + /** + * Denotes audible (not spoken) feedback. + */ + public static final int FEEDBACK_AUDIBLE = 0x0000004; + + /** + * Denotes visual feedback. + */ + public static final int FEEDBACK_VISUAL = 0x0000008; + + /** + * Denotes generic feedback. + */ + public static final int FEEDBACK_GENERIC = 0x0000010; + + /** + * If an {@link AccessibilityService} is the default for a given type. + * Default service is invoked only if no package specific one exists. In case of + * more than one package specific service only the earlier registered is notified. + */ + public static final int DEFAULT = 0x0000001; + + /** + * The event types an {@link AccessibilityService} is interested in. + * + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED + * @see android.view.accessibility.AccessibilityEvent#TYPE_ACTIVITY_STARTED + * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED + * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED + */ + public int eventTypes; + + /** + * The package names an {@link AccessibilityService} is interested in. Setting + * to null is equivalent to all packages. + */ + public String[] packageNames; + + /** + * The feedback type an {@link AccessibilityService} provides. + * + * @see #FEEDBACK_AUDIBLE + * @see #FEEDBACK_GENERIC + * @see #FEEDBACK_HAPTIC + * @see #FEEDBACK_SPOKEN + * @see #FEEDBACK_VISUAL + */ + public int feedbackType; + + /** + * The timeout after the most recent event of a given type before an + * {@link AccessibilityService} is notified. + * <p> + * Note: The event notification timeout is useful to avoid propagating events to the client + * too frequently since this is accomplished via an expensive interprocess call. + * One can think of the timeout as a criteria to determine when event generation has + * settled down + */ + public long notificationTimeout; + + /** + * This field represents a set of flags used for configuring an + * {@link AccessibilityService}. + * + * @see #DEFAULT + */ + public int flags; + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(eventTypes); + parcel.writeStringArray(packageNames); + parcel.writeInt(feedbackType); + parcel.writeLong(notificationTimeout); + parcel.writeInt(flags); + } + + /** + * @see Parcelable.Creator + */ + public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR = + new Parcelable.Creator<AccessibilityServiceInfo>() { + public AccessibilityServiceInfo createFromParcel(Parcel parcel) { + AccessibilityServiceInfo info = new AccessibilityServiceInfo(); + info.eventTypes = parcel.readInt(); + info.packageNames = parcel.readStringArray(); + info.feedbackType = parcel.readInt(); + info.notificationTimeout = parcel.readLong(); + info.flags = parcel.readInt(); + return info; + } + + public AccessibilityServiceInfo[] newArray(int size) { + return new AccessibilityServiceInfo[size]; + } + }; +} diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl new file mode 100644 index 0000000..7157def --- /dev/null +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -0,0 +1,30 @@ +/* + * 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.accessibilityservice; + +import android.accessibilityservice.AccessibilityServiceInfo; + +/** + * Interface AccessibilityManagerService#Service implements, and passes to an + * AccessibilityService so it can dynamically configure how the system handles it. + * + * @hide + */ +oneway interface IAccessibilityServiceConnection { + + void setServiceInfo(in AccessibilityServiceInfo info); +} diff --git a/core/java/android/accessibilityservice/IEventListener.aidl b/core/java/android/accessibilityservice/IEventListener.aidl new file mode 100644 index 0000000..5b849f1 --- /dev/null +++ b/core/java/android/accessibilityservice/IEventListener.aidl @@ -0,0 +1,34 @@ +/* +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.accessibilityservice; + +import android.accessibilityservice.IAccessibilityServiceConnection; +import android.view.accessibility.AccessibilityEvent; + +/** + * Top-level interface to accessibility service component (implemented in Service). + * + * @hide + */ + oneway interface IEventListener { + + void setConnection(in IAccessibilityServiceConnection connection); + + void onAccessibilityEvent(in AccessibilityEvent event); + + void onInterrupt(); +} diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 9b1f0f9..ca9632a 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -16,11 +16,14 @@ package android.app; +import com.android.internal.policy.PolicyManager; + import android.content.ComponentCallbacks; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IIntentSender; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -32,11 +35,12 @@ import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.Uri; import android.os.Bundle; -import android.os.RemoteException; import android.os.Handler; import android.os.IBinder; +import android.os.RemoteException; import android.text.Selection; import android.text.SpannableStringBuilder; +import android.text.TextUtils; import android.text.method.TextKeyListener; import android.util.AttributeSet; import android.util.Config; @@ -58,10 +62,10 @@ import android.view.Window; import android.view.WindowManager; import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; +import android.view.ViewGroup.LayoutParams; +import android.view.accessibility.AccessibilityEvent; import android.widget.AdapterView; -import com.android.internal.policy.PolicyManager; - import java.util.ArrayList; import java.util.HashMap; @@ -625,6 +629,8 @@ public class Activity extends ContextThemeWrapper boolean mStartedActivity; /*package*/ int mConfigChangeFlags; /*package*/ Configuration mCurrentConfig; + private SearchManager mSearchManager; + private Bundle mSearchDialogState = null; private Window mWindow; @@ -785,6 +791,9 @@ public class Activity extends ContextThemeWrapper protected void onCreate(Bundle savedInstanceState) { mVisibleFromClient = mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, true); + // uses super.getSystemService() since this.getSystemService() looks at the + // mSearchManager field. + mSearchManager = (SearchManager) super.getSystemService(Context.SEARCH_SERVICE); mCalled = true; } @@ -802,9 +811,10 @@ public class Activity extends ContextThemeWrapper // Also restore the state of a search dialog (if any) // TODO more generic than just this manager - SearchManager searchManager = - (SearchManager) getSystemService(Context.SEARCH_SERVICE); - searchManager.restoreSearchDialog(savedInstanceState, SAVED_SEARCH_DIALOG_KEY); + Bundle searchState = savedInstanceState.getBundle(SAVED_SEARCH_DIALOG_KEY); + if (searchState != null) { + mSearchManager.restoreSearchDialog(searchState); + } } /** @@ -854,13 +864,26 @@ public class Activity extends ContextThemeWrapper final Integer dialogId = ids[i]; Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId)); if (dialogState != null) { - final Dialog dialog = onCreateDialog(dialogId); - dialog.onRestoreInstanceState(dialogState); + // Calling onRestoreInstanceState() below will invoke dispatchOnCreate + // so tell createDialog() not to do it, otherwise we get an exception + final Dialog dialog = createDialog(dialogId, false); mManagedDialogs.put(dialogId, dialog); + onPrepareDialog(dialogId, dialog); + dialog.onRestoreInstanceState(dialogState); } } } + private Dialog createDialog(Integer dialogId, boolean dispatchOnCreate) { + final Dialog dialog = onCreateDialog(dialogId); + if (dialog == null) { + throw new IllegalArgumentException("Activity#onCreateDialog did " + + "not create a dialog for id " + dialogId); + } + if (dispatchOnCreate) dialog.dispatchOnCreate(null); + return dialog; + } + private String savedDialogKeyFor(int key) { return SAVED_DIALOG_KEY_PREFIX + key; } @@ -1010,9 +1033,11 @@ public class Activity extends ContextThemeWrapper // Also save the state of a search dialog (if any) // TODO more generic than just this manager - SearchManager searchManager = - (SearchManager) getSystemService(Context.SEARCH_SERVICE); - searchManager.saveSearchDialog(outState, SAVED_SEARCH_DIALOG_KEY); + // onPause() should always be called before this method, so mSearchManagerState + // should be up to date. + if (mSearchDialogState != null) { + outState.putBundle(SAVED_SEARCH_DIALOG_KEY, mSearchDialogState); + } } /** @@ -1283,12 +1308,6 @@ public class Activity extends ContextThemeWrapper } } } - - // also dismiss search dialog if showing - // TODO more generic than just this manager - SearchManager searchManager = - (SearchManager) getSystemService(Context.SEARCH_SERVICE); - searchManager.stopSearch(); // close any cursors we are managing. int numCursors = mManagedCursors.size(); @@ -1298,6 +1317,10 @@ public class Activity extends ContextThemeWrapper c.mCursor.close(); } } + + // Clear any search state saved in performPause(). If the state may be needed in the + // future, it will have been saved by performSaveInstanceState() + mSearchDialogState = null; } /** @@ -1321,9 +1344,7 @@ public class Activity extends ContextThemeWrapper // also update search dialog if showing // TODO more generic than just this manager - SearchManager searchManager = - (SearchManager) getSystemService(Context.SEARCH_SERVICE); - searchManager.onConfigurationChanged(newConfig); + mSearchManager.onConfigurationChanged(newConfig); if (mWindow != null) { // Pass the configuration changed event to the window @@ -2013,7 +2034,24 @@ public class Activity extends ContextThemeWrapper } return onTrackballEvent(ev); } - + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + event.setClassName(getClass().getName()); + event.setPackageName(getPackageName()); + + LayoutParams params = getWindow().getAttributes(); + boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) && + (params.height == LayoutParams.FILL_PARENT); + event.setFullScreen(isFullScreen); + + CharSequence title = getTitle(); + if (!TextUtils.isEmpty(title)) { + event.getText().add(title); + } + + return true; + } + /** * Default implementation of * {@link android.view.Window.Callback#onCreatePanelView} @@ -2394,12 +2432,7 @@ public class Activity extends ContextThemeWrapper } Dialog dialog = mManagedDialogs.get(id); if (dialog == null) { - dialog = onCreateDialog(id); - if (dialog == null) { - throw new IllegalArgumentException("Activity#onCreateDialog did " - + "not create a dialog for id " + id); - } - dialog.dispatchOnCreate(null); + dialog = createDialog(id, true); mManagedDialogs.put(id, dialog); } @@ -2523,10 +2556,7 @@ public class Activity extends ContextThemeWrapper */ public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData, boolean globalSearch) { - // activate the search manager and start it up! - SearchManager searchManager = (SearchManager) - getSystemService(Context.SEARCH_SERVICE); - searchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(), + mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(), appSearchData, globalSearch); } @@ -3245,6 +3275,8 @@ public class Activity extends ContextThemeWrapper if (WINDOW_SERVICE.equals(name)) { return mWindowManager; + } else if (SEARCH_SERVICE.equals(name)) { + return mSearchManager; } return super.getSystemService(name); } @@ -3543,10 +3575,21 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPostResume()"); } + + // restore search dialog, if any + if (mSearchDialogState != null) { + mSearchManager.restoreSearchDialog(mSearchDialogState); + } + mSearchDialogState = null; } final void performPause() { onPause(); + + // save search dialog state if the search dialog is open, + // and then dismiss the search dialog + mSearchDialogState = mSearchManager.saveSearchDialog(); + mSearchManager.stopSearch(); } final void performUserLeaving() { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 541f413..dfa8139 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -17,9 +17,11 @@ package android.app; import android.content.ComponentName; -import android.content.ContentResolver; import android.content.Intent; import android.content.IntentFilter; +import android.content.IIntentSender; +import android.content.IIntentReceiver; +import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.IPackageDataObserver; import android.content.res.Configuration; @@ -984,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; @@ -998,6 +1002,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case STOP_APP_SWITCHES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + stopAppSwitches(); + reply.writeNoException(); + return true; + } + + case RESUME_APP_SWITCHES_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + resumeAppSwitches(); + reply.writeNoException(); + return true; + } + case PEEK_SERVICE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); Intent service = Intent.CREATOR.createFromParcel(data); @@ -1007,6 +1025,33 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeStrongBinder(binder); return true; } + + case START_BACKUP_AGENT_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); + int backupRestoreMode = data.readInt(); + boolean success = bindBackupAgent(info, backupRestoreMode); + reply.writeNoException(); + reply.writeInt(success ? 1 : 0); + return true; + } + + case BACKUP_AGENT_CREATED_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + IBinder agent = data.readStrongBinder(); + backupAgentCreated(packageName, agent); + reply.writeNoException(); + return true; + } + + case UNBIND_BACKUP_AGENT_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); + unbindBackupAgent(info); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -1667,6 +1712,43 @@ class ActivityManagerProxy implements IActivityManager return binder; } + public boolean bindBackupAgent(ApplicationInfo app, int backupRestoreMode) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + app.writeToParcel(data, 0); + data.writeInt(backupRestoreMode); + mRemote.transact(START_BACKUP_AGENT_TRANSACTION, data, reply, 0); + reply.readException(); + boolean success = reply.readInt() != 0; + reply.recycle(); + data.recycle(); + return success; + } + + public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + data.writeStrongBinder(agent); + mRemote.transact(BACKUP_AGENT_CREATED_TRANSACTION, data, reply, 0); + reply.recycle(); + data.recycle(); + } + + public void unbindBackupAgent(ApplicationInfo app) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + app.writeToParcel(data, 0); + mRemote.transact(UNBIND_BACKUP_AGENT_TRANSACTION, data, reply, 0); + reply.readException(); + reply.recycle(); + data.recycle(); + } + public boolean startInstrumentation(ComponentName className, String profileFile, int flags, Bundle arguments, IInstrumentationWatcher watcher) throws RemoteException { @@ -2152,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(); @@ -2160,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; @@ -2182,5 +2270,25 @@ class ActivityManagerProxy implements IActivityManager return res; } + public void stopAppSwitches() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(STOP_APP_SWITCHES_TRANSACTION, data, reply, 0); + reply.readException(); + reply.recycle(); + data.recycle(); + } + + public void resumeAppSwitches() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(RESUME_APP_SWITCHES_TRANSACTION, data, reply, 0); + reply.readException(); + reply.recycle(); + data.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 1e15d14..5ee29ac 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -23,6 +23,7 @@ import android.content.ContentProvider; import android.content.Context; import android.content.IContentProvider; import android.content.Intent; +import android.content.IIntentReceiver; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -31,6 +32,7 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; +import android.content.pm.PackageParser.Component; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; @@ -46,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; @@ -72,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; @@ -115,6 +119,7 @@ public final class ActivityThread { private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; private static final boolean DEBUG_BROADCAST = false; private static final boolean DEBUG_RESULTS = false; + private static final boolean DEBUG_BACKUP = true; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; @@ -161,7 +166,7 @@ public final class ActivityThread { return metrics; } - Resources getTopLevelResources(String appDir, float applicationScale) { + Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) { synchronized (mPackages) { //Log.w(TAG, "getTopLevelResources: " + appDir); WeakReference<Resources> wr = mActiveResources.get(appDir); @@ -180,23 +185,17 @@ public final class ActivityThread { if (assets.addAssetPath(appDir) == 0) { return null; } - DisplayMetrics metrics = getDisplayMetricsLocked(false); - // density used to load resources - // scaledDensity is calculated in Resources constructor - // - boolean usePreloaded = true; - - // TODO: use explicit flag to indicate the compatibility mode. - if (applicationScale != 1.0f) { - usePreloaded = false; - DisplayMetrics newMetrics = new DisplayMetrics(); - newMetrics.setTo(metrics); - float newDensity = metrics.density / applicationScale; - newMetrics.updateDensity(newDensity); - metrics = newMetrics; + ApplicationInfo appInfo; + try { + appInfo = getPackageManager().getApplicationInfo( + pkgInfo.getPackageName(), + PackageManager.GET_SUPPORTS_DENSITIES); + } catch (RemoteException e) { + throw new AssertionError(e); } //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics); - r = new Resources(assets, metrics, getConfiguration(), usePreloaded); + DisplayMetrics metrics = getDisplayMetricsLocked(false); + r = new Resources(assets, metrics, getConfiguration(), appInfo); //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration()); // XXX need to remove entries when weak references go away mActiveResources.put(appDir, new WeakReference<Resources>(r)); @@ -224,7 +223,6 @@ public final class ActivityThread { private Resources mResources; private ClassLoader mClassLoader; private Application mApplication; - private float mApplicationScale; private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>(); @@ -267,8 +265,6 @@ public final class ActivityThread { mClassLoader = mSystemContext.getClassLoader(); mResources = mSystemContext.getResources(); } - - mApplicationScale = -1.0f; } public PackageInfo(ActivityThread activityThread, String name, @@ -287,56 +283,20 @@ public final class ActivityThread { mIncludeCode = true; mClassLoader = systemContext.getClassLoader(); mResources = systemContext.getResources(); - mApplicationScale = systemContext.getApplicationScale(); } public String getPackageName() { return mPackageName; } + public ApplicationInfo getApplicationInfo() { + return mApplicationInfo; + } + public boolean isSecurityViolation() { return mSecurityViolation; } - public float getApplicationScale() { - if (mApplicationScale > 0.0f) { - return mApplicationScale; - } - DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false); - // Find out the density scale (relative to 160) of the supported density that - // is closest to the system's density. - try { - ApplicationInfo ai = getPackageManager().getApplicationInfo( - mPackageName, PackageManager.GET_SUPPORTS_DENSITIES); - - float appScale = -1.0f; - if (ai.supportsDensities != null) { - int minDiff = Integer.MAX_VALUE; - for (int density : ai.supportsDensities) { - int tmpDiff = (int) Math.abs(DisplayMetrics.DEVICE_DENSITY - density); - if (tmpDiff == 0) { - appScale = 1.0f; - break; - } - // prefer higher density (appScale>1.0), unless that's only option. - if (tmpDiff < minDiff && appScale < 1.0f) { - appScale = DisplayMetrics.DEVICE_DENSITY / density; - minDiff = tmpDiff; - } - } - } - if (appScale < 0.0f) { - mApplicationScale = metrics.density; - } else { - mApplicationScale = appScale; - } - } catch (RemoteException e) { - throw new AssertionError(e); - } - if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName); - return mApplicationScale; - } - /** * Gets the array of shared libraries that are listed as * used by the given package. @@ -494,12 +454,12 @@ public final class ActivityThread { public Resources getResources(ActivityThread mainThread) { if (mResources == null) { - mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale()); + mResources = mainThread.getTopLevelResources(mResDir, this); } return mResources; } - public Application makeApplication() { + public Application makeApplication(boolean forceDefaultAppClass) { if (mApplication != null) { return mApplication; } @@ -507,7 +467,7 @@ public final class ActivityThread { Application app = null; String appClass = mApplicationInfo.className; - if (appClass == null) { + if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } @@ -1199,6 +1159,16 @@ public final class ActivityThread { } } + private static final class CreateBackupAgentData { + ApplicationInfo appInfo; + int backupMode; + public String toString() { + return "CreateBackupAgentData{appInfo=" + appInfo + + " backupAgent=" + appInfo.backupAgentName + + " mode=" + backupMode + "}"; + } + } + private static final class CreateServiceData { IBinder token; ServiceInfo info; @@ -1239,6 +1209,7 @@ public final class ActivityThread { Bundle instrumentationArgs; IInstrumentationWatcher instrumentationWatcher; int debugMode; + boolean restrictedBackupMode; Configuration config; boolean handlingProfiling; public String toString() { @@ -1267,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"; @@ -1374,6 +1350,21 @@ public final class ActivityThread { queueOrSendMessage(H.RECEIVER, r); } + public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) { + CreateBackupAgentData d = new CreateBackupAgentData(); + d.appInfo = app; + d.backupMode = backupMode; + + queueOrSendMessage(H.CREATE_BACKUP_AGENT, d); + } + + public final void scheduleDestroyBackupAgent(ApplicationInfo app) { + CreateBackupAgentData d = new CreateBackupAgentData(); + d.appInfo = app; + + queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d); + } + public final void scheduleCreateService(IBinder token, ServiceInfo info) { CreateServiceData s = new CreateServiceData(); @@ -1419,7 +1410,7 @@ public final class ActivityThread { ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, String profileFile, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, - int debugMode, Configuration config, + int debugMode, boolean isRestrictedBackupMode, Configuration config, Map<String, IBinder> services) { Process.setArgV0(processName); @@ -1437,6 +1428,7 @@ public final class ActivityThread { data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.debugMode = debugMode; + data.restrictedBackupMode = isRestrictedBackupMode; data.config = config; queueOrSendMessage(H.BIND_APPLICATION, data); } @@ -1509,10 +1501,25 @@ 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) { + // Note: do this immediately, since going into the foreground + // should happen regardless of what pending work we have to do + // and the activity manager will wait for us to report back that + // we are done before sending us to the background. + try { + Process.setProcessGroup(Process.myPid(), group); + } catch (Exception e) { + Log.w(TAG, "Failed setting process group to " + group, e); + } } - + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { long nativeMax = Debug.getNativeHeapSize() / 1024; @@ -1706,6 +1713,8 @@ public final class ActivityThread { public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; public static final int RELAUNCH_ACTIVITY = 126; public static final int PROFILER_CONTROL = 127; + public static final int CREATE_BACKUP_AGENT = 128; + public static final int DESTROY_BACKUP_AGENT = 129; String codeToString(int code) { if (localLOGV) { switch (code) { @@ -1737,6 +1746,8 @@ public final class ActivityThread { case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; case PROFILER_CONTROL: return "PROFILER_CONTROL"; + case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; + case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; } } return "(unknown)"; @@ -1837,7 +1848,13 @@ 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); + break; + case DESTROY_BACKUP_AGENT: + handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); break; } } @@ -1896,6 +1913,8 @@ public final class ActivityThread { Application mInitialApplication; final ArrayList<Application> mAllApplications = new ArrayList<Application>(); + // set of instantiated backup agents, keyed by package name + final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>(); static final ThreadLocal sThreadLocal = new ThreadLocal(); Instrumentation mInstrumentation; String mInstrumentationAppDir = null; @@ -2079,6 +2098,10 @@ public final class ActivityThread { return mInitialApplication; } + public String getProcessName() { + return mBoundApplication.processName; + } + public ApplicationContext getSystemContext() { synchronized (this) { if (mSystemContext == null) { @@ -2257,7 +2280,7 @@ public final class ActivityThread { } try { - Application app = r.packageInfo.makeApplication(); + Application app = r.packageInfo.makeApplication(false); if (localLOGV) Log.v(TAG, "Performing launch of " + r); if (localLOGV) Log.v( @@ -2452,7 +2475,7 @@ public final class ActivityThread { } try { - Application app = packageInfo.makeApplication(); + Application app = packageInfo.makeApplication(false); if (localLOGV) Log.v( TAG, "Performing receive of " + data.intent @@ -2495,6 +2518,85 @@ public final class ActivityThread { } } + // Instantiate a BackupAgent and tell it that it's alive + private final void handleCreateBackupAgent(CreateBackupAgentData data) { + if (DEBUG_BACKUP) Log.v(TAG, "handleCreateBackupAgent: " + data); + + // no longer idle; we have backup work to do + unscheduleGcIdler(); + + // instantiate the BackupAgent class named in the manifest + PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo); + String packageName = packageInfo.mPackageName; + if (mBackupAgents.get(packageName) != null) { + Log.d(TAG, "BackupAgent " + " for " + packageName + + " already exists"); + return; + } + + BackupAgent agent = null; + String classname = data.appInfo.backupAgentName; + if (classname == null) { + if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) { + Log.e(TAG, "Attempted incremental backup but no defined agent for " + + packageName); + return; + } + classname = "android.app.FullBackupAgent"; + } + try { + java.lang.ClassLoader cl = packageInfo.getClassLoader(); + agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Unable to instantiate backup agent " + + data.appInfo.backupAgentName + ": " + e.toString(), e); + } + + // set up the agent's context + try { + if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent " + + data.appInfo.backupAgentName); + + ApplicationContext context = new ApplicationContext(); + context.init(packageInfo, null, this); + context.setOuterContext(agent); + agent.attach(context); + agent.onCreate(); + + // tell the OS that we're live now + IBinder binder = agent.onBind(); + try { + ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); + } catch (RemoteException e) { + // nothing to do. + } + mBackupAgents.put(packageName, agent); + } catch (Exception e) { + throw new RuntimeException("Unable to create BackupAgent " + + data.appInfo.backupAgentName + ": " + e.toString(), e); + } + } + + // Tear down a BackupAgent + private final void handleDestroyBackupAgent(CreateBackupAgentData data) { + if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data); + + PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo); + String packageName = packageInfo.mPackageName; + BackupAgent agent = mBackupAgents.get(packageName); + if (agent != null) { + try { + agent.onDestroy(); + } catch (Exception e) { + Log.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo); + e.printStackTrace(); + } + mBackupAgents.remove(packageName); + } else { + Log.w(TAG, "Attempt to destroy unknown backup agent " + data); + } + } + private final void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. @@ -2520,7 +2622,7 @@ public final class ActivityThread { ApplicationContext context = new ApplicationContext(); context.init(packageInfo, null, this); - Application app = packageInfo.makeApplication(); + Application app = packageInfo.makeApplication(false); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); @@ -3134,7 +3236,7 @@ public final class ActivityThread { r.activity.getComponentName().getClassName()); if (!r.activity.mCalled) { throw new SuperNotCalledException( - "Activity " + r.intent.getComponent().toShortString() + "Activity " + safeToComponentShortString(r.intent) + " did not call through to super.onPause()"); } } catch (SuperNotCalledException e) { @@ -3143,7 +3245,7 @@ public final class ActivityThread { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( "Unable to pause activity " - + r.intent.getComponent().toShortString() + + safeToComponentShortString(r.intent) + ": " + e.toString(), e); } } @@ -3158,7 +3260,7 @@ public final class ActivityThread { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( "Unable to stop activity " - + r.intent.getComponent().toShortString() + + safeToComponentShortString(r.intent) + ": " + e.toString(), e); } } @@ -3183,7 +3285,7 @@ public final class ActivityThread { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( "Unable to retain child activities " - + r.intent.getComponent().toShortString() + + safeToComponentShortString(r.intent) + ": " + e.toString(), e); } } @@ -3194,7 +3296,7 @@ public final class ActivityThread { r.activity.onDestroy(); if (!r.activity.mCalled) { throw new SuperNotCalledException( - "Activity " + r.intent.getComponent().toShortString() + + "Activity " + safeToComponentShortString(r.intent) + " did not call through to super.onDestroy()"); } if (r.window != null) { @@ -3205,8 +3307,7 @@ public final class ActivityThread { } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( - "Unable to destroy activity " - + r.intent.getComponent().toShortString() + "Unable to destroy activity " + safeToComponentShortString(r.intent) + ": " + e.toString(), e); } } @@ -3216,6 +3317,11 @@ public final class ActivityThread { return r; } + private static String safeToComponentShortString(Intent intent) { + ComponentName component = intent.getComponent(); + return component == null ? "[Unknown]" : component.toShortString(); + } + private final void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityRecord r = performDestroyActivity(token, finishing, @@ -3475,8 +3581,6 @@ public final class ActivityThread { } mConfiguration.updateFrom(config); DisplayMetrics dm = getDisplayMetricsLocked(true); - DisplayMetrics appDm = new DisplayMetrics(); - appDm.setTo(dm); // set it for java, this also affects newly created Resources if (config.locale != null) { @@ -3496,11 +3600,7 @@ public final class ActivityThread { WeakReference<Resources> v = it.next(); Resources r = v.get(); if (r != null) { - // keep the original density based on application cale. - appDm.updateDensity(r.getDisplayMetrics().density); - r.updateConfiguration(config, appDm); - // reset - appDm.setTo(dm); + r.updateConfiguration(config, dm); //Log.i(TAG, "Updated app resources " + v.getKey() // + " " + r + ": " + r.getConfiguration()); } else { @@ -3528,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(); @@ -3592,6 +3697,13 @@ public final class ActivityThread { */ Locale.setDefault(data.config.locale); + /* + * Update the system configuration since its preloaded and might not + * reflect configuration changes. The configuration object passed + * in AppBindData can be safely assumed to be up to date + */ + Resources.getSystem().updateConfiguration(mConfiguration, null); + data.info = getPackageInfoNoCheck(data.appInfo); if (data.debugMode != IApplicationThread.DEBUG_OFF) { @@ -3682,7 +3794,9 @@ public final class ActivityThread { mInstrumentation = new Instrumentation(); } - Application app = data.info.makeApplication(); + // If the app is being launched for full backup or restore, bring it up in + // a restricted environment with the base application class. + Application app = data.info.makeApplication(data.restrictedBackupMode); mInitialApplication = app; List<ProviderInfo> providers = data.providers; @@ -3867,7 +3981,10 @@ public final class ActivityThread { ProviderRecord pr = mProviderMap.get(name); if (pr.mProvider.asBinder() == provider.asBinder()) { Log.i(TAG, "Removing dead content provider: " + name); - mProviderMap.remove(name); + ProviderRecord removed = mProviderMap.remove(name); + if (removed != null) { + removed.mProvider.asBinder().unlinkToDeath(removed, 0); + } } } } @@ -3876,7 +3993,10 @@ public final class ActivityThread { ProviderRecord pr = mProviderMap.get(name); if (pr.mProvider.asBinder() == provider.asBinder()) { Log.i(TAG, "Removing dead content provider: " + name); - mProviderMap.remove(name); + ProviderRecord removed = mProviderMap.remove(name); + if (removed != null) { + removed.mProvider.asBinder().unlinkToDeath(removed, 0); + } } } diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index bb17dc3..38ea686 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -16,8 +16,11 @@ package android.app; -import com.google.android.collect.Maps; +import com.android.internal.policy.PolicyManager; import com.android.internal.util.XmlUtils; +import com.google.android.collect.Maps; + +import org.xmlpull.v1.XmlPullParserException; import android.bluetooth.BluetoothDevice; import android.bluetooth.IBluetoothDevice; @@ -29,6 +32,8 @@ import android.content.ContextWrapper; import android.content.IContentProvider; import android.content.Intent; import android.content.IntentFilter; +import android.content.IIntentReceiver; +import android.content.IntentSender; import android.content.ReceiverCallNotAllowedException; import android.content.ServiceConnection; import android.content.SharedPreferences; @@ -37,9 +42,9 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; -import android.content.pm.IPackageStatsObserver; import android.content.pm.IPackageInstallObserver; import android.content.pm.IPackageManager; +import android.content.pm.IPackageStatsObserver; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -68,29 +73,30 @@ import android.net.wifi.IWifiManager; import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Bundle; -import android.os.Looper; -import android.os.RemoteException; import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.IPowerManager; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteException; import android.os.ServiceManager; import android.os.Vibrator; import android.os.FileUtils.FileStatus; import android.telephony.TelephonyManager; import android.text.ClipboardManager; import android.util.AndroidRuntimeException; +import android.util.DisplayMetrics; import android.util.Log; import android.view.ContextThemeWrapper; +import android.view.Display; import android.view.LayoutInflater; import android.view.WindowManagerImpl; +import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.InputMethodManager; -import com.android.internal.policy.PolicyManager; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -100,16 +106,14 @@ import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.WeakHashMap; import java.util.Set; -import java.util.HashSet; +import java.util.WeakHashMap; import java.util.Map.Entry; -import org.xmlpull.v1.XmlPullParserException; - class ReceiverRestrictedContext extends ContextWrapper { ReceiverRestrictedContext(Context base) { super(base); @@ -147,6 +151,7 @@ class ReceiverRestrictedContext extends ContextWrapper { */ class ApplicationContext extends Context { private final static String TAG = "ApplicationContext"; + private final static boolean DEBUG = false; private final static boolean DEBUG_ICONS = false; private static final Object sSync = new Object(); @@ -172,6 +177,7 @@ class ApplicationContext extends Context { private Resources.Theme mTheme = null; private PackageManager mPackageManager; private NotificationManager mNotificationManager = null; + private AccessibilityManager mAccessibilityManager = null; private ActivityManager mActivityManager = null; private Context mReceiverRestrictedContext = null; private SearchManager mSearchManager = null; @@ -181,6 +187,7 @@ class ApplicationContext extends Context { private StatusBarManager mStatusBarManager = null; private TelephonyManager mTelephonyManager = null; private ClipboardManager mClipboardManager = null; + private boolean mRestricted; private final Object mSync = new Object(); @@ -280,6 +287,14 @@ class ApplicationContext extends Context { } @Override + public ApplicationInfo getApplicationInfo() { + if (mPackageInfo != null) { + return mPackageInfo.getApplicationInfo(); + } + throw new RuntimeException("Not supported in system context"); + } + + @Override public String getPackageResourcePath() { if (mPackageInfo != null) { return mPackageInfo.getResDir(); @@ -299,10 +314,14 @@ class ApplicationContext extends Context { return new File(prefsFile.getPath() + ".bak"); } + public File getSharedPrefsFile(String name) { + return makeFilename(getPreferencesDir(), name + ".xml"); + } + @Override public SharedPreferences getSharedPreferences(String name, int mode) { SharedPreferencesImpl sp; - File f = makeFilename(getPreferencesDir(), name + ".xml"); + File f = getSharedPrefsFile(name); synchronized (sSharedPrefs) { sp = sSharedPrefs.get(f); if (sp != null && !sp.hasFileChanged()) { @@ -550,19 +569,6 @@ class ApplicationContext extends Context { } } - /** - * @hide - */ - @Override - public float getApplicationScale() { - if (mPackageInfo != null) { - return mPackageInfo.getApplicationScale(); - } else { - // same as system density - return 1.0f; - } - } - @Override public void setWallpaper(Bitmap bitmap) throws IOException { try { @@ -904,6 +910,8 @@ class ApplicationContext extends Context { return getNotificationManager(); } else if (KEYGUARD_SERVICE.equals(name)) { return new KeyguardManager(); + } else if (ACCESSIBILITY_SERVICE.equals(name)) { + return AccessibilityManager.getInstance(this); } else if (LOCATION_SERVICE.equals(name)) { return getLocationManager(); } else if (SEARCH_SERVICE.equals(name)) { @@ -1033,11 +1041,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()); @@ -1238,7 +1241,7 @@ class ApplicationContext extends Context { @Override public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags) { - if (false) { + if (DEBUG) { Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission=" + readPermission + " writePermission=" + writePermission + " pid=" + pid + " uid=" + uid + " mode" + modeFlags); @@ -1337,8 +1340,22 @@ class ApplicationContext extends Context { mMainThread.getPackageInfo(packageName, flags); if (pi != null) { ApplicationContext c = new ApplicationContext(); + c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; c.init(pi, null, mMainThread); if (c.mResources != null) { + Resources newRes = c.mResources; + if (mResources.getCompatibilityInfo().applicationScale != + newRes.getCompatibilityInfo().applicationScale) { + DisplayMetrics dm = mMainThread.getDisplayMetricsLocked(false); + c.mResources = new Resources(newRes.getAssets(), dm, + newRes.getConfiguration(), + mResources.getCompatibilityInfo().copy()); + if (DEBUG) { + Log.d(TAG, "loaded context has different scaling. Using container's" + + " compatiblity info:" + mResources.getDisplayMetrics()); + } + + } return c; } } @@ -1348,6 +1365,11 @@ class ApplicationContext extends Context { "Application package " + packageName + " not found"); } + @Override + public boolean isRestricted() { + return mRestricted; + } + private File getDataDirFile() { if (mPackageInfo != null) { return mPackageInfo.getDataDirFile(); @@ -1453,7 +1475,7 @@ class ApplicationContext extends Context { if ((mode&MODE_WORLD_WRITEABLE) != 0) { perms |= FileUtils.S_IWOTH; } - if (false) { + if (DEBUG) { Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode) + ", perms=0x" + Integer.toHexString(perms)); } @@ -1516,43 +1538,33 @@ class ApplicationContext extends Context { throw new NameNotFoundException(packageName); } - public Intent getLaunchIntentForPackage(String packageName) - throws NameNotFoundException { + @Override + public Intent getLaunchIntentForPackage(String packageName) { // First see if the package has an INFO activity; the existence of // such an activity is implied to be the desired front-door for the // overall package (such as if it has multiple launcher entries). - Intent intent = getLaunchIntentForPackageCategory(this, packageName, - Intent.CATEGORY_INFO); - if (intent != null) { - return intent; - } - + Intent intentToResolve = new Intent(Intent.ACTION_MAIN); + intentToResolve.addCategory(Intent.CATEGORY_INFO); + intentToResolve.setPackage(packageName); + ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0); + // Otherwise, try to find a main launcher activity. - return getLaunchIntentForPackageCategory(this, packageName, - Intent.CATEGORY_LAUNCHER); - } - - // XXX This should be implemented as a call to the package manager, - // to reduce the work needed. - static Intent getLaunchIntentForPackageCategory(PackageManager pm, - String packageName, String category) { + if (resolveInfo == null) { + // reuse the intent instance + intentToResolve.removeCategory(Intent.CATEGORY_INFO); + intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); + intentToResolve.setPackage(packageName); + resolveInfo = resolveActivity(intentToResolve, 0); + } + if (resolveInfo == null) { + return null; + } Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClassName(packageName, resolveInfo.activityInfo.name); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Intent intentToResolve = new Intent(Intent.ACTION_MAIN, null); - intentToResolve.addCategory(category); - final List<ResolveInfo> apps = - pm.queryIntentActivities(intentToResolve, 0); - // I wish there were a way to directly get the "main" activity of a - // package but ... - for (ResolveInfo app : apps) { - if (app.activityInfo.packageName.equals(packageName)) { - intent.setClassName(packageName, app.activityInfo.name); - return intent; - } - } - return null; + return intent; } - + @Override public int[] getPackageGids(String packageName) throws NameNotFoundException { @@ -2024,8 +2036,7 @@ class ApplicationContext extends Context { ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app); Resources r = mContext.mMainThread.getTopLevelResources( app.uid == Process.myUid() ? app.sourceDir - : app.publicSourceDir, - pi.getApplicationScale()); + : app.publicSourceDir, pi); if (r != null) { return r; } @@ -2363,11 +2374,11 @@ class ApplicationContext extends Context { // Should never happen! } } - + @Override - public void freeStorage(long idealStorageSize, PendingIntent opFinishedIntent) { + public void freeStorage(long freeStorageSize, IntentSender pi) { try { - mPM.freeStorage(idealStorageSize, opFinishedIntent); + mPM.freeStorage(freeStorageSize, pi); } catch (RemoteException e) { // Should never happen! } @@ -2421,6 +2432,16 @@ class ApplicationContext extends Context { } @Override + public void replacePreferredActivity(IntentFilter filter, + int match, ComponentName[] set, ComponentName activity) { + try { + mPM.replacePreferredActivity(filter, match, set, activity); + } catch (RemoteException e) { + // Should never happen! + } + } + + @Override public void clearPackagePreferredActivities(String packageName) { try { mPM.clearPackagePreferredActivities(packageName); diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java new file mode 100644 index 0000000..6b17236 --- /dev/null +++ b/core/java/android/app/ApplicationErrorReport.java @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +/** + * Describes an application error. + * + * A report has a type, which is one of + * <ul> + * <li> {@link #TYPE_CRASH} application crash. Information about the crash + * is stored in {@link #crashInfo}. + * <li> {@link #TYPE_ANR} application not responding. Information about the + * ANR is stored in {@link #anrInfo}. + * <li> {@link #TYPE_NONE} uninitialized instance of {@link ApplicationErrorReport}. + * </ul> + * + * @hide + */ + +public class ApplicationErrorReport implements Parcelable { + /** + * Uninitialized error report. + */ + public static final int TYPE_NONE = 0; + + /** + * An error report about an application crash. + */ + public static final int TYPE_CRASH = 1; + + /** + * An error report about an application that's not responding. + */ + public static final int TYPE_ANR = 2; + + /** + * Type of this report. Can be one of {@link #TYPE_NONE}, + * {@link #TYPE_CRASH} or {@link #TYPE_ANR}. + */ + public int type; + + /** + * Package name of the application. + */ + public String packageName; + + /** + * Package name of the application which installed the application this + * report pertains to. + * This identifies which Market the application came from. + */ + public String installerPackageName; + + /** + * Process name of the application. + */ + public String processName; + + /** + * Time at which the error occurred. + */ + public long time; + + /** + * If this report is of type {@link #TYPE_CRASH}, contains an instance + * of CrashInfo describing the crash; otherwise null. + */ + public CrashInfo crashInfo; + + /** + * If this report is of type {@link #TYPE_ANR}, contains an instance + * of AnrInfo describing the ANR; otherwise null. + */ + public AnrInfo anrInfo; + + /** + * Create an uninitialized instance of {@link ApplicationErrorReport}. + */ + public ApplicationErrorReport() { + } + + /** + * Create an instance of {@link ApplicationErrorReport} initialized from + * a parcel. + */ + ApplicationErrorReport(Parcel in) { + readFromParcel(in); + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(type); + dest.writeString(packageName); + dest.writeString(installerPackageName); + dest.writeString(processName); + dest.writeLong(time); + + switch (type) { + case TYPE_CRASH: + crashInfo.writeToParcel(dest, flags); + break; + case TYPE_ANR: + anrInfo.writeToParcel(dest, flags); + break; + } + } + + public void readFromParcel(Parcel in) { + type = in.readInt(); + packageName = in.readString(); + installerPackageName = in.readString(); + processName = in.readString(); + time = in.readLong(); + + switch (type) { + case TYPE_CRASH: + crashInfo = new CrashInfo(in); + anrInfo = null; + break; + case TYPE_ANR: + anrInfo = new AnrInfo(in); + crashInfo = null; + break; + } + } + + /** + * Describes an application crash. + */ + public static class CrashInfo { + /** + * Class name of the exception that caused the crash. + */ + public String exceptionClassName; + + /** + * Message stored in the exception. + */ + public String exceptionMessage; + + /** + * File which the exception was thrown from. + */ + public String throwFileName; + + /** + * Class which the exception was thrown from. + */ + public String throwClassName; + + /** + * Method which the exception was thrown from. + */ + public String throwMethodName; + + /** + * Stack trace. + */ + public String stackTrace; + + /** + * Create an uninitialized instance of CrashInfo. + */ + public CrashInfo() { + } + + /** + * Create an instance of CrashInfo initialized from a Parcel. + */ + public CrashInfo(Parcel in) { + exceptionClassName = in.readString(); + exceptionMessage = in.readString(); + throwFileName = in.readString(); + throwClassName = in.readString(); + throwMethodName = in.readString(); + stackTrace = in.readString(); + } + + /** + * Save a CrashInfo instance to a parcel. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(exceptionClassName); + dest.writeString(exceptionMessage); + dest.writeString(throwFileName); + dest.writeString(throwClassName); + dest.writeString(throwMethodName); + dest.writeString(stackTrace); + } + + /** + * Dump a CrashInfo instance to a Printer. + */ + public void dump(Printer pw, String prefix) { + pw.println(prefix + "exceptionClassName: " + exceptionClassName); + pw.println(prefix + "exceptionMessage: " + exceptionMessage); + pw.println(prefix + "throwFileName: " + throwFileName); + pw.println(prefix + "throwClassName: " + throwClassName); + pw.println(prefix + "throwMethodName: " + throwMethodName); + pw.println(prefix + "stackTrace: " + stackTrace); + } + } + + /** + * Describes an application not responding error. + */ + public static class AnrInfo { + /** + * Activity name. + */ + public String activity; + + /** + * Description of the operation that timed out. + */ + public String cause; + + /** + * Additional info, including CPU stats. + */ + public String info; + + /** + * Create an uninitialized instance of AnrInfo. + */ + public AnrInfo() { + } + + /** + * Create an instance of AnrInfo initialized from a Parcel. + */ + public AnrInfo(Parcel in) { + activity = in.readString(); + cause = in.readString(); + info = in.readString(); + } + + /** + * Save an AnrInfo instance to a parcel. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(activity); + dest.writeString(cause); + dest.writeString(info); + } + + /** + * Dump an AnrInfo instance to a Printer. + */ + public void dump(Printer pw, String prefix) { + pw.println(prefix + "activity: " + activity); + pw.println(prefix + "cause: " + cause); + pw.println(prefix + "info: " + info); + } + } + + public static final Parcelable.Creator<ApplicationErrorReport> CREATOR + = new Parcelable.Creator<ApplicationErrorReport>() { + public ApplicationErrorReport createFromParcel(Parcel source) { + return new ApplicationErrorReport(source); + } + + public ApplicationErrorReport[] newArray(int size) { + return new ApplicationErrorReport[size]; + } + }; + + public int describeContents() { + return 0; + } + + /** + * Dump the report to a Printer. + */ + public void dump(Printer pw, String prefix) { + pw.println(prefix + "type: " + type); + pw.println(prefix + "packageName: " + packageName); + pw.println(prefix + "installerPackageName: " + installerPackageName); + pw.println(prefix + "processName: " + processName); + pw.println(prefix + "time: " + time); + + switch (type) { + case TYPE_CRASH: + crashInfo.dump(pw, prefix); + break; + case TYPE_ANR: + anrInfo.dump(pw, prefix); + break; + } + } +} diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index bcc9302..b052c99 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -18,6 +18,7 @@ package android.app; import android.content.ComponentName; import android.content.Intent; +import android.content.IIntentReceiver; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ProviderInfo; @@ -25,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; @@ -230,11 +232,13 @@ public abstract class ApplicationThreadNative extends Binder IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); int testMode = data.readInt(); + boolean restrictedBackupMode = (data.readInt() != 0); Configuration config = Configuration.CREATOR.createFromParcel(data); HashMap<String, IBinder> services = data.readHashMap(null); bindApplication(packageName, info, providers, testName, profileName, - testArgs, testWatcher, testMode, config, services); + testArgs, testWatcher, testMode, restrictedBackupMode, + config, services); return true; } @@ -328,7 +332,34 @@ 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; + } + + case SET_SCHEDULING_GROUP_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + int group = data.readInt(); + setSchedulingGroup(group); + return true; + } + + case SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data); + int backupMode = data.readInt(); + scheduleCreateBackupAgent(appInfo, backupMode); + return true; + } + + case SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data); + scheduleDestroyBackupAgent(appInfo); return true; } } @@ -484,6 +515,24 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } + public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) + throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + app.writeToParcel(data, 0); + data.writeInt(backupMode); + mRemote.transact(SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION, data, null, 0); + data.recycle(); + } + + public final void scheduleDestroyBackupAgent(ApplicationInfo app) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + app.writeToParcel(data, 0); + mRemote.transact(SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION, data, null, 0); + data.recycle(); + } + public final void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException { Parcel data = Parcel.obtain(); @@ -543,7 +592,8 @@ class ApplicationThreadProxy implements IApplicationThread { public final void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, ComponentName testName, String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode, - Configuration config, Map<String, IBinder> services) throws RemoteException { + boolean restrictedBackupMode, Configuration config, + Map<String, IBinder> services) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeString(packageName); @@ -559,6 +609,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeBundle(testArgs); data.writeStrongInterface(testWatcher); data.writeInt(debugMode); + data.writeInt(restrictedBackupMode ? 1 : 0); config.writeToParcel(data, 0); data.writeMap(services); mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null, @@ -663,14 +714,30 @@ 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(); } + + public void setSchedulingGroup(int group) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeInt(group); + mRemote.transact(SET_SCHEDULING_GROUP_TRANSACTION, data, null, + IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/backup/BackupService.java b/core/java/android/app/BackupAgent.java index 50a5921..0ac8a1e 100644 --- a/core/java/android/backup/BackupService.java +++ b/core/java/android/app/BackupAgent.java @@ -14,47 +14,38 @@ * limitations under the License. */ -package android.backup; +package android.app; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; -import android.app.Service; -import android.backup.IBackupService; -import android.content.Intent; +import android.app.IBackupAgent; +import android.backup.BackupDataInput; +import android.backup.BackupDataOutput; +import android.content.Context; +import android.content.ContextWrapper; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; +import java.io.IOException; + /** * This is the central interface between an application and Android's * settings backup mechanism. * - * In order to use the backup service, your application must implement a - * subclass of BackupService, and declare an intent filter - * in the application manifest specifying that your BackupService subclass - * handles the {@link BackupService#SERVICE_ACTION} intent action. For example: - * - * <pre class="prettyprint"> - * <!-- Use the class "MyBackupService" to perform backups for my app --> - * <service android:name=".MyBackupService"> - * <intent-filter> - * <action android:name="android.backup.BackupService.SERVICE" /> - * </intent-filter> - * </service></pre> - * * @hide pending API solidification */ +public abstract class BackupAgent extends ContextWrapper { + private static final String TAG = "BackupAgent"; -public abstract class BackupService extends Service { - /** - * Service Action: Participate in the backup infrastructure. Applications - * that wish to use the Android backup mechanism must provide an exported - * subclass of BackupService and give it an {@link android.content.IntentFilter - * IntentFilter} that accepts this action. - */ - @SdkConstant(SdkConstantType.SERVICE_ACTION) - public static final String SERVICE_ACTION = "android.backup.BackupService.SERVICE"; + public BackupAgent() { + super(null); + } + + public void onCreate() { + } + + public void onDestroy() { + } /** * The application is being asked to write any data changed since the @@ -76,7 +67,7 @@ public abstract class BackupService extends Service { * here after writing the requested data to dataFd. */ public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState); + ParcelFileDescriptor newState) throws IOException; /** * The application is being restored from backup, and should replace any @@ -87,11 +78,17 @@ public abstract class BackupService extends Service { * * @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(ParcelFileDescriptor /* TODO: BackupDataInput */ data, ParcelFileDescriptor newState); + public abstract void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) + throws IOException; // ----- Core implementation ----- @@ -100,38 +97,52 @@ public abstract class BackupService extends Service { * Returns the private interface called by the backup system. Applications will * not typically override this. */ - public IBinder onBind(Intent intent) { - if (intent.getAction().equals(SERVICE_ACTION)) { - return mBinder; - } - return null; + public IBinder onBind() { + return mBinder; } private final IBinder mBinder = new BackupServiceBinder().asBinder(); + /** @hide */ + public void attach(Context context) { + attachBaseContext(context); + } + // ----- IBackupService binder interface ----- - private class BackupServiceBinder extends IBackupService.Stub { + private class BackupServiceBinder extends IBackupAgent.Stub { + private static final String TAG = "BackupServiceBinder"; + public void doBackup(ParcelFileDescriptor oldState, ParcelFileDescriptor data, ParcelFileDescriptor newState) throws RemoteException { // !!! TODO - real implementation; for now just invoke the callbacks directly - Log.v("BackupServiceBinder", "doBackup() invoked"); - BackupDataOutput output = new BackupDataOutput(BackupService.this, - data.getFileDescriptor()); + Log.v(TAG, "doBackup() invoked"); + BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor()); try { - BackupService.this.onBackup(oldState, output, newState); + BackupAgent.this.onBackup(oldState, output, newState); + } catch (IOException ex) { + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw new RuntimeException(ex); } catch (RuntimeException ex) { - Log.d("BackupService", "onBackup (" - + BackupService.this.getClass().getName() + ") threw", ex); + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); throw ex; } } - 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("BackupServiceBinder", "doRestore() invoked"); - BackupService.this.onRestore(data, newState); + Log.v(TAG, "doRestore() invoked"); + BackupDataInput input = new BackupDataInput(data.getFileDescriptor()); + try { + BackupAgent.this.onRestore(input, appVersionCode, newState); + } catch (IOException ex) { + Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw new RuntimeException(ex); + } catch (RuntimeException ex) { + Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw ex; + } } } } diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java index 863cbcc..78bbb4f 100644 --- a/core/java/android/app/DatePickerDialog.java +++ b/core/java/android/app/DatePickerDialog.java @@ -46,7 +46,6 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, private final DatePicker mDatePicker; private final OnDateSetListener mCallBack; private final Calendar mCalendar; - private final java.text.DateFormat mDateFormat; private final java.text.DateFormat mTitleDateFormat; private final String[] mWeekDays; @@ -108,7 +107,6 @@ public class DatePickerDialog extends AlertDialog implements OnClickListener, DateFormatSymbols symbols = new DateFormatSymbols(); mWeekDays = symbols.getShortWeekdays(); - mDateFormat = DateFormat.getMediumDateFormat(context); mTitleDateFormat = java.text.DateFormat. getDateInstance(java.text.DateFormat.FULL); mCalendar = Calendar.getInstance(); diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index b09a57f..222fe75 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -16,32 +16,34 @@ package android.app; +import com.android.internal.policy.PolicyManager; + import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.os.Bundle; import android.util.Config; import android.util.Log; import android.view.ContextMenu; import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.LayoutInflater; import android.view.Window; import android.view.WindowManager; import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; - -import com.android.internal.policy.PolicyManager; +import android.view.ViewGroup.LayoutParams; +import android.view.accessibility.AccessibilityEvent; import java.lang.ref.WeakReference; @@ -81,6 +83,7 @@ public class Dialog implements DialogInterface, Window.Callback, * {@hide} */ protected boolean mCancelable = true; + private Message mCancelMessage; private Message mDismissMessage; @@ -209,7 +212,9 @@ public class Dialog implements DialogInterface, Window.Callback, if (mShowing) { if (Config.LOGV) Log.v(LOG_TAG, "[Dialog] start: already showing, ignore"); - if (mDecor != null) mDecor.setVisibility(View.VISIBLE); + if (mDecor != null) { + mDecor.setVisibility(View.VISIBLE); + } return; } @@ -236,7 +241,9 @@ public class Dialog implements DialogInterface, Window.Callback, * Hide the dialog, but do not dismiss it. */ public void hide() { - if (mDecor != null) mDecor.setVisibility(View.GONE); + if (mDecor != null) { + mDecor.setVisibility(View.GONE); + } } /** @@ -266,6 +273,7 @@ public class Dialog implements DialogInterface, Window.Callback, } mWindowManager.removeView(mDecor); + mDecor = null; mWindow.closeAllPanels(); onStop(); @@ -280,7 +288,7 @@ public class Dialog implements DialogInterface, Window.Callback, Message.obtain(mDismissMessage).sendToTarget(); } } - + // internal method to make sure mcreated is set properly without requiring // users to call through to super in onCreate void dispatchOnCreate(Bundle savedInstanceState) { @@ -608,6 +616,18 @@ public class Dialog implements DialogInterface, Window.Callback, return onTrackballEvent(ev); } + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + event.setClassName(getClass().getName()); + event.setPackageName(mContext.getPackageName()); + + LayoutParams params = getWindow().getAttributes(); + boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) && + (params.height == LayoutParams.FILL_PARENT); + event.setFullScreen(isFullScreen); + + return false; + } + /** * @see Activity#onCreatePanelView(int) */ diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java new file mode 100644 index 0000000..d89db96 --- /dev/null +++ b/core/java/android/app/FullBackupAgent.java @@ -0,0 +1,58 @@ +package android.app; + +import android.backup.BackupDataInput; +import android.backup.BackupDataOutput; +import android.backup.FileBackupHelper; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Backs up an application's entire /data/data/<package>/... file system. This + * class is used by the desktop full backup mechanism and is not intended for direct + * use by applications. + * + * {@hide} + */ + +public class FullBackupAgent extends BackupAgent { + // !!! TODO: turn off debugging + private static final String TAG = "FullBackupAgent"; + private static final boolean DEBUG = true; + + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) { + LinkedList<File> dirsToScan = new LinkedList<File>(); + ArrayList<String> allFiles = new ArrayList<String>(); + + // build the list of files in the app's /data/data tree + dirsToScan.add(getFilesDir()); + if (DEBUG) Log.v(TAG, "Backing up dir tree @ " + getFilesDir().getAbsolutePath() + " :"); + while (dirsToScan.size() > 0) { + File dir = dirsToScan.removeFirst(); + File[] contents = dir.listFiles(); + if (contents != null) { + for (File f : contents) { + if (f.isDirectory()) { + dirsToScan.add(f); + } else if (f.isFile()) { + if (DEBUG) Log.v(TAG, " " + f.getAbsolutePath()); + allFiles.add(f.getAbsolutePath()); + } + } + } + } + + // That's the file set; now back it all up + FileBackupHelper helper = new FileBackupHelper(this, (String[])allFiles.toArray()); + helper.performBackup(oldState, data, newState); + } + + @Override + 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 56b29c1..3ec7938 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -21,6 +21,9 @@ import android.content.ContentProviderNative; import android.content.IContentProvider; import android.content.Intent; import android.content.IntentFilter; +import android.content.IIntentSender; +import android.content.IIntentReceiver; +import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.ProviderInfo; @@ -44,9 +47,30 @@ import java.util.List; * {@hide} */ public interface IActivityManager extends IInterface { + /** + * Returned by startActivity() if the start request was canceled because + * app switches are temporarily canceled to ensure the user's last request + * (such as pressing home) is performed. + */ + public static final int START_SWITCHES_CANCELED = 4; + /** + * Returned by startActivity() if an activity wasn't really started, but + * the given Intent was given to the existing top activity. + */ public static final int START_DELIVERED_TO_TOP = 3; + /** + * Returned by startActivity() if an activity wasn't really started, but + * a task was simply brought to the foreground. + */ public static final int START_TASK_TO_FRONT = 2; + /** + * Returned by startActivity() if the caller asked that the Intent not + * be executed if it is the recipient, and that is indeed the case. + */ public static final int START_RETURN_INTENT_TO_CALLER = 1; + /** + * Activity was started successfully as normal. + */ public static final int START_SUCCESS = 0; public static final int START_INTENT_NOT_RESOLVED = -1; public static final int START_CLASS_NOT_FOUND = -2; @@ -128,6 +152,11 @@ public interface IActivityManager extends IInterface { public void serviceDoneExecuting(IBinder token) throws RemoteException; public IBinder peekService(Intent service, String resolvedType) throws RemoteException; + public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode) + throws RemoteException; + public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException; + public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException; + public boolean startInstrumentation(ComponentName className, String profileFile, int flags, Bundle arguments, IInstrumentationWatcher watcher) throws RemoteException; @@ -221,10 +250,13 @@ 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; + public void stopAppSwitches() throws RemoteException; + public void resumeAppSwitches() throws RemoteException; + /* * Private non-Binder interfaces */ @@ -371,4 +403,9 @@ public interface IActivityManager extends IInterface { int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84; int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85; int SHUTDOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+86; + int STOP_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+87; + int RESUME_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+88; + int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89; + int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90; + int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91; } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 9f3534b..c0bc2a0 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -18,12 +18,14 @@ package android.app; import android.content.ComponentName; import android.content.Intent; +import android.content.IIntentReceiver; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; 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; @@ -59,6 +61,11 @@ public interface IApplicationThread extends IInterface { int configChanges) throws RemoteException; void scheduleReceiver(Intent intent, ActivityInfo info, int resultCode, String data, Bundle extras, boolean sync) throws RemoteException; + static final int BACKUP_MODE_INCREMENTAL = 0; + static final int BACKUP_MODE_FULL = 1; + static final int BACKUP_MODE_RESTORE = 2; + void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) throws RemoteException; + void scheduleDestroyBackupAgent(ApplicationInfo app) throws RemoteException; void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException; void scheduleBindService(IBinder token, Intent intent, boolean rebind) throws RemoteException; @@ -71,8 +78,8 @@ public interface IApplicationThread extends IInterface { static final int DEBUG_WAIT = 2; void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, ComponentName testName, String profileName, Bundle testArguments, - IInstrumentationWatcher testWatcher, int debugMode, Configuration config, Map<String, - IBinder> services) throws RemoteException; + IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode, + Configuration config, Map<String, IBinder> services) throws RemoteException; void scheduleExit() throws RemoteException; void requestThumbnail(IBinder token) throws RemoteException; void scheduleConfigurationChanged(Configuration config) throws RemoteException; @@ -86,8 +93,10 @@ 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"; int SCHEDULE_PAUSE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; @@ -117,4 +126,7 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25; int REQUEST_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26; int PROFILER_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27; + int SET_SCHEDULING_GROUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28; + int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29; + int SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30; } diff --git a/core/java/android/backup/IBackupService.aidl b/core/java/android/app/IBackupAgent.aidl index 1bde8ea..9b0550f 100644 --- a/core/java/android/backup/IBackupService.aidl +++ b/core/java/android/app/IBackupAgent.aidl @@ -14,18 +14,18 @@ * limitations under the License. */ -package android.backup; +package android.app; import android.os.ParcelFileDescriptor; /** * Interface presented by applications being asked to participate in the * backup & restore mechanism. End user code does not typically implement - * this interface; they subclass BackupService instead. + * this interface; they subclass BackupAgent instead. * * {@hide} */ -interface IBackupService { +interface IBackupAgent { /** * Request that the app perform an incremental backup. * @@ -51,9 +51,14 @@ interface IBackupService { * 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/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl index 39eb4f1..e8bd60a 100644 --- a/core/java/android/app/ISearchManager.aidl +++ b/core/java/android/app/ISearchManager.aidl @@ -16,11 +16,28 @@ package android.app; +import android.app.ISearchManagerCallback; import android.content.ComponentName; +import android.content.res.Configuration; +import android.os.Bundle; import android.server.search.SearchableInfo; /** @hide */ interface ISearchManager { SearchableInfo getSearchableInfo(in ComponentName launchActivity, boolean globalSearch); List<SearchableInfo> getSearchablesInGlobalSearch(); + List<SearchableInfo> getSearchablesForWebSearch(); + SearchableInfo getDefaultSearchableForWebSearch(); + void setDefaultWebSearch(in ComponentName component); + void startSearch(in String initialQuery, + boolean selectInitialQuery, + in ComponentName launchActivity, + in Bundle appSearchData, + boolean globalSearch, + ISearchManagerCallback searchManagerCallback); + void stopSearch(); + boolean isVisible(); + Bundle onSaveInstanceState(); + void onRestoreInstanceState(in Bundle savedInstanceState); + void onConfigurationChanged(in Configuration newConfig); } diff --git a/core/java/android/app/ISearchManagerCallback.aidl b/core/java/android/app/ISearchManagerCallback.aidl new file mode 100644 index 0000000..bdfb2ba --- /dev/null +++ b/core/java/android/app/ISearchManagerCallback.aidl @@ -0,0 +1,23 @@ +/** + * 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.app; + +/** @hide */ +oneway interface ISearchManagerCallback { + void onDismiss(); + void onCancel(); +} diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index f6a28b2..e31f4f8 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -446,13 +446,13 @@ public class Instrumentation { if (ai == null) { throw new RuntimeException("Unable to resolve activity for: " + intent); } - if (!ai.applicationInfo.processName.equals( - getTargetContext().getPackageName())) { + String myProc = mThread.getProcessName(); + if (!ai.processName.equals(myProc)) { // todo: if this intent is ambiguous, look here to see if // there is a single match that is in our package. - throw new RuntimeException("Intent resolved to different package " - + ai.applicationInfo.packageName + ": " - + intent); + throw new RuntimeException("Intent in process " + + myProc + " resolved to different process " + + ai.processName + ": " + intent); } intent.setComponent(new ComponentName( diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java index 8d249da..accdda9 100644 --- a/core/java/android/app/LauncherActivity.java +++ b/core/java/android/app/LauncherActivity.java @@ -60,26 +60,20 @@ public abstract class LauncherActivity extends ListActivity { * An item in the list */ public static class ListItem { + public ResolveInfo resolveInfo; public CharSequence label; - //public CharSequence description; public Drawable icon; public String packageName; public String className; public Bundle extras; ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) { + this.resolveInfo = resolveInfo; label = resolveInfo.loadLabel(pm); if (label == null && resolveInfo.activityInfo != null) { label = resolveInfo.activityInfo.name; } - /* - if (resolveInfo.activityInfo != null && - resolveInfo.activityInfo.applicationInfo != null) { - description = resolveInfo.activityInfo.applicationInfo.loadDescription(pm); - } - */ - icon = resizer.createIconThumbnail(resolveInfo.loadIcon(pm)); packageName = resolveInfo.activityInfo.applicationInfo.packageName; className = resolveInfo.activityInfo.name; @@ -122,6 +116,14 @@ public abstract class LauncherActivity extends ListActivity { return intent; } + public ListItem itemForPosition(int position) { + if (mActivitiesList == null) { + return null; + } + + return mActivitiesList.get(position); + } + public int getCount() { return mActivitiesList != null ? mActivitiesList.size() : 0; } @@ -354,6 +356,16 @@ public abstract class LauncherActivity extends ListActivity { } /** + * Return the {@link ListItem} for a specific position in our + * {@link android.widget.ListView}. + * @param position The item to return + */ + protected ListItem itemForPosition(int position) { + ActivityAdapter adapter = (ActivityAdapter) mAdapter; + return adapter.itemForPosition(position); + } + + /** * Get the base intent to use when running * {@link PackageManager#queryIntentActivities(Intent, int)}. */ diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index cb660c7..f9c38f9 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -18,6 +18,9 @@ package android.app; import android.content.Context; import android.content.Intent; +import android.content.IIntentReceiver; +import android.content.IIntentSender; +import android.content.IntentSender; import android.os.Bundle; import android.os.RemoteException; import android.os.Handler; @@ -105,7 +108,7 @@ public final class PendingIntent implements Parcelable { public CanceledException(Exception cause) { super(cause); } - }; + } /** * Callback interface for discovering when a send operation has @@ -270,6 +273,21 @@ public final class PendingIntent implements Parcelable { return null; } + private class IntentSenderWrapper extends IntentSender { + protected IntentSenderWrapper(IIntentSender target) { + super(target); + } + } + /** + * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent + * + * @return Returns a IntentSender object that wraps the sender of PendingIntent + * + */ + public IntentSender getIntentSender() { + return new IntentSenderWrapper(mTarget); + } + /** * Cancel a currently active PendingIntent. Only the original application * owning an PendingIntent can cancel it. diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 343380c..fdb619a 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -24,6 +24,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ContentResolver; +import android.content.ContentValues; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -32,6 +34,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Animatable; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; @@ -41,8 +44,10 @@ 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; import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; @@ -51,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; @@ -67,8 +73,8 @@ import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; /** - * In-application-process implementation of Search Bar. This is still controlled by the - * SearchManager, but it runs in the current activity's process to keep things lighter weight. + * System search dialog. This is controlled by the + * SearchManagerService and runs in the system process. * * @hide */ @@ -82,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; @@ -103,6 +107,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private Button mGoButton; private ImageButton mVoiceButton; private View mSearchPlate; + private Drawable mWorkingSpinner; // interaction with searchable application private SearchableInfo mSearchable; @@ -129,9 +134,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private SuggestionsAdapter mSuggestionsAdapter; // Whether to rewrite queries when selecting suggestions - // TODO: This is disabled because of problems with persistent selections - // causing non-user-initiated rewrites. - private static final boolean REWRITE_QUERIES = false; + private static final boolean REWRITE_QUERIES = true; // The query entered by the user. This is not changed when selecting a suggestion // that modifies the contents of the text field. But if the user then edits @@ -142,14 +145,17 @@ 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. * * @param context Application Context we can use for system acess */ public SearchDialog(Context context) { - super(context, com.android.internal.R.style.Theme_SearchBar); + super(context, com.android.internal.R.style.Theme_GlobalSearchBar); } /** @@ -160,17 +166,17 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Window theWindow = getWindow(); - theWindow.setGravity(Gravity.TOP|Gravity.FILL_HORIZONTAL); - setContentView(com.android.internal.R.layout.search_bar); - theWindow.setLayout(ViewGroup.LayoutParams.FILL_PARENT, - // taking up the whole window (even when transparent) is less than ideal, - // but necessary to show the popup window until the window manager supports - // having windows anchored by their parent but not clipped by them. - ViewGroup.LayoutParams.FILL_PARENT); + Window theWindow = getWindow(); WindowManager.LayoutParams lp = theWindow.getAttributes(); + lp.type = WindowManager.LayoutParams.TYPE_SEARCH_BAR; + lp.width = ViewGroup.LayoutParams.FILL_PARENT; + // taking up the whole window (even when transparent) is less than ideal, + // but necessary to show the popup window until the window manager supports + // having windows anchored by their parent but not clipped by them. + lp.height = ViewGroup.LayoutParams.FILL_PARENT; + lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; theWindow.setAttributes(lp); @@ -182,6 +188,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn); mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn); mSearchPlate = findViewById(com.android.internal.R.id.search_plate); + mWorkingSpinner = getContext().getResources(). + getDrawable(com.android.internal.R.drawable.search_spinner); // attach listeners mSearchAutoComplete.addTextChangedListener(mTextWatcher); @@ -213,10 +221,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // Save voice intent for later queries/launching mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); + mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + mSearchAutoCompleteImeOptions = mSearchAutoComplete.getImeOptions(); } /** @@ -226,20 +238,21 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ public boolean show(String initialQuery, boolean selectInitialQuery, ComponentName componentName, Bundle appSearchData, boolean globalSearch) { - if (isShowing()) { - // race condition - already showing but not handling events yet. - // in this case, just discard the "show" request - return true; - } - + // Reset any stored values from last time dialog was shown. mStoredComponentName = null; mStoredAppSearchData = null; - - return doShow(initialQuery, selectInitialQuery, componentName, appSearchData, globalSearch); + + boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData, + globalSearch); + if (success) { + // Display the drop down as soon as possible instead of waiting for the rest of the + // pending UI stuff to get done, so that things appear faster to the user. + mSearchAutoComplete.showDropDownAfterLayout(); + } + return success; } - /** * Called in response to a press of the hard search button in * {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app @@ -309,15 +322,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. @@ -332,7 +347,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(). @@ -345,6 +360,21 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.showSoftInputUnchecked(0, null); } + + // The Dialog uses a ContextThemeWrapper for the context; use this to change the + // theme out from underneath us, between the global search theme and the in-app + // search theme. They are identical except that the global search theme does not + // dim the background of the window (because global search is full screen so it's + // not needed and this should save a little bit of time on global search invocation). + Object context = getContext(); + if (context instanceof ContextThemeWrapper) { + ContextThemeWrapper wrapper = (ContextThemeWrapper) context; + if (globalSearch) { + wrapper.setTheme(com.android.internal.R.style.Theme_GlobalSearchBar); + } else { + wrapper.setTheme(com.android.internal.R.style.Theme_SearchBar); + } + } show(); } @@ -372,11 +402,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS public void onStop() { super.onStop(); - // TODO: Removing the listeners means that they never get called, since - // Dialog.dismissDialog() calls onStop() before sendDismissMessage(). - setOnCancelListener(null); - setOnDismissListener(null); - // stop receiving broadcasts (throws exception if none registered) try { getContext().unregisterReceiver(mBroadcastReceiver); @@ -394,6 +419,24 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mUserQuery = null; mPreviousComponents = null; } + + /** + * Sets the search dialog to the 'working' state, which shows a working spinner in the + * right hand size of the text field. + * + * @param working true to show spinner, false to hide spinner + */ + public void setWorking(boolean working) { + if (working) { + mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds( + null, null, mWorkingSpinner, null); + ((Animatable) mWorkingSpinner).start(); + } else { + mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds( + null, null, null, null); + ((Animatable) mWorkingSpinner).stop(); + } + } /** * Closes and gets rid of the suggestions adapter. @@ -412,8 +455,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 @@ -424,20 +465,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; } @@ -451,45 +483,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; - } } /** @@ -534,7 +548,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } } mSearchAutoComplete.setInputType(inputType); - mSearchAutoComplete.setImeOptions(mSearchable.getImeOptions()); + mSearchAutoCompleteImeOptions = mSearchable.getImeOptions(); + mSearchAutoComplete.setImeOptions(mSearchAutoCompleteImeOptions); } } @@ -547,24 +562,20 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchAutoComplete.setDropDownAnimationStyle(0); // no animation mSearchAutoComplete.setThreshold(mSearchable.getSuggestThreshold()); + // we dismiss the entire dialog instead + mSearchAutoComplete.setDropDownDismissedOnCompletion(false); if (mGlobalSearchMode) { mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in - mSearchAutoComplete.setDropDownDismissedOnCompletion(false); - mSearchAutoComplete.setDropDownBackgroundResource( - com.android.internal.R.drawable.search_dropdown_background); } else { mSearchAutoComplete.setDropDownAlwaysVisible(false); - mSearchAutoComplete.setDropDownDismissedOnCompletion(true); - mSearchAutoComplete.setDropDownBackgroundResource( - com.android.internal.R.drawable.search_dropdown_background_apps); } // attach the suggestions adapter, if suggestions are available // The existence of a suggestions authority is the proxy for "suggestions available here" if (mSearchable.getSuggestAuthority() != null) { - mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, - mOutsideDrawablesCache); + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), this, mSearchable, + mOutsideDrawablesCache, mGlobalSearchMode); mSearchAutoComplete.setAdapter(mSuggestionsAdapter); } } @@ -597,7 +608,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchPlate.getPaddingBottom()); } else { PackageManager pm = getContext().getPackageManager(); - Drawable icon = null; + Drawable icon; try { ActivityInfo info = pm.getActivityInfo(mLaunchComponent, 0); icon = pm.getApplicationIcon(info.applicationInfo); @@ -765,7 +776,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()); + } + } + } }; /** @@ -903,6 +931,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. */ @@ -932,7 +986,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) { @@ -1069,7 +1135,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ protected void launchQuerySearch(int actionKey, String actionMsg) { String query = mSearchAutoComplete.getText().toString(); - Intent intent = createIntent(Intent.ACTION_SEARCH, null, query, null, + Intent intent = createIntent(Intent.ACTION_SEARCH, null, null, query, null, actionKey, actionMsg); launchIntent(intent); } @@ -1097,15 +1163,121 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS protected boolean launchSuggestion(int position, int actionKey, String actionMsg) { Cursor c = mSuggestionsAdapter.getCursor(); if ((c != null) && c.moveToPosition(position)) { + Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); + + // report back about the click + if (mGlobalSearchMode) { + // in global search mode, do it via cursor + mSuggestionsAdapter.callCursorOnClick(c, position); + } else if (intent != null + && mPreviousComponents != null + && !mPreviousComponents.isEmpty()) { + // in-app search (and we have pivoted in as told by mPreviousComponents, + // which is used for keeping track of what we pop back to when we are pivoting into + // in app search.) + reportInAppClickToGlobalSearch(c, intent); + } + + // launch the intent launchIntent(intent); + return true; } return false; } - + + /** + * Report a click from an in app search result back to global search for shortcutting porpoises. + * + * @param c The cursor that is pointing to the clicked position. + * @param intent The intent that will be launched for the click. + */ + private void reportInAppClickToGlobalSearch(Cursor c, Intent intent) { + // for in app search, still tell global search via content provider + Uri uri = getClickReportingUri(); + final ContentValues cv = new ContentValues(); + cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_QUERY, mUserQuery); + final ComponentName source = mSearchable.getSearchActivity(); + cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_COMPONENT, source.flattenToShortString()); + + // grab the intent columns from the intent we created since it has additional + // logic for falling back on the searchable default + cv.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, intent.getAction()); + cv.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, intent.getDataString()); + cv.put(SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME, + intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY)); + + // ensure the icons will work for global search + cv.put(SearchManager.SUGGEST_COLUMN_ICON_1, + wrapIconForPackage( + source, + getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1))); + cv.put(SearchManager.SUGGEST_COLUMN_ICON_2, + wrapIconForPackage( + source, + getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_2))); + + // the rest can be passed through directly + cv.put(SearchManager.SUGGEST_COLUMN_FORMAT, + getColumnString(c, SearchManager.SUGGEST_COLUMN_FORMAT)); + cv.put(SearchManager.SUGGEST_COLUMN_TEXT_1, + getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_1)); + cv.put(SearchManager.SUGGEST_COLUMN_TEXT_2, + getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_2)); + cv.put(SearchManager.SUGGEST_COLUMN_QUERY, + getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY)); + cv.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, + getColumnString(c, SearchManager.SUGGEST_COLUMN_SHORTCUT_ID)); + // note: deliberately omitting background color since it is only for global search + // "more results" entries + mContext.getContentResolver().insert(uri, cv); + } + /** - * Launches an intent. Also dismisses the search dialog if not in global search mode. + * @return A URI appropriate for reporting a click. + */ + private Uri getClickReportingUri() { + Uri.Builder uriBuilder = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SearchManager.SEARCH_CLICK_REPORT_AUTHORITY); + + uriBuilder.appendPath(SearchManager.SEARCH_CLICK_REPORT_URI_PATH); + + return uriBuilder + .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .fragment("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .build(); + } + + /** + * Wraps an icon for a particular package. If the icon is a resource id, it is converted into + * an android.resource:// URI. + * + * @param source The source of the icon + * @param icon The icon retrieved from a suggestion column + * @return An icon string appropriate for the package. + */ + private String wrapIconForPackage(ComponentName source, String icon) { + if (icon == null || icon.length() == 0 || "0".equals(icon)) { + // SearchManager specifies that null or zero can be returned to indicate + // no icon. We also allow empty string. + return null; + } else if (!Character.isDigit(icon.charAt(0))){ + return icon; + } else { + String packageName = source.getPackageName(); + return new Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(packageName) + .encodedPath(icon) + .toString(); + } + } + + /** + * Launches an intent and dismisses the search dialog (unless the intent + * is one of the special intents that modifies the state of the search dialog). */ private void launchIntent(Intent intent) { if (intent == null) { @@ -1114,9 +1286,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (handleSpecialIntent(intent)){ return; } - if (!mGlobalSearchMode) { - dismiss(); - } + dismiss(); getContext().startActivity(intent); } @@ -1130,15 +1300,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.equals(action)) { handleChangeSourceIntent(intent); return true; - } else if (SearchManager.INTENT_ACTION_CURSOR_RESPOND.equals(action)) { - handleCursorRespondIntent(intent); - return true; } return false; } /** - * Handles SearchManager#INTENT_ACTION_CHANGE_SOURCE. + * Handles {@link SearchManager#INTENT_ACTION_CHANGE_SEARCH_SOURCE}. */ private void handleChangeSourceIntent(Intent intent) { Uri dataUri = intent.getData(); @@ -1162,18 +1329,16 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS String query = intent.getStringExtra(SearchManager.QUERY); setUserQuery(query); + mSearchAutoComplete.showDropDown(); } - + /** - * Handles {@link SearchManager#INTENT_ACTION_CURSOR_RESPOND}. + * Sets the list item selection in the AutoCompleteTextView's ListView. */ - private void handleCursorRespondIntent(Intent intent) { - Cursor c = mSuggestionsAdapter.getCursor(); - if (c != null) { - c.respond(intent.getExtras()); - } + public void setListSelection(int index) { + mSearchAutoComplete.setListSelection(index); } - + /** * Saves the previous component that was searched, so that we can go * back to it. @@ -1243,6 +1408,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS try { // use specific action if supplied, or default action if supplied, or fixed default String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION); + + // some items are display only, or have effect via the cursor respond click reporting. + if (SearchManager.INTENT_ACTION_NONE.equals(action)) { + return null; + } + if (action == null) { action = mSearchable.getSuggestIntentAction(); } @@ -1264,11 +1435,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } Uri dataUri = (data == null) ? null : Uri.parse(data); - String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); - + String componentName = getColumnString( + c, SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME); + String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); + String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); - return createIntent(action, dataUri, query, extraData, actionKey, actionMsg); + return createIntent(action, dataUri, extraData, query, componentName, actionKey, + actionMsg); } catch (RuntimeException e ) { int rowNum; try { // be really paranoid now @@ -1287,27 +1461,33 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * * @param action Intent action. * @param data Intent data, or <code>null</code>. - * @param query Intent query, or <code>null</code>. * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>. + * @param query Intent query, or <code>null</code>. + * @param componentName Data for {@link SearchManager#COMPONENT_NAME_KEY} or <code>null</code>. * @param actionKey The key code of the action key that was pressed, * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. * @param actionMsg The message for the action key that was pressed, * or <code>null</code> if none. * @return The intent. */ - private Intent createIntent(String action, Uri data, String query, String extraData, - int actionKey, String actionMsg) { + private Intent createIntent(String action, Uri data, String extraData, String query, + String componentName, int actionKey, String actionMsg) { // Now build the Intent Intent intent = new Intent(action); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (data != null) { intent.setData(data); } + intent.putExtra(SearchManager.USER_QUERY, mUserQuery); if (query != null) { intent.putExtra(SearchManager.QUERY, query); } if (extraData != null) { intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); } + if (componentName != null) { + intent.putExtra(SearchManager.COMPONENT_NAME_KEY, componentName); + } if (mAppSearchData != null) { intent.putExtra(SearchManager.APP_DATA, mAppSearchData); } @@ -1383,20 +1563,22 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private boolean isEmpty() { return TextUtils.getTrimmedLength(getText()) == 0; } - + /** - * Clears the entered text. + * We override this method to avoid replacing the query box text + * when a suggestion is clicked. */ - private void clear() { - setText(""); + @Override + protected void replaceText(CharSequence text) { } /** - * We override this method to avoid replacing the query box text - * when a suggestion is clicked. + * We override this method to avoid an extra onItemClick being called on the + * drop-down's OnItemClickListener by {@link AutoCompleteTextView#onKeyUp(int, KeyEvent)} + * when an item is clicked with the trackball. */ @Override - protected void replaceText(CharSequence text) { + public void performCompletion() { } /** diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 3bf37c3..e5ba6a4 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.server.search.SearchableInfo; +import android.util.Log; import android.view.KeyEvent; import java.util.List; @@ -1108,6 +1109,10 @@ import java.util.List; public class SearchManager implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener { + + private static final boolean DBG = false; + private static final String TAG = "SearchManager"; + /** * This is a shortcut definition for the default menu key to use for invoking search. * @@ -1131,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()} @@ -1148,7 +1167,7 @@ public class SearchManager * @hide */ public final static String SOURCE = "source"; - + /** * Intent extra data key: Use this key with Intent.ACTION_SEARCH and * {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()} @@ -1160,12 +1179,66 @@ public class SearchManager public final static String ACTION_KEY = "action_key"; /** + * Intent component name key: This key will be used for the extra populated by the + * {@link #SUGGEST_COLUMN_INTENT_COMPONENT_NAME} column. + * + * {@hide} + */ + public final static String COMPONENT_NAME_KEY = "intent_component_name_key"; + + /** * Intent extra data key: This key will be used for the extra populated by the * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column. + * * {@hide} */ public final static String EXTRA_DATA_KEY = "intent_extra_data_key"; - + + /** + * Defines the constants used in the communication between {@link android.app.SearchDialog} and + * the global search provider via {@link Cursor#respond(android.os.Bundle)}. + * + * @hide + */ + public static class DialogCursorProtocol { + + /** + * The sent bundle will contain this integer key, with a value set to one of the events + * below. + */ + public final static String METHOD = "DialogCursorProtocol.method"; + + /** + * After data has been refreshed. + */ + public final static int POST_REFRESH = 0; + public final static String POST_REFRESH_RECEIVE_ISPENDING + = "DialogCursorProtocol.POST_REFRESH.isPending"; + public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY + = "DialogCursorProtocol.POST_REFRESH.displayNotify"; + + /** + * Just before closing the cursor. + */ + public final static int PRE_CLOSE = 1; + public final static String PRE_CLOSE_SEND_MAX_DISPLAY_POS + = "DialogCursorProtocol.PRE_CLOSE.sendDisplayPosition"; + + /** + * When a position has been clicked. + */ + public final static int CLICK = 2; + public final static String CLICK_SEND_POSITION + = "DialogCursorProtocol.CLICK.sendPosition"; + public final static String CLICK_RECEIVE_SELECTED_POS + = "DialogCursorProtocol.CLICK.receiveSelectedPosition"; + + /** + * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed. + */ + public final static int THRESH_HIT = 3; + } + /** * Intent extra data key: Use this key with Intent.ACTION_SEARCH and * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()} @@ -1210,6 +1283,41 @@ public class SearchManager */ public final static String SHORTCUT_MIME_TYPE = "vnd.android.cursor.item/vnd.android.search.suggest"; + + + /** + * The authority of the provider to report clicks to when a click is detected after pivoting + * into a specific app's search from global search. + * + * In addition to the columns below, the suggestion columns are used to pass along the full + * suggestion so it can be shortcutted. + * + * @hide + */ + public final static String SEARCH_CLICK_REPORT_AUTHORITY = + "com.android.globalsearch.stats"; + + /** + * The path the write goes to. + * + * @hide + */ + public final static String SEARCH_CLICK_REPORT_URI_PATH = "click"; + + /** + * The column storing the query for the click. + * + * @hide + */ + public final static String SEARCH_CLICK_REPORT_COLUMN_QUERY = "query"; + + /** + * The column storing the component name of the application that was pivoted into. + * + * @hide + */ + public final static String SEARCH_CLICK_REPORT_COLUMN_COMPONENT = "component"; + /** * Column name for suggestions cursor. <i>Unused - can be null or column can be omitted.</i> */ @@ -1258,28 +1366,6 @@ public class SearchManager */ public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2"; /** - * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, - * then all suggestions will be provided in a format that includes space for two small icons, - * one at the left and one at the right of each suggestion. The data in the column must - * be a blob that contains a bitmap. - * - * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_1} column. - * - * @hide - */ - public final static String SUGGEST_COLUMN_ICON_1_BITMAP = "suggest_icon_1_bitmap"; - /** - * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, - * then all suggestions will be provided in a format that includes space for two small icons, - * one at the left and one at the right of each suggestion. The data in the column must - * be a blob that contains a bitmap. - * - * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_2} column. - * - * @hide - */ - public final static String SUGGEST_COLUMN_ICON_2_BITMAP = "suggest_icon_2_bitmap"; - /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the action that will be used when * forming the suggestion's intent. If the element is not provided, the action will be taken @@ -1300,13 +1386,24 @@ public class SearchManager */ public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data"; /** + * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> + * this element exists at the given row, this is the data that will be used when + * forming the suggestion's intent. If not provided, the Intent's extra data field will be null. + * This column allows suggestions to provide additional arbitrary data which will be included as + * an extra under the key EXTRA_DATA_KEY. + * + * @hide Pending API council approval. + */ + public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> This column allows suggestions * to provide additional arbitrary data which will be included as an extra under the key - * {@link #EXTRA_DATA_KEY}. - * - * @hide pending API council approval + * {@link #COMPONENT_NAME_KEY}. For use by the global search system only - if other providers + * attempt to use this column, the value will be overwritten by global search. + * + * @hide */ - public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + public final static String SUGGEST_COLUMN_INTENT_COMPONENT_NAME = "suggest_intent_component"; /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, then "/" and this value will be appended to the data @@ -1335,6 +1432,25 @@ public class SearchManager public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id"; /** + * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify the + * cursor item's background color if it needs a non-default background color. A non-zero value + * indicates a valid background color to override the default. + * + * @hide For internal use, not part of the public API. + */ + public final static String SUGGEST_COLUMN_BACKGROUND_COLOR = "suggest_background_color"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify + * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion + * is being refreshed. + * + * @hide Pending API council approval. + */ + public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = + "suggest_spinner_while_refreshing"; + + /** * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion * should not be stored as a shortcut in global search. * @@ -1362,21 +1478,7 @@ public class SearchManager */ public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE = "android.search.action.CHANGE_SEARCH_SOURCE"; - - /** - * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, - * the search dialog will call {@link Cursor#respond(Bundle)} when the - * suggestion is clicked. - * - * The {@link Bundle} argument will be constructed - * in the same way as the "extra" bundle included in an Intent constructed - * from the suggestion. - * - * @hide Pending API council approval. - */ - public final static String INTENT_ACTION_CURSOR_RESPOND - = "android.search.action.CURSOR_RESPOND"; - + /** * Intent action for finding the global search activity. * The global search provider should handle this intent. @@ -1396,21 +1498,53 @@ public class SearchManager = "android.search.action.SEARCH_SETTINGS"; /** + * Intent action for starting a web search provider's settings activity. + * Web search providers should handle this intent if they have provider-specific + * settings to implement. + * + * @hide Pending API council approval. + */ + public final static String INTENT_ACTION_WEB_SEARCH_SETTINGS + = "android.search.action.WEB_SEARCH_SETTINGS"; + + /** + * Intent action broadcasted to inform that the searchables list or default have changed. + * Components should handle this intent if they cache any searchable data and wish to stay + * up to date on changes. + * + * @hide Pending API council approval. + */ + public final static String INTENT_ACTION_SEARCHABLES_CHANGED + = "android.search.action.SEARCHABLES_CHANGED"; + + /** + * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, + * the search dialog will take no action. + * + * @hide + */ + public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH"; + + /** * Reference to the shared system search service. */ - private static ISearchManager sService = getSearchManagerService(); + private static ISearchManager mService; private final Context mContext; - private final Handler mHandler; - - private SearchDialog mSearchDialog; - - private OnDismissListener mDismissListener = null; - private OnCancelListener mCancelListener = null; + + // package private since they are used by the inner class SearchManagerCallback + /* package */ boolean mIsShowing = false; + /* package */ final Handler mHandler; + /* package */ OnDismissListener mDismissListener = null; + /* package */ OnCancelListener mCancelListener = null; + + private final SearchManagerCallback mSearchManagerCallback = new SearchManagerCallback(); /*package*/ SearchManager(Context context, Handler handler) { mContext = context; mHandler = handler; + mService = ISearchManager.Stub.asInterface( + ServiceManager.getService(Context.SEARCH_SERVICE)); } /** @@ -1458,17 +1592,16 @@ public class SearchManager ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) { - - if (mSearchDialog == null) { - mSearchDialog = new SearchDialog(mContext); + if (DBG) debug("startSearch(), mIsShowing=" + mIsShowing); + if (mIsShowing) return; + try { + mIsShowing = true; + // activate the search manager and start it up! + mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData, + globalSearch, mSearchManagerCallback); + } catch (RemoteException ex) { + Log.e(TAG, "startSearch() failed: " + ex); } - - // activate the search manager and start it up! - mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, - globalSearch); - - mSearchDialog.setOnCancelListener(this); - mSearchDialog.setOnDismissListener(this); } /** @@ -1482,9 +1615,16 @@ public class SearchManager * * @see #startSearch */ - public void stopSearch() { - if (mSearchDialog != null) { - mSearchDialog.cancel(); + public void stopSearch() { + if (DBG) debug("stopSearch(), mIsShowing=" + mIsShowing); + if (!mIsShowing) return; + try { + mService.stopSearch(); + // onDismiss will also clear this, but we do it here too since onDismiss() is + // called asynchronously. + mIsShowing = false; + } catch (RemoteException ex) { + Log.e(TAG, "stopSearch() failed: " + ex); } } @@ -1497,33 +1637,33 @@ public class SearchManager * * @hide */ - public boolean isVisible() { - if (mSearchDialog != null) { - return mSearchDialog.isShowing(); - } - return false; + public boolean isVisible() { + if (DBG) debug("isVisible(), mIsShowing=" + mIsShowing); + return mIsShowing; } - + /** - * See {@link #setOnDismissListener} for configuring your activity to monitor search UI state. + * See {@link SearchManager#setOnDismissListener} for configuring your activity to monitor + * search UI state. */ public interface OnDismissListener { /** - * This method will be called when the search UI is dismissed. To make use if it, you must - * implement this method in your activity, and call {@link #setOnDismissListener} to - * register it. + * This method will be called when the search UI is dismissed. To make use of it, you must + * implement this method in your activity, and call + * {@link SearchManager#setOnDismissListener} to register it. */ public void onDismiss(); } /** - * See {@link #setOnCancelListener} for configuring your activity to monitor search UI state. + * See {@link SearchManager#setOnCancelListener} for configuring your activity to monitor + * search UI state. */ public interface OnCancelListener { /** * This method will be called when the search UI is canceled. To make use if it, you must - * implement this method in your activity, and call {@link #setOnCancelListener} to - * register it. + * implement this method in your activity, and call + * {@link SearchManager#setOnCancelListener} to register it. */ public void onCancel(); } @@ -1536,84 +1676,112 @@ public class SearchManager public void setOnDismissListener(final OnDismissListener listener) { mDismissListener = listener; } - - /** - * The callback from the search dialog when dismissed - * @hide - */ - public void onDismiss(DialogInterface dialog) { - if (dialog == mSearchDialog) { - if (mDismissListener != null) { - mDismissListener.onDismiss(); - } - } - } /** * Set or clear the callback that will be invoked whenever the search UI is canceled. * * @param listener The {@link OnCancelListener} to use, or null. */ - public void setOnCancelListener(final OnCancelListener listener) { + public void setOnCancelListener(OnCancelListener listener) { mCancelListener = listener; } - - - /** - * The callback from the search dialog when canceled - * @hide - */ - public void onCancel(DialogInterface dialog) { - if (dialog == mSearchDialog) { - if (mCancelListener != null) { - mCancelListener.onCancel(); + + private class SearchManagerCallback extends ISearchManagerCallback.Stub { + + private final Runnable mFireOnDismiss = new Runnable() { + public void run() { + if (DBG) debug("mFireOnDismiss"); + mIsShowing = false; + if (mDismissListener != null) { + mDismissListener.onDismiss(); + } + } + }; + + private final Runnable mFireOnCancel = new Runnable() { + public void run() { + if (DBG) debug("mFireOnCancel"); + // doesn't need to clear mIsShowing since onDismiss() always gets called too + if (mCancelListener != null) { + mCancelListener.onCancel(); + } } + }; + + public void onDismiss() { + if (DBG) debug("onDismiss()"); + mHandler.post(mFireOnDismiss); + } + + public void onCancel() { + if (DBG) debug("onCancel()"); + mHandler.post(mFireOnCancel); } + + } + + // TODO: remove the DialogInterface interfaces from SearchManager. + // This changes the public API, so I'll do it in a separate change. + public void onCancel(DialogInterface dialog) { + throw new UnsupportedOperationException(); + } + public void onDismiss(DialogInterface dialog) { + throw new UnsupportedOperationException(); } /** - * Save instance state so we can recreate after a rotation. - * + * Saves the state of the search UI. + * + * @return A Bundle containing the state of the search dialog, or {@code null} + * if the search UI is not visible. + * * @hide */ - void saveSearchDialog(Bundle outState, String key) { - if (mSearchDialog != null && mSearchDialog.isShowing()) { - Bundle searchDialogState = mSearchDialog.onSaveInstanceState(); - outState.putBundle(key, searchDialogState); + public Bundle saveSearchDialog() { + if (DBG) debug("saveSearchDialog(), mIsShowing=" + mIsShowing); + if (!mIsShowing) return null; + try { + return mService.onSaveInstanceState(); + } catch (RemoteException ex) { + Log.e(TAG, "onSaveInstanceState() failed: " + ex); + return null; } } /** - * Restore instance state after a rotation. - * + * Restores the state of the search dialog. + * + * @param searchDialogState Bundle to read the state from. + * * @hide */ - void restoreSearchDialog(Bundle inState, String key) { - Bundle searchDialogState = inState.getBundle(key); - if (searchDialogState != null) { - if (mSearchDialog == null) { - mSearchDialog = new SearchDialog(mContext); - } - mSearchDialog.onRestoreInstanceState(searchDialogState); + public void restoreSearchDialog(Bundle searchDialogState) { + if (DBG) debug("restoreSearchDialog(" + searchDialogState + ")"); + if (searchDialogState == null) return; + try { + mService.onRestoreInstanceState(searchDialogState); + } catch (RemoteException ex) { + Log.e(TAG, "onRestoreInstanceState() failed: " + ex); } } - + /** - * Hook for updating layout on a rotation - * + * Update the search dialog after a configuration change. + * + * @param newConfig The new configuration. + * * @hide */ - void onConfigurationChanged(Configuration newConfig) { - if (mSearchDialog != null && mSearchDialog.isShowing()) { - mSearchDialog.onConfigurationChanged(newConfig); + public void onConfigurationChanged(Configuration newConfig) { + if (DBG) debug("onConfigurationChanged(" + newConfig + "), mIsShowing=" + mIsShowing); + if (!mIsShowing) return; + try { + 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. @@ -1625,11 +1793,12 @@ 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); - } catch (RemoteException e) { + return mService.getSearchableInfo(componentName, globalSearch); + } catch (RemoteException ex) { + Log.e(TAG, "getSearchableInfo() failed: " + ex); return null; } } @@ -1639,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; } @@ -1694,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); } /** @@ -1706,11 +1874,65 @@ 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; } } + + /** + * Returns a list of the searchable activities that handle web searches. + * + * @return a list of all searchable activities that handle + * {@link android.content.Intent#ACTION_WEB_SEARCH}. + * + * @hide because SearchableInfo is not part of the API. + */ + public List<SearchableInfo> getSearchablesForWebSearch() { + try { + return mService.getSearchablesForWebSearch(); + } catch (RemoteException e) { + Log.e(TAG, "getSearchablesForWebSearch() failed: " + e); + return null; + } + } + + /** + * Returns the default searchable activity for web searches. + * + * @return searchable information for the activity handling web searches by default. + * + * @hide because SearchableInfo is not part of the API. + */ + public SearchableInfo getDefaultSearchableForWebSearch() { + try { + return mService.getDefaultSearchableForWebSearch(); + } catch (RemoteException e) { + Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e); + return null; + } + } + + /** + * Sets the default searchable activity for web searches. + * + * @param component Name of the component to set as default activity for web searches. + * + * @hide + */ + public void setDefaultWebSearch(ComponentName component) { + try { + mService.setDefaultWebSearch(component); + } catch (RemoteException e) { + Log.e(TAG, "setDefaultWebSearch() failed: " + e); + } + } + + private static void debug(String msg) { + Thread thread = Thread.currentThread(); + Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")"); + } } diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java index 6a02fc9..49c94d1 100644 --- a/core/java/android/app/SuggestionsAdapter.java +++ b/core/java/android/app/SuggestionsAdapter.java @@ -20,62 +20,103 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources.NotFoundException; import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; +import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Bundle; import android.server.search.SearchableInfo; import android.text.Html; import android.text.TextUtils; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; -import android.widget.CursorAdapter; +import android.widget.AbsListView; import android.widget.ImageView; import android.widget.ResourceCursorAdapter; import android.widget.TextView; +import static android.app.SearchManager.DialogCursorProtocol; + import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.util.WeakHashMap; /** * Provides the contents for the suggestion drop-down list.in {@link SearchDialog}. - * + * * @hide */ 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; private WeakHashMap<String, Drawable> mOutsideDrawablesCache; + private boolean mGlobalSearchMode; - // Cached column indexes, updated when the cursor changes. + // Cached column indexes, updated when the cursor changes. private int mFormatCol; private int mText1Col; private int mText2Col; private int mIconName1Col; private int mIconName2Col; - private int mIconBitmap1Col; - private int mIconBitmap2Col; - - public SuggestionsAdapter(Context context, SearchableInfo searchable, - WeakHashMap<String, Drawable> outsideDrawablesCache) { + private int mBackgroundColorCol; + + // This value is stored in SuggestionsAdapter by the SearchDialog to indicate whether + // a particular list item should be selected upon the next call to notifyDataSetChanged. + // This is used to indicate the index of the "More results..." list item so that when + // the data set changes after a click of "More results...", we can correctly tell the + // ListView to scroll to the right line item. It gets reset to NONE every time it + // is consumed. + private int mListItemToSelect = NONE; + static final int NONE = -1; + + // holds the maximum position that has been displayed to the user + int mMaxDisplayed = NONE; + + // holds the position that, when displayed, should result in notifying the cursor + int mDisplayNotifyPos = NONE; + + private final Runnable mStartSpinnerRunnable; + private final Runnable mStopSpinnerRunnable; + + public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable, + WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) { super(context, com.android.internal.R.layout.search_dropdown_item_icons_2line, null, // no initial cursor true); // auto-requery + mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); + mSearchDialog = searchDialog; mSearchable = searchable; - + // set up provider resources (gives us icons, etc.) Context activityContext = mSearchable.getActivityContext(mContext); mProviderContext = mSearchable.getProviderContext(mContext, activityContext); - + mOutsideDrawablesCache = outsideDrawablesCache; + mGlobalSearchMode = globalSearchMode; + + mStartSpinnerRunnable = new Runnable() { + public void run() { + mSearchDialog.setWorking(true); + } + }; + + mStopSpinnerRunnable = new Runnable() { + public void run() { + mSearchDialog.setWorking(false); + } + }; } - + /** * Overridden to always return <code>false</code>, since we cannot be sure that * suggestion sources return stable IDs. @@ -94,20 +135,41 @@ class SuggestionsAdapter extends ResourceCursorAdapter { public Cursor runQueryOnBackgroundThread(CharSequence constraint) { if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); String query = (constraint == null) ? "" : constraint.toString(); + if (!mGlobalSearchMode) { + /** + * for in app search we show the progress spinner until the cursor is returned with + * the results. for global search we manage the progress bar using + * {@link DialogCursorProtocol#POST_REFRESH_RECEIVE_ISPENDING}. + */ + mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable); + } try { - return 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 != null) cursor.getCount(); + return cursor; } catch (RuntimeException e) { Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); return null; + } finally { + if (!mGlobalSearchMode) { + mSearchDialog.getWindow().getDecorView().post(mStopSpinnerRunnable); + } } } - + /** * Cache columns. */ @Override public void changeCursor(Cursor c) { if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")"); + + if (mCursor != null) { + callCursorPreClose(mCursor); + } + super.changeCursor(c); if (c != null) { mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT); @@ -115,21 +177,86 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); - mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP); - mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP); + mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR); + } + } + + /** + * Handle sending and receiving information associated with + * {@link DialogCursorProtocol#PRE_CLOSE}. + * + * @param cursor The cursor to call. + */ + private void callCursorPreClose(Cursor cursor) { + if (!mGlobalSearchMode) return; + final Bundle request = new Bundle(); + request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.PRE_CLOSE); + request.putInt(DialogCursorProtocol.PRE_CLOSE_SEND_MAX_DISPLAY_POS, mMaxDisplayed); + final Bundle response = cursor.respond(request); + + mMaxDisplayed = -1; + } + + @Override + public void notifyDataSetChanged() { + if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged"); + super.notifyDataSetChanged(); + + callCursorPostRefresh(mCursor); + + // look out for the pending item we are supposed to scroll to + if (mListItemToSelect != NONE) { + mSearchDialog.setListSelection(mListItemToSelect); + mListItemToSelect = NONE; } } - + + /** + * Handle sending and receiving information associated with + * {@link DialogCursorProtocol#POST_REFRESH}. + * + * @param cursor The cursor to call. + */ + private void callCursorPostRefresh(Cursor cursor) { + if (!mGlobalSearchMode) return; + final Bundle request = new Bundle(); + request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.POST_REFRESH); + final Bundle response = cursor.respond(request); + + mSearchDialog.setWorking( + response.getBoolean(DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, false)); + + mDisplayNotifyPos = + response.getInt(DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY, -1); + } + + /** + * Tell the cursor which position was clicked, handling sending and receiving information + * associated with {@link DialogCursorProtocol#CLICK}. + * + * @param cursor The cursor + * @param position The position that was clicked. + */ + void callCursorOnClick(Cursor cursor, int position) { + if (!mGlobalSearchMode) return; + final Bundle request = new Bundle(1); + request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK); + request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position); + final Bundle response = cursor.respond(request); + mListItemToSelect = response.getInt( + DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE); + } + /** * Tags the view with cached child view look-ups. */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - View v = super.newView(context, cursor, parent); + View v = new SuggestionItemView(context, cursor); v.setTag(new ChildViewCache(v)); return v; } - + /** * Cache of the child views of drop-drown list items, to avoid looking up the children * each time the contents of a list item are changed. @@ -139,7 +266,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { public final TextView mText2; public final ImageView mIcon1; public final ImageView mIcon2; - + public ChildViewCache(View v) { mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1); mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2); @@ -147,21 +274,38 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2); } } - + @Override public void bindView(View view, Context context, Cursor cursor) { ChildViewCache views = (ChildViewCache) view.getTag(); - boolean isHtml = false; - if (mFormatCol >= 0) { - String format = cursor.getString(mFormatCol); - isHtml = "html".equals(format); + final int pos = cursor.getPosition(); + + // update the maximum position displayed since last refresh + if (pos > mMaxDisplayed) { + mMaxDisplayed = pos; } + + // if the cursor wishes to be notified about this position, send it + if (mGlobalSearchMode && mDisplayNotifyPos != NONE && pos == mDisplayNotifyPos) { + final Bundle request = new Bundle(); + request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.THRESH_HIT); + mCursor.respond(request); + mDisplayNotifyPos = NONE; // only notify the first time + } + + int backgroundColor = 0; + if (mBackgroundColorCol != -1) { + backgroundColor = cursor.getInt(mBackgroundColorCol); + } + ((SuggestionItemView)view).setColor(backgroundColor); + + final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol)); setViewText(cursor, views.mText1, mText1Col, isHtml); setViewText(cursor, views.mText2, mText2Col, isHtml); - setViewIcon(cursor, views.mIcon1, mIconBitmap1Col, mIconName1Col); - setViewIcon(cursor, views.mIcon2, mIconBitmap2Col, mIconName2Col); + setViewIcon(cursor, views.mIcon1, mIconName1Col); + setViewIcon(cursor, views.mIcon2, mIconName2Col); } - + private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) { if (v == null) { return; @@ -173,49 +317,46 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } // Set the text even if it's null, since we need to clear any previous text. v.setText(text); - + if (TextUtils.isEmpty(text)) { v.setVisibility(View.GONE); } else { v.setVisibility(View.VISIBLE); } } - - private void setViewIcon(Cursor cursor, ImageView v, int iconBitmapCol, int iconNameCol) { + + private void setViewIcon(Cursor cursor, ImageView v, int iconNameCol) { if (v == null) { return; } - Drawable drawable = null; - // First try the bitmap column - if (iconBitmapCol >= 0) { - byte[] data = cursor.getBlob(iconBitmapCol); - if (data != null) { - Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); - if (bitmap != null) { - drawable = new BitmapDrawable(bitmap); - } - } - } - // If there was no bitmap, try the icon resource column. - if (drawable == null && iconNameCol >= 0) { - String value = cursor.getString(iconNameCol); - drawable = getDrawableFromResourceValue(value); + if (iconNameCol < 0) { + return; } + String value = cursor.getString(iconNameCol); + Drawable drawable = getDrawableFromResourceValue(value); // Set the icon even if the drawable is null, since we need to clear any // previous icon. v.setImageDrawable(drawable); - + if (drawable == null) { v.setVisibility(View.GONE); } else { v.setVisibility(View.VISIBLE); + + // This is a hack to get any animated drawables (like a 'working' spinner) + // to animate. You have to setVisible true on an AnimationDrawable to get + // it to start animating, but it must first have been false or else the + // call to setVisible will be ineffective. We need to clear up the story + // about animated drawables in the future, see http://b/1878430. + drawable.setVisible(false, false); + drawable.setVisible(true, false); } } - + /** * Gets the text to show in the query field when a suggestion is selected. - * - * @param cursor The Cursor to read the suggestion data from. The Cursor should already + * + * @param cursor The Cursor to read the suggestion data from. The Cursor should already * be moved to the suggestion that is to be read from. * @return The text to show, or <code>null</code> if the query should not be * changed when selecting this suggestion. @@ -225,36 +366,36 @@ class SuggestionsAdapter extends ResourceCursorAdapter { if (cursor == null) { return null; } - + String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY); if (query != null) { return query; } - + if (mSearchable.shouldRewriteQueryFromData()) { String data = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_INTENT_DATA); if (data != null) { return data; } } - + if (mSearchable.shouldRewriteQueryFromText()) { String text1 = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_TEXT_1); if (text1 != null) { return text1; } } - + return null; } - + /** * This method is overridden purely to provide a bit of protection against * flaky content providers. - * + * * @see android.widget.ListAdapter#getView(int, View, ViewGroup) */ - @Override + @Override public View getView(int position, View convertView, ViewGroup parent) { try { return super.getView(position, convertView, parent); @@ -263,28 +404,28 @@ class SuggestionsAdapter extends ResourceCursorAdapter { // Put exception string in item title View v = newView(mContext, mCursor, parent); if (v != null) { - ChildViewCache views = (ChildViewCache) v.getTag(); + ChildViewCache views = (ChildViewCache) v.getTag(); TextView tv = views.mText1; tv.setText(e.toString()); } return v; } } - + /** * Gets a drawable given a value provided by a suggestion provider. - * + * * This value could be just the string value of a resource id * (e.g., "2130837524"), in which case we will try to retrieve a drawable from * the provider's resources. If the value is not an integer, it is - * treated as a Uri and opened with + * treated as a Uri and opened with * {@link ContentResolver#openOutputStream(android.net.Uri, String)}. * * All resources and URIs are read using the suggestion provider's context. * * If the string is not formatted as expected, or no drawable can be found for * the provided value, this method returns null. - * + * * @param drawableId a string like "2130837524", * "android.resource://com.android.alarmclock/2130837524", * or "content://contacts/photos/253". @@ -294,43 +435,58 @@ class SuggestionsAdapter extends ResourceCursorAdapter { if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) { return null; } - + // First, check the cache. Drawable drawable = mOutsideDrawablesCache.get(drawableId); - if (drawable != null) return drawable; + if (drawable != null) { + if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId); + return drawable; + } try { // Not cached, try using it as a plain resource ID in the provider's context. int resourceId = Integer.parseInt(drawableId); drawable = mProviderContext.getResources().getDrawable(resourceId); + if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId); } catch (NumberFormatException nfe) { // The id was not an integer resource id. // Let the ContentResolver handle content, android.resource and file URIs. try { Uri uri = Uri.parse(drawableId); - drawable = Drawable.createFromStream( - mProviderContext.getContentResolver().openInputStream(uri), - null); + InputStream stream = mProviderContext.getContentResolver().openInputStream(uri); + if (stream != null) { + try { + drawable = Drawable.createFromStream(stream, null); + } finally { + try { + stream.close(); + } catch (IOException ex) { + Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex); + } + } + } + if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId); } catch (FileNotFoundException fnfe) { + if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId); // drawable = null; } - + // If we got a drawable for this resource id, then stick it in the // map so we don't do this lookup again. if (drawable != null) { mOutsideDrawablesCache.put(drawableId, drawable); } } catch (NotFoundException nfe) { - // Resource could not be found + if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId); // drawable = null; } - + return drawable; } - + /** * Gets the value of a string column by name. - * + * * @param cursor Cursor to read the value from. * @param columnName The name of the column to read. * @return The value of the given column, or <code>null</null> @@ -338,10 +494,75 @@ class SuggestionsAdapter extends ResourceCursorAdapter { */ public static String getColumnString(Cursor cursor, String columnName) { int col = cursor.getColumnIndex(columnName); - if (col == -1) { + if (col == NONE) { return null; } return cursor.getString(col); } + /** + * A parent viewgroup class which holds the actual suggestion item as a child. + * + * The sole purpose of this class is to draw the given background color when the item is in + * normal state and not draw the background color when it is pressed, so that when pressed the + * list view's selection highlight will be displayed properly (if we draw our background it + * draws on top of the list view selection highlight). + */ + private class SuggestionItemView extends ViewGroup { + private int mBackgroundColor; // the background color to draw in normal state. + private View mView; // the suggestion item's view. + + protected SuggestionItemView(Context context, Cursor cursor) { + // Initialize ourselves + super(context); + mBackgroundColor = 0; // transparent by default. + + // For our layout use the default list item height from the current theme. + TypedValue lineHeight = new TypedValue(); + context.getTheme().resolveAttribute( + com.android.internal.R.attr.searchResultListItemHeight, lineHeight, true); + DisplayMetrics metrics = new DisplayMetrics(); + metrics.setToDefaults(); + AbsListView.LayoutParams layout = new AbsListView.LayoutParams( + AbsListView.LayoutParams.FILL_PARENT, + (int)lineHeight.getDimension(metrics)); + + setLayoutParams(layout); + + // Initialize the child view + mView = SuggestionsAdapter.super.newView(context, cursor, this); + if (mView != null) { + addView(mView, layout.width, layout.height); + mView.setVisibility(View.VISIBLE); + } + } + + public void setColor(int backgroundColor) { + mBackgroundColor = backgroundColor; + } + + @Override + public void dispatchDraw(Canvas canvas) { + if (mBackgroundColor != 0 && !isPressed() && !isSelected()) { + canvas.drawColor(mBackgroundColor); + } + super.dispatchDraw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mView != null) { + mView.measure(widthMeasureSpec, heightMeasureSpec); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mView != null) { + mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); + } + } + } + } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 10c2b02..03e8623 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -26,7 +26,6 @@ import android.widget.RemoteViews; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; @@ -40,7 +39,7 @@ public class AppWidgetHost { static final int HANDLE_UPDATE = 1; static final int HANDLE_PROVIDER_CHANGED = 2; - static Object sServiceLock = new Object(); + final static Object sServiceLock = new Object(); static IAppWidgetService sService; Context mContext; @@ -85,7 +84,7 @@ public class AppWidgetHost { int mHostId; Callbacks mCallbacks = new Callbacks(); - HashMap<Integer,AppWidgetHostView> mViews = new HashMap(); + final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>(); public AppWidgetHost(Context context, int hostId) { mContext = context; @@ -104,8 +103,8 @@ public class AppWidgetHost { * becomes visible, i.e. from onStart() in your Activity. */ public void startListening() { - int[] updatedIds = null; - ArrayList<RemoteViews> updatedViews = new ArrayList(); + int[] updatedIds; + ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); try { if (mPackageName == null) { @@ -209,7 +208,7 @@ public class AppWidgetHost { synchronized (mViews) { mViews.put(appWidgetId, view); } - RemoteViews views = null; + RemoteViews views; try { views = sService.getAppWidgetViews(appWidgetId); } catch (RemoteException e) { @@ -231,6 +230,7 @@ public class AppWidgetHost { /** * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk. */ + @SuppressWarnings({"UnusedDeclaration"}) protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index be0f96e..62d9267 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -22,16 +22,12 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.os.Handler; -import android.os.Message; import android.os.SystemClock; -import android.util.Config; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; import android.widget.FrameLayout; import android.widget.RemoteViews; import android.widget.TextView; @@ -86,6 +82,7 @@ public class AppWidgetHostView extends FrameLayout { * @param animationIn Resource ID of in animation to use * @param animationOut Resource ID of out animation to use */ + @SuppressWarnings({"UnusedDeclaration"}) public AppWidgetHostView(Context context, int animationIn, int animationOut) { super(context); mContext = context; @@ -272,7 +269,7 @@ public class AppWidgetHostView extends FrameLayout { try { if (mInfo != null) { Context theirContext = mContext.createPackageContext( - mInfo.provider.getPackageName(), 0 /* no flags */); + mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED); LayoutInflater inflater = (LayoutInflater) theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater = inflater.cloneInContext(theirContext); diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index eca04b3..3660001 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -21,7 +21,9 @@ import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.widget.RemoteViews; import com.android.internal.appwidget.IAppWidgetService; @@ -187,6 +189,8 @@ public class AppWidgetManager { Context mContext; + private DisplayMetrics mDisplayMetrics; + /** * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context * Context} object. @@ -213,6 +217,7 @@ public class AppWidgetManager { private AppWidgetManager(Context context) { mContext = context; + mDisplayMetrics = context.getResources().getDisplayMetrics(); } /** @@ -292,7 +297,15 @@ public class AppWidgetManager { */ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) { try { - return sService.getAppWidgetInfo(appWidgetId); + AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId); + if (info != null) { + // Converting complex to dp. + info.minWidth = + TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics); + info.minHeight = + TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics); + } + return info; } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); diff --git a/core/java/android/backup/AbsoluteFileBackupHelper.java b/core/java/android/backup/AbsoluteFileBackupHelper.java new file mode 100644 index 0000000..ab24675 --- /dev/null +++ b/core/java/android/backup/AbsoluteFileBackupHelper.java @@ -0,0 +1,66 @@ +/* + * 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.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; +import java.io.FileDescriptor; + +/** + * Like FileBackupHelper, but takes absolute paths for the files instead of + * subpaths of getFilesDir() + * + * @hide + */ +public class AbsoluteFileBackupHelper extends FileBackupHelperBase implements BackupHelper { + private static final String TAG = "AbsoluteFileBackupHelper"; + + Context mContext; + String[] mFiles; + + public AbsoluteFileBackupHelper(Context context, String... files) { + super(context); + + mContext = context; + mFiles = files; + } + + /** + * 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) { + // use the file paths as the keys, too + performBackup_checked(oldState, data, newState, mFiles, mFiles); + } + + 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(key); + writeFile(f, data); + } + } +} + diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java new file mode 100644 index 0000000..69c206c --- /dev/null +++ b/core/java/android/backup/BackupDataInput.java @@ -0,0 +1,117 @@ +/* + * 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 java.io.FileDescriptor; +import java.io.IOException; + +/** @hide */ +public class BackupDataInput { + int mBackupReader; + + private EntityHeader mHeader = new EntityHeader(); + private boolean mHeaderReady; + + private static class EntityHeader { + String key; + int dataSize; + } + + public BackupDataInput(FileDescriptor fd) { + if (fd == null) throw new NullPointerException(); + mBackupReader = ctor(fd); + if (mBackupReader == 0) { + throw new RuntimeException("Native initialization failed with fd=" + fd); + } + } + + protected void finalize() throws Throwable { + try { + dtor(mBackupReader); + } finally { + super.finalize(); + } + } + + public boolean readNextHeader() throws IOException { + int result = readNextHeader_native(mBackupReader, mHeader); + if (result == 0) { + // read successfully + mHeaderReady = true; + return true; + } else if (result > 0) { + // done + mHeaderReady = false; + return false; + } else { + // error + mHeaderReady = false; + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } + + public String getKey() { + if (mHeaderReady) { + return mHeader.key; + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + public int getDataSize() { + if (mHeaderReady) { + return mHeader.dataSize; + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + public int readEntityData(byte[] data, int offset, int size) throws IOException { + if (mHeaderReady) { + int result = readEntityData_native(mBackupReader, data, offset, size); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + public void skipEntityData() throws IOException { + if (mHeaderReady) { + int result = skipEntityData_native(mBackupReader); + if (result >= 0) { + return; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + private native static int ctor(FileDescriptor fd); + private native static void dtor(int mBackupReader); + + private native int readNextHeader_native(int mBackupReader, EntityHeader entity); + private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size); + private native int skipEntityData_native(int mBackupReader); +} diff --git a/core/java/android/backup/BackupDataInputStream.java b/core/java/android/backup/BackupDataInputStream.java new file mode 100644 index 0000000..b705c4c --- /dev/null +++ b/core/java/android/backup/BackupDataInputStream.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.backup; + +import android.util.Log; + +import java.io.InputStream; +import java.io.IOException; + +/** @hide */ +public class BackupDataInputStream extends InputStream { + + String key; + int dataSize; + + BackupDataInput mData; + byte[] mOneByte; + + BackupDataInputStream(BackupDataInput data) { + mData = data; + } + + public int read() throws IOException { + byte[] one = mOneByte; + if (mOneByte == null) { + one = mOneByte = new byte[1]; + } + mData.readEntityData(one, 0, 1); + return one[0]; + } + + public int read(byte[] b, int offset, int size) throws IOException { + return mData.readEntityData(b, offset, size); + } + + public int read(byte[] b) throws IOException { + return mData.readEntityData(b, 0, b.length); + } + + public String getKey() { + return this.key; + } + + public int size() { + return this.dataSize; + } +} + + diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java index 555494e..d29c5ba 100644 --- a/core/java/android/backup/BackupDataOutput.java +++ b/core/java/android/backup/BackupDataOutput.java @@ -19,27 +19,59 @@ package android.backup; import android.content.Context; import java.io.FileDescriptor; +import java.io.IOException; /** @hide */ public class BackupDataOutput { - /* package */ FileDescriptor fd; + int mBackupWriter; public static final int OP_UPDATE = 1; public static final int OP_DELETE = 2; - public BackupDataOutput(Context context, FileDescriptor fd) { - this.fd = fd; + public BackupDataOutput(FileDescriptor fd) { + if (fd == null) throw new NullPointerException(); + mBackupWriter = ctor(fd); + if (mBackupWriter == 0) { + throw new RuntimeException("Native initialization failed with fd=" + fd); + } } - public void close() { - // do we close the fd? + // A dataSize of -1 indicates that the record under this key should be deleted + public int writeEntityHeader(String key, int dataSize) throws IOException { + int result = writeEntityHeader_native(mBackupWriter, key, dataSize); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } } - public native void flush(); - public native void write(byte[] buffer); - public native void write(int oneByte); - public native void write(byte[] buffer, int offset, int count); - public native void writeOperation(int op); - public native void writeKey(String key); + public int writeEntityData(byte[] data, int size) throws IOException { + int result = writeEntityData_native(mBackupWriter, data, size); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } + + public void setKeyPrefix(String keyPrefix) { + setKeyPrefix_native(mBackupWriter, keyPrefix); + } + + protected void finalize() throws Throwable { + try { + dtor(mBackupWriter); + } finally { + 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/BackupHelper.java b/core/java/android/backup/BackupHelper.java new file mode 100644 index 0000000..3983e28 --- /dev/null +++ b/core/java/android/backup/BackupHelper.java @@ -0,0 +1,46 @@ +/* + * 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.os.ParcelFileDescriptor; + +import java.io.InputStream; + +/** @hide */ +public interface BackupHelper { + /** + * 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 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..5d0c4a2 --- /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) throws IOException { + 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/BackupHelperDispatcher.java b/core/java/android/backup/BackupHelperDispatcher.java new file mode 100644 index 0000000..6ccb83e --- /dev/null +++ b/core/java/android/backup/BackupHelperDispatcher.java @@ -0,0 +1,151 @@ +/* + * 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.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.FileDescriptor; +import java.util.TreeMap; +import java.util.Map; + +/** @hide */ +public class BackupHelperDispatcher { + private static final String TAG = "BackupHelperDispatcher"; + + private static class Header { + int chunkSize; // not including the header + String keyPrefix; + } + + TreeMap<String,BackupHelper> mHelpers = new TreeMap<String,BackupHelper>(); + + public BackupHelperDispatcher() { + } + + public void addHelper(String keyPrefix, BackupHelper helper) { + mHelpers.put(keyPrefix, helper); + } + + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + // First, do the helpers that we've already done, since they're already in the state + // file. + int err; + Header header = new Header(); + TreeMap<String,BackupHelper> helpers = (TreeMap<String,BackupHelper>)mHelpers.clone(); + FileDescriptor oldStateFD = null; + FileDescriptor newStateFD = newState.getFileDescriptor(); + + if (oldState != null) { + oldStateFD = oldState.getFileDescriptor(); + while ((err = readHeader_native(header, oldStateFD)) >= 0) { + if (err == 0) { + BackupHelper helper = helpers.get(header.keyPrefix); + Log.d(TAG, "handling existing helper '" + header.keyPrefix + "' " + helper); + if (helper != null) { + doOneBackup(oldState, data, newState, header, helper); + helpers.remove(header.keyPrefix); + } else { + skipChunk_native(oldStateFD, header.chunkSize); + } + } + } + } + + // Then go through and do the rest that we haven't done. + for (Map.Entry<String,BackupHelper> entry: helpers.entrySet()) { + header.keyPrefix = entry.getKey(); + Log.d(TAG, "handling new helper '" + header.keyPrefix + "'"); + BackupHelper helper = entry.getValue(); + doOneBackup(oldState, data, newState, header, helper); + } + } + + private void doOneBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState, Header header, BackupHelper helper) + throws IOException { + int err; + FileDescriptor newStateFD = newState.getFileDescriptor(); + + // allocate space for the header in the file + int pos = allocateHeader_native(header, newStateFD); + if (pos < 0) { + throw new IOException("allocateHeader_native failed (error " + pos + ")"); + } + + data.setKeyPrefix(header.keyPrefix); + + // do the backup + helper.performBackup(oldState, data, newState); + + // fill in the header (seeking back to pos). The file pointer will be returned to + // where it was at the end of performBackup. Header.chunkSize will not be filled in. + err = writeHeader_native(header, newStateFD, pos); + if (err != 0) { + throw new IOException("writeHeader_native failed (error " + err + ")"); + } + } + + public void performRestore(BackupDataInput input, int appVersionCode, + ParcelFileDescriptor newState) + throws IOException { + boolean alreadyComplained = false; + + BackupDataInputStream stream = new BackupDataInputStream(input); + while (input.readNextHeader()) { + + String rawKey = input.getKey(); + int pos = rawKey.indexOf(':'); + if (pos > 0) { + String prefix = rawKey.substring(0, pos); + BackupHelper helper = mHelpers.get(prefix); + if (helper != null) { + stream.dataSize = input.getDataSize(); + stream.key = rawKey.substring(pos+1); + helper.restoreEntity(stream); + } else { + if (!alreadyComplained) { + Log.w(TAG, "Couldn't find helper for: '" + rawKey + "'"); + alreadyComplained = true; + } + } + } else { + if (!alreadyComplained) { + Log.w(TAG, "Entity with no prefix: '" + rawKey + "'"); + alreadyComplained = true; + } + } + input.skipEntityData(); // In case they didn't consume the data. + } + + // Write out the state files -- mHelpers is a TreeMap, so the order is well defined. + for (BackupHelper helper: mHelpers.values()) { + helper.writeRestoreSnapshot(newState); + } + } + + private static native int readHeader_native(Header h, FileDescriptor fd); + private static native int skipChunk_native(FileDescriptor fd, int bytesToSkip); + + private static native int allocateHeader_native(Header h, FileDescriptor fd); + private static native int writeHeader_native(Header h, FileDescriptor fd, int pos); +} + diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java index 6f0b2ee..34a1a0c 100644 --- a/core/java/android/backup/BackupManager.java +++ b/core/java/android/backup/BackupManager.java @@ -19,6 +19,7 @@ package android.backup; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.Log; /** * BackupManager is the interface to the system's backup service. @@ -32,14 +33,24 @@ import android.os.ServiceManager; * until the backup operation actually occurs. * * <p>The backup operation itself begins with the system launching the - * {@link BackupService} subclass declared in your manifest. See the documentation - * for {@link BackupService} for a detailed description of how the backup then proceeds. + * {@link android.app.BackupAgent} subclass declared in your manifest. See the + * documentation for {@link android.app.BackupAgent} for a detailed description + * of how the backup then proceeds. * * @hide pending API solidification */ public class BackupManager { + private static final String TAG = "BackupManager"; + private Context mContext; - private IBackupManager mService; + private static IBackupManager sService; + + private static void checkServiceBinder() { + if (sService == null) { + sService = IBackupManager.Stub.asInterface( + ServiceManager.getService(Context.BACKUP_SERVICE)); + } + } /** * Constructs a BackupManager object through which the application can @@ -51,19 +62,60 @@ public class BackupManager { */ public BackupManager(Context context) { mContext = context; - mService = IBackupManager.Stub.asInterface( - ServiceManager.getService(Context.BACKUP_SERVICE)); } /** * Notifies the Android backup system that your application wishes to back up * new changes to its data. A backup operation using your application's - * {@link BackupService} subclass will be scheduled when you call this method. + * {@link android.app.BackupAgent} subclass will be scheduled when you call this method. */ public void dataChanged() { - try { - mService.dataChanged(mContext.getPackageName()); - } catch (RemoteException e) { + checkServiceBinder(); + if (sService != null) { + try { + sService.dataChanged(mContext.getPackageName()); + } catch (RemoteException e) { + Log.d(TAG, "dataChanged() couldn't connect"); + } + } + } + + /** + * Convenience method for callers who need to indicate that some other package + * needs a backup pass. This can be relevant in the case of groups of packages + * that share a uid, for example. + * + * This method requires that the application hold the "android.permission.BACKUP" + * permission if the package named in the argument is not the caller's own. + */ + public static void dataChanged(String packageName) { + checkServiceBinder(); + if (sService != null) { + try { + sService.dataChanged(packageName); + } catch (RemoteException e) { + Log.d(TAG, "dataChanged(pkg) couldn't connect"); + } + } + } + + /** + * Begin the process of restoring system data from backup. This method requires + * that the application hold the "android.permission.BACKUP" permission, and is + * not public. + * + * {@hide} + */ + public IRestoreSession beginRestoreSession(String transport) { + IRestoreSession binder = null; + checkServiceBinder(); + if (sService != null) { + try { + binder = sService.beginRestoreSession(transport); + } catch (RemoteException e) { + Log.d(TAG, "beginRestoreSession() couldn't connect"); + } } + return binder; } } diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java index 05159dc..4058497 100644 --- a/core/java/android/backup/FileBackupHelper.java +++ b/core/java/android/backup/FileBackupHelper.java @@ -20,54 +20,53 @@ import android.content.Context; import android.os.ParcelFileDescriptor; import android.util.Log; +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; + File mFilesDir; + String[] mFiles; + + public FileBackupHelper(Context context, String... files) { + super(context); + + mContext = context; + mFilesDir = context.getFilesDir(); + mFiles = files; + } + /** * 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 static void performBackup(Context context, - ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState, String[] files) { - String basePath = context.getFilesDir().getAbsolutePath(); - performBackup_checked(basePath, oldState, data, newState, files); - } - - /** - * 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(String basePath, - ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState, String[] files) { - if (files.length == 0) { - return; - } - if (basePath == null) { - throw new NullPointerException(); - } - // oldStateFd can be null - FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null; - if (data.fd == null) { - throw new NullPointerException(); - } - FileDescriptor newStateFd = newState.getFileDescriptor(); - if (newStateFd == null) { - throw new NullPointerException(); + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) { + // file names + String[] files = mFiles; + File base = mContext.getFilesDir(); + final int N = files.length; + String[] fullPaths = new String[N]; + for (int i=0; i<N; i++) { + fullPaths[i] = (new File(base, files[i])).getAbsolutePath(); } - int err = performBackup_native(basePath, oldStateFd, data.fd, newStateFd, files); + // go + performBackup_checked(oldState, data, newState, fullPaths, files); + } - if (err != 0) { - throw new RuntimeException("Backup failed"); // TODO: more here + 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(String basePath, FileDescriptor oldState, - FileDescriptor data, FileDescriptor newState, String[] files); } + diff --git a/core/java/android/backup/FileBackupHelperBase.java b/core/java/android/backup/FileBackupHelperBase.java new file mode 100644 index 0000000..03ae476 --- /dev/null +++ b/core/java/android/backup/FileBackupHelperBase.java @@ -0,0 +1,130 @@ +/* + * 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.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.InputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; + +class FileBackupHelperBase { + private static final String TAG = "RestoreHelperBase"; + + int mPtr; + Context mContext; + boolean mExceptionLogged; + + FileBackupHelperBase(Context context) { + mPtr = ctor(); + mContext = context; + } + + protected void finalize() throws Throwable { + try { + dtor(mPtr); + } finally { + super.finalize(); + } + } + + /** + * 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"); + } + int result = -1; + + // Create the enclosing directory. + File parent = f.getParentFile(); + parent.mkdirs(); + + result = writeFile_native(mPtr, f.getAbsolutePath(), + ((BackupDataInputStream)in).mData.mBackupReader); + if (result != 0) { + // Bail on this entity. Only log one failure per helper object. + if (!mExceptionLogged) { + Log.e(TAG, "Failed restoring file '" + f + "' for app '" + + mContext.getPackageName() + "\' result=0x" + + Integer.toHexString(result)); + mExceptionLogged = true; + } + } + } + + 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/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl index cf22798..9d181be 100644 --- a/core/java/android/backup/IBackupManager.aidl +++ b/core/java/android/backup/IBackupManager.aidl @@ -16,6 +16,8 @@ package android.backup; +import android.backup.IRestoreSession; + /** * Direct interface to the Backup Manager Service that applications invoke on. The only * operation currently needed is a simple notification that the app has made changes to @@ -30,12 +32,102 @@ interface IBackupManager { /** * Tell the system service that the caller has made changes to its * data, and therefore needs to undergo an incremental backup pass. + * + * Any application can invoke this method for its own package, but + * only callers who hold the android.permission.BACKUP permission + * may invoke it for arbitrary packages. + */ + void dataChanged(String packageName); + + /** + * Erase all backed-up data for the given package from the storage + * destination. + * + * Any application can invoke this method for its own package, but + * only callers who hold the android.permission.BACKUP permission + * may invoke it for arbitrary packages. + */ + void clearBackupData(String packageName); + + /** + * Notifies the Backup Manager Service that an agent has become available. This + * method is only invoked by the Activity Manager. + */ + 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. + */ + void agentDisconnected(String packageName); + + /** + * Enable/disable the backup service entirely. When disabled, no backup + * or restore operations will take place. Data-changed notifications will + * still be observed and collected, however, so that changes made while the + * mechanism was disabled will still be backed up properly if it is enabled + * at some point in the future. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + void setBackupEnabled(boolean isEnabled); + + /** + * Indicate that any necessary one-time provisioning has occurred. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + void setBackupProvisioned(boolean isProvisioned); + + /** + * Report whether the backup mechanism is currently enabled. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + boolean isBackupEnabled(); + + /** + * Schedule an immediate backup attempt for all pending updates. This is + * primarily intended for transports to use when they detect a suitable + * opportunity for doing a backup pass. If there are no pending updates to + * be sent, no action will be taken. Even if some updates are pending, the + * transport will still be asked to confirm via the usual requestBackupTime() + * method. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + void backupNow(); + + /** + * Identify the currently selected transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + */ + String getCurrentTransport(); + + /** + * Request a list of all available backup transports' names. Callers must + * hold the android.permission.BACKUP permission to use this method. + */ + String[] listAllTransports(); + + /** + * Specify the current backup transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + * + * @param transport The name of the transport to select. This should be one + * of {@link BackupManager.TRANSPORT_GOOGLE} or {@link BackupManager.TRANSPORT_ADB}. + * @return The name of the previously selected transport. If the given transport + * name is not one of the currently available transports, no change is made to + * the current transport setting and the method returns null. */ - oneway void dataChanged(String packageName); + String selectBackupTransport(String transport); /** - * Schedule a full backup of the given package. - * !!! TODO: protect with a signature-or-system permission? + * Begin a restore session with the given transport (which may differ from the + * currently-active backup transport). + * + * @param transport The name of the transport to use for the restore operation. + * @return An interface to the restore session, or null on error. */ - oneway void scheduleFullBackup(String packageName); + IRestoreSession beginRestoreSession(String transportID); } diff --git a/core/java/android/backup/IRestoreObserver.aidl b/core/java/android/backup/IRestoreObserver.aidl new file mode 100644 index 0000000..59e59fc --- /dev/null +++ b/core/java/android/backup/IRestoreObserver.aidl @@ -0,0 +1,50 @@ +/* + * 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; + +/** + * Callback class for receiving progress reports during a restore operation. + * + * @hide + */ +interface IRestoreObserver { + /** + * The restore operation has begun. + * + * @param numPackages The total number of packages being processed in + * this restore operation. + */ + void restoreStarting(int numPackages); + + /** + * An indication of which package is being restored currently, out of the + * total number provided in the restoreStarting() callback. This method + * is not guaranteed to be called. + * + * @param nowBeingRestored The index, between 1 and the numPackages parameter + * to the restoreStarting() callback, of the package now being restored. + */ + void onUpdate(int nowBeingRestored); + + /** + * The restore operation has completed. + * + * @param error Zero on success; a nonzero error code if the restore operation + * as a whole failed. + */ + void restoreFinished(int error); +} diff --git a/core/java/android/backup/IRestoreSession.aidl b/core/java/android/backup/IRestoreSession.aidl new file mode 100644 index 0000000..2a1fbc1 --- /dev/null +++ b/core/java/android/backup/IRestoreSession.aidl @@ -0,0 +1,55 @@ +/* + * 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.backup.RestoreSet; +import android.backup.IRestoreObserver; + +/** + * Binder interface used by clients who wish to manage a restore operation. Every + * method in this interface requires the android.permission.BACKUP permission. + * + * {@hide} + */ +interface IRestoreSession { + /** + * Ask the current transport what the available restore sets are. + * + * @return A bundle containing two elements: an int array under the key + * "tokens" whose entries are a transport-private identifier for each backup set; + * and a String array under the key "names" whose entries are the user-meaningful + * text corresponding to the backup sets at each index in the tokens array. + */ + RestoreSet[] getAvailableRestoreSets(); + + /** + * Restore the given set onto the device, replacing the current data of any app + * contained in the restore set with the data previously backed up. + * + * @param token The token from {@link getAvailableRestoreSets()} corresponding to + * the restore set that should be used. + * @param observer If non-null, this binder points to an object that will receive + * progress callbacks during the restore operation. + */ + int performRestore(long token, IRestoreObserver observer); + + /** + * End this restore session. After this method is called, the IRestoreSession binder + * is no longer valid. + */ + void endRestoreSession(); +} diff --git a/core/java/android/backup/RestoreSet.aidl b/core/java/android/backup/RestoreSet.aidl new file mode 100644 index 0000000..42e77bf --- /dev/null +++ b/core/java/android/backup/RestoreSet.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.backup; + +parcelable RestoreSet;
\ No newline at end of file diff --git a/core/java/android/backup/RestoreSet.java b/core/java/android/backup/RestoreSet.java new file mode 100644 index 0000000..eeca148 --- /dev/null +++ b/core/java/android/backup/RestoreSet.java @@ -0,0 +1,87 @@ +/* + * 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.os.Parcel; +import android.os.Parcelable; + +/** + * Descriptive information about a set of backed-up app data available for restore. + * Used by IRestoreSession clients. + * + * @hide + */ +public class RestoreSet implements Parcelable { + /** + * Name of this restore set. May be user generated, may simply be the name + * of the handset model, e.g. "T-Mobile G1". + */ + public String name; + + /** + * Identifier of the device whose data this is. This will be as unique as + * is practically possible; for example, it might be an IMEI. + */ + public String device; + + /** + * Token that identifies this backup set unambiguously to the backup/restore + * transport. This is guaranteed to be valid for the duration of a restore + * session, but is meaningless once the session has ended. + */ + public long token; + + + public RestoreSet() { + // Leave everything zero / null + } + + public RestoreSet(String _name, String _dev, long _token) { + name = _name; + device = _dev; + token = _token; + } + + + // Parcelable implementation + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(name); + out.writeString(device); + out.writeLong(token); + } + + public static final Parcelable.Creator<RestoreSet> CREATOR + = new Parcelable.Creator<RestoreSet>() { + public RestoreSet createFromParcel(Parcel in) { + return new RestoreSet(in); + } + + public RestoreSet[] newArray(int size) { + return new RestoreSet[size]; + } + }; + + private RestoreSet(Parcel in) { + name = in.readString(); + device = in.readString(); + token = in.readLong(); + } +} diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java index 8627f08..4a7b399 100644 --- a/core/java/android/backup/SharedPreferencesBackupHelper.java +++ b/core/java/android/backup/SharedPreferencesBackupHelper.java @@ -18,24 +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 static void performBackup(Context context, - ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot, - BackupDataOutput data, String[] prefGroups) { - String basePath = "/xxx"; //context.getPreferencesDir(); +public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper { + private static final String TAG = "SharedPreferencesBackupHelper"; + private Context mContext; + private String[] mPrefGroups; + + public SharedPreferencesBackupHelper(Context context, String... prefGroups) { + super(context); + + mContext = context; + mPrefGroups = 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] = prefGroups[i] + ".xml"; + files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath(); } - FileBackupHelper.performBackup_checked(basePath, oldSnapshot, data, newSnapshot, files); + // go + 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/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index e198435..fe1e09a 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -332,6 +332,31 @@ public class BluetoothHeadset { } /** + * Get battery usage hint for Bluetooth Headset service. + * This is a monotonically increasing integer. Wraps to 0 at + * Integer.MAX_INT, and at boot. + * Current implementation returns the number of AT commands handled since + * boot. This is a good indicator for spammy headset/handsfree units that + * can keep the device awake by polling for cellular status updates. As a + * rule of thumb, each AT command prevents the CPU from sleeping for 500 ms + * @return monotonically increasing battery usage hint, or a negative error + * code on error + * @hide + */ + public int getBatteryUsageHint() { + if (DBG) log("getBatteryUsageHint()"); + if (mService != null) { + try { + return mService.getBatteryUsageHint(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return -1; + } + + /** * Check class bits for possible HSP or HFP support. * This is a simple heuristic that tries to guess if a device with the * given class bits might support HSP or HFP. It is not accurate for all diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java index f31e7a2..f987ffd 100644 --- a/core/java/android/bluetooth/HeadsetBase.java +++ b/core/java/android/bluetooth/HeadsetBase.java @@ -40,6 +40,8 @@ public class HeadsetBase { public static final int DIRECTION_INCOMING = 1; public static final int DIRECTION_OUTGOING = 2; + private static int sAtInputCount = 0; /* TODO: Consider not using a static variable */ + private final BluetoothDevice mBluetooth; private final String mAddress; private final int mRfcommChannel; @@ -109,6 +111,14 @@ public class HeadsetBase { acquireWakeLock(); long timestamp; + synchronized(HeadsetBase.class) { + if (sAtInputCount == Integer.MAX_VALUE) { + sAtInputCount = 0; + } else { + sAtInputCount++; + } + } + if (DBG) timestamp = System.currentTimeMillis(); AtCommandResult result = mAtParser.process(input); if (DBG) Log.d(TAG, "Processing " + input + " took " + @@ -279,7 +289,11 @@ public class HeadsetBase { } } - private void log(String msg) { + public static int getAtInputCount() { + return sAtInputCount; + } + + private static void log(String msg) { Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index 582d4e3..5f42fd6 100644 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -31,4 +31,5 @@ interface IBluetoothHeadset { boolean stopVoiceRecognition(); boolean setPriority(in String address, int priority); int getPriority(in String address); + int getBatteryUsageHint(); } diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java index ce6501c..249d9ba 100644 --- a/core/java/android/content/AbstractSyncableContentProvider.java +++ b/core/java/android/content/AbstractSyncableContentProvider.java @@ -147,7 +147,8 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro @Override public boolean onCreate() { if (isTemporary()) throw new IllegalStateException("onCreate() called for temp provider"); - mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(), mDatabaseName); + mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(), + mDatabaseName); mSyncState = new SyncStateContentProviderHelper(mOpenHelper); AccountMonitorListener listener = new AccountMonitorListener() { @@ -235,76 +236,147 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro return Collections.emptyList(); } - @Override - public final int update(final Uri url, final ContentValues values, - final String selection, final String[] selectionArgs) { + /** + * <p> + * Call mOpenHelper.getWritableDatabase() and mDb.beginTransaction(). + * {@link #endTransaction} MUST be called after calling this method. + * Those methods should be used like this: + * </p> + * + * <pre class="prettyprint"> + * boolean successful = false; + * beginTransaction(); + * try { + * // Do something related to mDb + * successful = true; + * return ret; + * } finally { + * endTransaction(successful); + * } + * </pre> + * + * @hide This method is dangerous from the view of database manipulation, though using + * this makes batch insertion/update/delete much faster. + */ + public final void beginTransaction() { mDb = mOpenHelper.getWritableDatabase(); mDb.beginTransaction(); + } + + /** + * <p> + * Call mDb.endTransaction(). If successful is true, try to call + * mDb.setTransactionSuccessful() before calling mDb.endTransaction(). + * This method MUST be used with {@link #beginTransaction()}. + * </p> + * + * @hide This method is dangerous from the view of database manipulation, though using + * this makes batch insertion/update/delete much faster. + */ + public final void endTransaction(boolean successful) { try { - if (isTemporary() && mSyncState.matches(url)) { - int numRows = mSyncState.asContentProvider().update( - url, values, selection, selectionArgs); + if (successful) { + // setTransactionSuccessful() must be called just once during opening the + // transaction. mDb.setTransactionSuccessful(); - return numRows; } + } finally { + mDb.endTransaction(); + } + } - int result = updateInternal(url, values, selection, selectionArgs); - mDb.setTransactionSuccessful(); + @Override + public final int update(final Uri uri, final ContentValues values, + final String selection, final String[] selectionArgs) { + boolean successful = false; + beginTransaction(); + try { + int ret = nonTransactionalUpdate(uri, values, selection, selectionArgs); + successful = true; + return ret; + } finally { + endTransaction(successful); + } + } - if (!isTemporary() && result > 0) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } + /** + * @hide + */ + public final int nonTransactionalUpdate(final Uri uri, final ContentValues values, + final String selection, final String[] selectionArgs) { + if (isTemporary() && mSyncState.matches(uri)) { + int numRows = mSyncState.asContentProvider().update( + uri, values, selection, selectionArgs); + return numRows; + } - return result; - } finally { - mDb.endTransaction(); + int result = updateInternal(uri, values, selection, selectionArgs); + if (!isTemporary() && result > 0) { + getContext().getContentResolver().notifyChange(uri, null /* observer */, + changeRequiresLocalSync(uri)); } + + return result; } @Override - public final int delete(final Uri url, final String selection, + public final int delete(final Uri uri, final String selection, final String[] selectionArgs) { - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); + boolean successful = false; + beginTransaction(); try { - if (isTemporary() && mSyncState.matches(url)) { - int numRows = mSyncState.asContentProvider().delete(url, selection, selectionArgs); - mDb.setTransactionSuccessful(); - return numRows; - } - int result = deleteInternal(url, selection, selectionArgs); - mDb.setTransactionSuccessful(); - if (!isTemporary() && result > 0) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } - return result; + int ret = nonTransactionalDelete(uri, selection, selectionArgs); + successful = true; + return ret; } finally { - mDb.endTransaction(); + endTransaction(successful); } } + /** + * @hide + */ + public final int nonTransactionalDelete(final Uri uri, final String selection, + final String[] selectionArgs) { + if (isTemporary() && mSyncState.matches(uri)) { + int numRows = mSyncState.asContentProvider().delete(uri, selection, selectionArgs); + return numRows; + } + int result = deleteInternal(uri, selection, selectionArgs); + if (!isTemporary() && result > 0) { + getContext().getContentResolver().notifyChange(uri, null /* observer */, + changeRequiresLocalSync(uri)); + } + return result; + } + @Override - public final Uri insert(final Uri url, final ContentValues values) { - mDb = mOpenHelper.getWritableDatabase(); - mDb.beginTransaction(); + public final Uri insert(final Uri uri, final ContentValues values) { + boolean successful = false; + beginTransaction(); try { - if (isTemporary() && mSyncState.matches(url)) { - Uri result = mSyncState.asContentProvider().insert(url, values); - mDb.setTransactionSuccessful(); - return result; - } - Uri result = insertInternal(url, values); - mDb.setTransactionSuccessful(); - if (!isTemporary() && result != null) { - getContext().getContentResolver().notifyChange(url, null /* observer */, - changeRequiresLocalSync(url)); - } - return result; + Uri ret = nonTransactionalInsert(uri, values); + successful = true; + return ret; } finally { - mDb.endTransaction(); + endTransaction(successful); + } + } + + /** + * @hide + */ + public final Uri nonTransactionalInsert(final Uri uri, final ContentValues values) { + if (isTemporary() && mSyncState.matches(uri)) { + Uri result = mSyncState.asContentProvider().insert(uri, values); + return result; + } + Uri result = insertInternal(uri, values); + if (!isTemporary() && result != null) { + getContext().getContentResolver().notifyChange(uri, null /* observer */, + changeRequiresLocalSync(uri)); } + return result; } @Override diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java index 700f1d8..9c760d9 100644 --- a/core/java/android/content/AbstractTableMerger.java +++ b/core/java/android/content/AbstractTableMerger.java @@ -61,8 +61,10 @@ public abstract class AbstractTableMerger _SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?"; private static final String SELECT_BY_ID = BaseColumns._ID +"=?"; - private static final String SELECT_UNSYNCED = "" - + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)"; + private static final String SELECT_UNSYNCED = + "(" + _SYNC_ACCOUNT + " IS NULL OR " + _SYNC_ACCOUNT + "=?) AND " + + "(" + _SYNC_ID + " IS NULL OR (" + _SYNC_DIRTY + " > 0 AND " + + _SYNC_VERSION + " IS NOT NULL))"; public AbstractTableMerger(SQLiteDatabase database, String table, Uri tableURL, String deletedTable, @@ -365,26 +367,32 @@ public abstract class AbstractTableMerger if (!TextUtils.isEmpty(localSyncID)) { // An existing server item has changed - boolean recordChanged = (localSyncVersion == null) || - !serverSyncVersion.equals(localSyncVersion); - if (recordChanged) { - if (localSyncDirty) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "remote record " + serverSyncId - + " conflicts with local _sync_id " + localSyncID - + ", local _id " + localRowId); + // If serverSyncVersion is null, there is no edit URL; + // server won't let this change be written. + // Just hold onto it, I guess, in case the server permissions + // change later. + if (serverSyncVersion != null) { + boolean recordChanged = (localSyncVersion == null) || + !serverSyncVersion.equals(localSyncVersion); + if (recordChanged) { + if (localSyncDirty) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "remote record " + serverSyncId + + " conflicts with local _sync_id " + localSyncID + + ", local _id " + localRowId); + } + conflict = true; + } else { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, + "remote record " + + serverSyncId + + " updates local _sync_id " + + localSyncID + ", local _id " + + localRowId); + } + update = true; } - conflict = true; - } else { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, - "remote record " + - serverSyncId + - " updates local _sync_id " + - localSyncID + ", local _id " + - localRowId); - } - update = true; } } } else { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f2ad248..9e37ae4 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -16,6 +16,7 @@ package android.content; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Resources; @@ -233,6 +234,9 @@ public abstract class Context { /** Return the name of this application's package. */ public abstract String getPackageName(); + /** Return the full application info for this context's package. */ + public abstract ApplicationInfo getApplicationInfo(); + /** * {@hide} * Return the full path to this context's resource files. This is the ZIP files @@ -254,12 +258,20 @@ public abstract class Context { * <p>Note: this is not generally useful for applications, since they should * not be directly accessing the file system. * - * * @return String Path to the code and assets. */ public abstract String getPackageCodePath(); /** + * {@hide} + * Return the full path to the shared prefs file for the given prefs group name. + * + * <p>Note: this is not generally useful for applications, since they should + * not be directly accessing the file system. + */ + public abstract File getSharedPrefsFile(String name); + + /** * Retrieve and hold the contents of the preferences file 'name', returning * a SharedPreferences through which you can retrieve and modify its * values. Only one instance of the SharedPreferences object is returned @@ -527,16 +539,6 @@ public abstract class Context { public abstract int getWallpaperDesiredMinimumHeight(); /** - * Returns the scale in which the application will be drawn on the - * screen. This is usually 1.0f if the application supports the device's - * resolution/density. This will be 1.5f, for example, if the application - * that supports only 160 density runs on 240 density screen. - * - * @hide - */ - public abstract float getApplicationScale(); - - /** * Change the current system wallpaper to a bitmap. The given bitmap is * converted to a PNG and stored as the wallpaper. On success, the intent * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast. @@ -1135,6 +1137,15 @@ public abstract class Context { public static final String NOTIFICATION_SERVICE = "notification"; /** * Use with {@link #getSystemService} to retrieve a + * {@link android.view.accessibility.AccessibilityManager} for giving the user + * feedback for UI events through the registered event listeners. + * + * @see #getSystemService + * @see android.view.accessibility.AccessibilityManager + */ + public static final String ACCESSIBILITY_SERVICE = "accessibility"; + /** + * Use with {@link #getSystemService} to retrieve a * {@link android.app.NotificationManager} for controlling keyguard. * * @see #getSystemService @@ -1643,6 +1654,13 @@ public abstract class Context { * with extreme care! */ public static final int CONTEXT_IGNORE_SECURITY = 0x00000002; + + /** + * Flag for use with {@link #createPackageContext}: a restricted context may + * disable specific features. For instance, a View associated with a restricted + * context would ignore particular XML attributes. + */ + public static final int CONTEXT_RESTRICTED = 0x00000004; /** * Return a new Context object for the given application name. This @@ -1671,4 +1689,15 @@ public abstract class Context { */ public abstract Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException; + + /** + * Indicates whether this Context is restricted. + * + * @return True if this Context is restricted, false otherwise. + * + * @see #CONTEXT_RESTRICTED + */ + public boolean isRestricted() { + return false; + } } diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 25b2cae..45a082a 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -16,6 +16,7 @@ package android.content; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Resources; @@ -120,6 +121,11 @@ public class ContextWrapper extends Context { } @Override + public ApplicationInfo getApplicationInfo() { + return mBase.getApplicationInfo(); + } + + @Override public String getPackageResourcePath() { return mBase.getPackageResourcePath(); } @@ -130,6 +136,11 @@ public class ContextWrapper extends Context { } @Override + public File getSharedPrefsFile(String name) { + return mBase.getSharedPrefsFile(name); + } + + @Override public SharedPreferences getSharedPreferences(String name, int mode) { return mBase.getSharedPreferences(name, mode); } @@ -420,11 +431,8 @@ public class ContextWrapper extends Context { return mBase.createPackageContext(packageName, flags); } - /** - * @hide - */ @Override - public float getApplicationScale() { - return mBase.getApplicationScale(); + public boolean isRestricted() { + return mBase.isRestricted(); } } diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl new file mode 100755 index 0000000..443db2d --- /dev/null +++ b/core/java/android/content/IIntentReceiver.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content; + +import android.content.Intent; +import android.os.Bundle; + +/** + * System private API for dispatching intent broadcasts. This is given to the + * activity manager as part of registering for an intent broadcasts, and is + * called when it receives intents. + * + * {@hide} + */ +oneway interface IIntentReceiver { + void performReceive(in Intent intent, int resultCode, + String data, in Bundle extras, boolean ordered); +} + diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl new file mode 100644 index 0000000..b7da472 --- /dev/null +++ b/core/java/android/content/IIntentSender.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content; + +import android.content.IIntentReceiver; +import android.content.Intent; + +/** @hide */ +interface IIntentSender { + int send(int code, in Intent intent, String resolvedType, + IIntentReceiver finishedReceiver); +} diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 24262f5..263f927 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -240,35 +240,35 @@ import java.util.Set; * * <activity class=".NotesList" android:label="@string/title_notes_list"> * <intent-filter> - * <action android:value="android.intent.action.MAIN" /> - * <category android:value="android.intent.category.LAUNCHER" /> + * <action android:name="android.intent.action.MAIN" /> + * <category android:name="android.intent.category.LAUNCHER" /> * </intent-filter> * <intent-filter> - * <action android:value="android.intent.action.VIEW" /> - * <action android:value="android.intent.action.EDIT" /> - * <action android:value="android.intent.action.PICK" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> + * <action android:name="android.intent.action.VIEW" /> + * <action android:name="android.intent.action.EDIT" /> + * <action android:name="android.intent.action.PICK" /> + * <category android:name="android.intent.category.DEFAULT" /> + * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> * </intent-filter> * <intent-filter> - * <action android:value="android.intent.action.GET_CONTENT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="android.intent.action.GET_CONTENT" /> + * <category android:name="android.intent.category.DEFAULT" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter> * </activity> * * <activity class=".NoteEditor" android:label="@string/title_note"> * <intent-filter android:label="@string/resolve_edit"> - * <action android:value="android.intent.action.VIEW" /> - * <action android:value="android.intent.action.EDIT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="android.intent.action.VIEW" /> + * <action android:name="android.intent.action.EDIT" /> + * <category android:name="android.intent.category.DEFAULT" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter> * * <intent-filter> - * <action android:value="android.intent.action.INSERT" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> + * <action android:name="android.intent.action.INSERT" /> + * <category android:name="android.intent.category.DEFAULT" /> + * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> * </intent-filter> * * </activity> @@ -276,11 +276,11 @@ import java.util.Set; * <activity class=".TitleEditor" android:label="@string/title_edit_title" * android:theme="@android:style/Theme.Dialog"> * <intent-filter android:label="@string/resolve_title"> - * <action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:value="android.intent.category.DEFAULT" /> - * <category android:value="android.intent.category.ALTERNATIVE" /> - * <category android:value="android.intent.category.SELECTED_ALTERNATIVE" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /> + * <category android:name="android.intent.category.DEFAULT" /> + * <category android:name="android.intent.category.ALTERNATIVE" /> + * <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter> * </activity> * @@ -294,8 +294,8 @@ import java.util.Set; * <ol> * <li><pre> * <intent-filter> - * <action android:value="{@link #ACTION_MAIN android.intent.action.MAIN}" /> - * <category android:value="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /> + * <action android:name="{@link #ACTION_MAIN android.intent.action.MAIN}" /> + * <category android:name="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /> * </intent-filter></pre> * <p>This provides a top-level entry into the NotePad application: the standard * MAIN action is a main entry point (not requiring any other information in @@ -303,11 +303,11 @@ import java.util.Set; * listed in the application launcher.</p> * <li><pre> * <intent-filter> - * <action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <action android:value="{@link #ACTION_PICK android.intent.action.PICK}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> + * <action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /> + * <action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /> + * <action android:name="{@link #ACTION_PICK android.intent.action.PICK}" /> + * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> + * <data mimeType:name="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> * </intent-filter></pre> * <p>This declares the things that the activity can do on a directory of * notes. The type being supported is given with the <type> tag, where @@ -322,9 +322,9 @@ import java.util.Set; * activity when its component name is not explicitly specified.</p> * <li><pre> * <intent-filter> - * <action android:value="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /> + * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter></pre> * <p>This filter describes the ability return to the caller a note selected by * the user without needing to know where it came from. The data type @@ -371,10 +371,10 @@ import java.util.Set; * <ol> * <li><pre> * <intent-filter android:label="@string/resolve_edit"> - * <action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /> - * <action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /> + * <action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /> + * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter></pre> * <p>The first, primary, purpose of this activity is to let the user interact * with a single note, as decribed by the MIME type @@ -384,9 +384,9 @@ import java.util.Set; * specifying its component.</p> * <li><pre> * <intent-filter> - * <action android:value="{@link #ACTION_INSERT android.intent.action.INSERT}" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> + * <action android:name="{@link #ACTION_INSERT android.intent.action.INSERT}" /> + * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> + * <data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /> * </intent-filter></pre> * <p>The secondary use of this activity is to insert a new note entry into * an existing directory of notes. This is used when the user creates a new @@ -422,11 +422,11 @@ import java.util.Set; * * <pre> * <intent-filter android:label="@string/resolve_title"> - * <action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /> - * <category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> - * <category android:value="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /> - * <category android:value="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /> - * <type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /> + * <action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /> + * <category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /> + * <category android:name="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /> + * <category android:name="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /> + * <data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /> * </intent-filter></pre> * * <p>In the single intent template here, we @@ -509,8 +509,8 @@ import java.util.Set; * <li> {@link #ACTION_UID_REMOVED} * <li> {@link #ACTION_BATTERY_CHANGED} * <li> {@link #ACTION_POWER_CONNECTED} - * <li> {@link #ACTION_POWER_DISCONNECTED} - * <li> {@link #ACTION_SHUTDOWN} + * <li> {@link #ACTION_POWER_DISCONNECTED} + * <li> {@link #ACTION_SHUTDOWN} * </ul> * * <h3>Standard Categories</h3> @@ -915,6 +915,23 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SEND = "android.intent.action.SEND"; /** + * Activity Action: Deliver multiple data to someone else. + * <p> + * Like ACTION_SEND, except the data is multiple. + * <p> + * Input: {@link #getType} is the MIME type of the data being sent. + * get*ArrayListExtra can have either a {@link #EXTRA_TEXT} or {@link + * #EXTRA_STREAM} field, containing the data to be sent. + * <p> + * Optional standard extras, which may be interpreted by some recipients as + * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC}, + * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}. + * <p> + * Output: nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE"; + /** * Activity Action: Handle an incoming phone call. * <p>Input: nothing. * <p>Output: nothing. @@ -1059,6 +1076,36 @@ public class Intent implements Parcelable { */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APP_ERROR = "android.intent.action.APP_ERROR"; + + /** + * Activity Action: Show power usage information to the user. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY"; + + /** + * Activity Action: Setup wizard to launch after a platform update. This + * activity should have a string meta-data field associated with it, + * {@link #METADATA_SETUP_VERSION}, which defines the current version of + * the platform for setup. The activity will be launched only if + * {@link android.provider.Settings.Secure#LAST_SETUP_SHOWN} is not the + * same value. + * <p>Input: Nothing. + * <p>Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; + + /** + * A string associated with a {@link #ACTION_UPGRADE_SETUP} activity + * describing the last run version of the platform that was setup. + * @hide + */ + public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent broadcast actions (see action variable). @@ -1264,6 +1311,13 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW"; /** + * Broadcast Action: Indicates the battery is now okay after being low. + * This will be sent after {@link #ACTION_BATTERY_LOW} once the battery has + * gone back up to an okay state. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY"; + /** * Broadcast Action: External power has been connected to the device. * This is intended for applications that wish to register specifically to this notification. * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to @@ -1277,10 +1331,10 @@ public class Intent implements Parcelable { * This is intended for applications that wish to register specifically to this notification. * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to * stay active to receive this notification. This action can be used to implement actions - * that wait until power is available to trigger. + * that wait until power is available to trigger. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED"; + public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED"; /** * Broadcast Action: Device is shutting down. * This is broadcast when the device is being shut down (completely turned @@ -1289,7 +1343,7 @@ public class Intent implements Parcelable { * to handle this, since the forground activity will be paused as well. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; + public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; /** * Broadcast Action: Indicates low memory condition on the device */ @@ -1552,6 +1606,16 @@ public class Intent implements Parcelable { public static final String ACTION_REBOOT = "android.intent.action.REBOOT"; + /** + * @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"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). @@ -1791,23 +1855,23 @@ public class Intent implements Parcelable { * delivered. */ public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT"; - + /** * Used as a parcelable extra field in {@link #ACTION_APP_ERROR}, containing * the bug report. - * + * * @hide */ public static final String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT"; /** - * Used as a string extra field when sending an intent to PackageInstaller to install a + * Used as a string extra field when sending an intent to PackageInstaller to install a * package. Specifies the installer package name; this package will receive the * {@link #ACTION_APP_ERROR} intent. - * + * * @hide */ - public static final String EXTRA_INSTALLER_PACKAGE_NAME + public static final String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME"; // --------------------------------------------------------------------- @@ -2040,10 +2104,25 @@ public class Intent implements Parcelable { public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000; // --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // toUri() and parseUri() options. + + /** + * Flag for use with {@link #toUri} and {@link #parseUri}: the URI string + * always has the "intent:" scheme. This syntax can be used when you want + * to later disambiguate between URIs that are intended to describe an + * Intent vs. all others that should be treated as raw URIs. When used + * with {@link #parseUri}, any other scheme will result in a generic + * VIEW action for that raw URI. + */ + public static final int URI_INTENT_SCHEME = 1<<0; + + // --------------------------------------------------------------------- private String mAction; private Uri mData; private String mType; + private String mPackage; private ComponentName mComponent; private int mFlags; private HashSet<String> mCategories; @@ -2064,6 +2143,7 @@ public class Intent implements Parcelable { this.mAction = o.mAction; this.mData = o.mData; this.mType = o.mType; + this.mPackage = o.mPackage; this.mComponent = o.mComponent; this.mFlags = o.mFlags; if (o.mCategories != null) { @@ -2083,6 +2163,7 @@ public class Intent implements Parcelable { this.mAction = o.mAction; this.mData = o.mData; this.mType = o.mType; + this.mPackage = o.mPackage; this.mComponent = o.mComponent; if (o.mCategories != null) { this.mCategories = new HashSet<String>(o.mCategories); @@ -2183,23 +2264,50 @@ public class Intent implements Parcelable { } /** + * Call {@link #parseUri} with 0 flags. + * @deprecated Use {@link #parseUri} instead. + */ + @Deprecated + public static Intent getIntent(String uri) throws URISyntaxException { + return parseUri(uri, 0); + } + + /** * Create an intent from a URI. This URI may encode the action, - * category, and other intent fields, if it was returned by toURI(). If - * the Intent was not generate by toURI(), its data will be the entire URI - * and its action will be ACTION_VIEW. + * category, and other intent fields, if it was returned by + * {@link #toUri}.. If the Intent was not generate by toUri(), its data + * will be the entire URI and its action will be ACTION_VIEW. * * <p>The URI given here must not be relative -- that is, it must include * the scheme and full path. * * @param uri The URI to turn into an Intent. + * @param flags Additional processing flags. Either 0 or * * @return Intent The newly created Intent object. * - * @see #toURI + * @throws URISyntaxException Throws URISyntaxError if the basic URI syntax + * it bad (as parsed by the Uri class) or the Intent data within the + * URI is invalid. + * + * @see #toUri */ - public static Intent getIntent(String uri) throws URISyntaxException { + public static Intent parseUri(String uri, int flags) throws URISyntaxException { int i = 0; try { + // Validate intent scheme for if requested. + if ((flags&URI_INTENT_SCHEME) != 0) { + if (!uri.startsWith("intent:")) { + Intent intent = new Intent(ACTION_VIEW); + try { + intent.setData(Uri.parse(uri)); + } catch (IllegalArgumentException e) { + throw new URISyntaxException(uri, e.getMessage()); + } + return intent; + } + } + // simple case i = uri.lastIndexOf("#"); if (i == -1) return new Intent(ACTION_VIEW, Uri.parse(uri)); @@ -2211,16 +2319,15 @@ public class Intent implements Parcelable { Intent intent = new Intent(ACTION_VIEW); // fetch data part, if present - if (i > 0) { - intent.mData = Uri.parse(uri.substring(0, i)); - } + String data = i >= 0 ? uri.substring(0, i) : null; + String scheme = null; i += "#Intent;".length(); // loop over contents of Intent, all name=value; while (!uri.startsWith("end", i)) { int eq = uri.indexOf('=', i); int semi = uri.indexOf(';', eq); - String value = uri.substring(eq + 1, semi); + String value = Uri.decode(uri.substring(eq + 1, semi)); // action if (uri.startsWith("action=", i)) { @@ -2242,15 +2349,24 @@ public class Intent implements Parcelable { intent.mFlags = Integer.decode(value).intValue(); } + // package + else if (uri.startsWith("package=", i)) { + intent.mPackage = value; + } + // component else if (uri.startsWith("component=", i)) { intent.mComponent = ComponentName.unflattenFromString(value); } + // scheme + else if (uri.startsWith("scheme=", i)) { + scheme = value; + } + // extra else { String key = Uri.decode(uri.substring(i + 2, eq)); - value = Uri.decode(value); // create Bundle if it doesn't already exist if (intent.mExtras == null) intent.mExtras = new Bundle(); Bundle b = intent.mExtras; @@ -2271,6 +2387,23 @@ public class Intent implements Parcelable { i = semi + 1; } + if (data != null) { + if (data.startsWith("intent:")) { + data = data.substring(7); + if (scheme != null) { + data = scheme + ':' + data; + } + } + + if (data.length() > 0) { + try { + intent.mData = Uri.parse(data); + } catch (IllegalArgumentException e) { + throw new URISyntaxException(uri, e.getMessage()); + } + } + } + return intent; } catch (IndexOutOfBoundsException e) { @@ -3084,6 +3217,20 @@ public class Intent implements Parcelable { } /** + * Retrieve the application package name this Intent is limited to. When + * resolving an Intent, if non-null this limits the resolution to only + * components in the given application package. + * + * @return The name of the application package for the Intent. + * + * @see #resolveActivity + * @see #setPackage + */ + public String getPackage() { + return mPackage; + } + + /** * Retrieve the concrete component associated with the intent. When receiving * an intent, this is the component that was found to best handle it (that is, * yourself) and will always be non-null; in all other cases it will be @@ -3118,6 +3265,9 @@ public class Intent implements Parcelable { * <p>If {@link #addCategory} has added any categories, the activity must * handle ALL of the categories specified. * + * <p>If {@link #getPackage} is non-NULL, only activity components in + * that application package will be considered. + * * <p>If there are no activities that satisfy all of these conditions, a * null string is returned. * @@ -3239,7 +3389,7 @@ public class Intent implements Parcelable { * only specify a type and not data, for example to indicate the type of * data to return. This method automatically clears any data that was * previously set by {@link #setData}. - * + * * <p><em>Note: MIME type matching in the Android framework is * case-sensitive, unlike formal RFC MIME types. As a result, * you should always write your MIME types with lower case letters, @@ -4089,6 +4239,27 @@ public class Intent implements Parcelable { } /** + * (Usually optional) Set an explicit application package name that limits + * the components this Intent will resolve to. If left to the default + * value of null, all components in all applications will considered. + * If non-null, the Intent can only match the components in the given + * application package. + * + * @param packageName The name of the application package to handle the + * intent, or null to allow any application package. + * + * @return Returns the same Intent object, for chaining multiple calls + * into a single statement. + * + * @see #getPackage + * @see #resolveActivity + */ + public Intent setPackage(String packageName) { + mPackage = packageName; + return this; + } + + /** * (Usually optional) Explicitly set the component to handle the intent. * If left with the default value of null, the system will determine the * appropriate class to use based on the other fields (action, data, @@ -4200,6 +4371,12 @@ public class Intent implements Parcelable { public static final int FILL_IN_COMPONENT = 1<<3; /** + * Use with {@link #fillIn} to allow the current package value to be + * overwritten, even if it is already set. + */ + public static final int FILL_IN_PACKAGE = 1<<4; + + /** * Copy the contents of <var>other</var> in to this object, but only * where fields are not defined by this object. For purposes of a field * being defined, the following pieces of data in the Intent are @@ -4210,14 +4387,15 @@ public class Intent implements Parcelable { * <li> data URI and MIME type, as set by {@link #setData(Uri)}, * {@link #setType(String)}, or {@link #setDataAndType(Uri, String)}. * <li> categories, as set by {@link #addCategory}. + * <li> package, as set by {@link #setPackage}. * <li> component, as set by {@link #setComponent(ComponentName)} or * related methods. * <li> each top-level name in the associated extras. * </ul> * * <p>In addition, you can use the {@link #FILL_IN_ACTION}, - * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and - * {@link #FILL_IN_COMPONENT} to override the restriction where the + * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE}, + * and {@link #FILL_IN_COMPONENT} to override the restriction where the * corresponding field will not be replaced if it is already set. * * <p>For example, consider Intent A with {data="foo", categories="bar"} @@ -4233,32 +4411,39 @@ public class Intent implements Parcelable { * @param flags Options to control which fields can be filled in. * * @return Returns a bit mask of {@link #FILL_IN_ACTION}, - * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and - * {@link #FILL_IN_COMPONENT} indicating which fields were changed. + * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE}, + * and {@link #FILL_IN_COMPONENT} indicating which fields were changed. */ public int fillIn(Intent other, int flags) { int changes = 0; - if ((mAction == null && other.mAction == null) - || (flags&FILL_IN_ACTION) != 0) { + if (other.mAction != null + && (mAction == null || (flags&FILL_IN_ACTION) != 0)) { mAction = other.mAction; changes |= FILL_IN_ACTION; } - if ((mData == null && mType == null && - (other.mData != null || other.mType != null)) - || (flags&FILL_IN_DATA) != 0) { + if ((other.mData != null || other.mType != null) + && ((mData == null && mType == null) + || (flags&FILL_IN_DATA) != 0)) { mData = other.mData; mType = other.mType; changes |= FILL_IN_DATA; } - if ((mCategories == null && other.mCategories == null) - || (flags&FILL_IN_CATEGORIES) != 0) { + if (other.mCategories != null + && (mCategories == null || (flags&FILL_IN_CATEGORIES) != 0)) { if (other.mCategories != null) { mCategories = new HashSet<String>(other.mCategories); } changes |= FILL_IN_CATEGORIES; } - if ((mComponent == null && other.mComponent == null) - || (flags&FILL_IN_COMPONENT) != 0) { + if (other.mPackage != null + && (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) { + mPackage = other.mPackage; + changes |= FILL_IN_PACKAGE; + } + // Component is special: it can -only- be set if explicitly allowed, + // since otherwise the sender could force the intent somewhere the + // originator didn't intend. + if (other.mComponent != null && (flags&FILL_IN_COMPONENT) != 0) { mComponent = other.mComponent; changes |= FILL_IN_COMPONENT; } @@ -4373,6 +4558,17 @@ public class Intent implements Parcelable { } } } + if (mPackage != other.mPackage) { + if (mPackage != null) { + if (!mPackage.equals(other.mPackage)) { + return false; + } + } else { + if (!other.mPackage.equals(mPackage)) { + return false; + } + } + } if (mComponent != other.mComponent) { if (mComponent != null) { if (!mComponent.equals(other.mComponent)) { @@ -4418,6 +4614,9 @@ public class Intent implements Parcelable { if (mType != null) { code += mType.hashCode(); } + if (mPackage != null) { + code += mPackage.hashCode(); + } if (mComponent != null) { code += mComponent.hashCode(); } @@ -4444,7 +4643,7 @@ public class Intent implements Parcelable { toShortString(b, comp, extras); return b.toString(); } - + /** @hide */ public void toShortString(StringBuilder b, boolean comp, boolean extras) { boolean first = true; @@ -4488,6 +4687,13 @@ public class Intent implements Parcelable { first = false; b.append("flg=0x").append(Integer.toHexString(mFlags)); } + if (mPackage != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("pkg=").append(mPackage); + } if (comp && mComponent != null) { if (!first) { b.append(' '); @@ -4504,28 +4710,87 @@ public class Intent implements Parcelable { } } + /** + * Call {@link #toUri} with 0 flags. + * @deprecated Use {@link #toUri} instead. + */ + @Deprecated public String toURI() { + return toUri(0); + } + + /** + * Convert this Intent into a String holding a URI representation of it. + * The returned URI string has been properly URI encoded, so it can be + * used with {@link Uri#parse Uri.parse(String)}. The URI contains the + * Intent's data as the base URI, with an additional fragment describing + * the action, categories, type, flags, package, component, and extras. + * + * <p>You can convert the returned string back to an Intent with + * {@link #getIntent}. + * + * @param flags Additional operating flags. Either 0 or + * {@link #URI_INTENT_SCHEME}. + * + * @return Returns a URI encoding URI string describing the entire contents + * of the Intent. + */ + public String toUri(int flags) { StringBuilder uri = new StringBuilder(128); - if (mData != null) uri.append(mData.toString()); + String scheme = null; + if (mData != null) { + String data = mData.toString(); + if ((flags&URI_INTENT_SCHEME) != 0) { + final int N = data.length(); + for (int i=0; i<N; i++) { + char c = data.charAt(i); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || c == '.' || c == '-') { + continue; + } + if (c == ':' && i > 0) { + // Valid scheme. + scheme = data.substring(0, i); + uri.append("intent:"); + data = data.substring(i+1); + break; + } + + // No scheme. + break; + } + } + uri.append(data); + + } else if ((flags&URI_INTENT_SCHEME) != 0) { + uri.append("intent:"); + } uri.append("#Intent;"); + if (scheme != null) { + uri.append("scheme=").append(scheme).append(';'); + } if (mAction != null) { - uri.append("action=").append(mAction).append(';'); + uri.append("action=").append(Uri.encode(mAction)).append(';'); } if (mCategories != null) { for (String category : mCategories) { - uri.append("category=").append(category).append(';'); + uri.append("category=").append(Uri.encode(category)).append(';'); } } if (mType != null) { - uri.append("type=").append(mType).append(';'); + uri.append("type=").append(Uri.encode(mType, "/")).append(';'); } if (mFlags != 0) { uri.append("launchFlags=0x").append(Integer.toHexString(mFlags)).append(';'); } + if (mPackage != null) { + uri.append("package=").append(Uri.encode(mPackage)).append(';'); + } if (mComponent != null) { - uri.append("component=").append(mComponent.flattenToShortString()).append(';'); + uri.append("component=").append(Uri.encode( + mComponent.flattenToShortString(), "/")).append(';'); } if (mExtras != null) { for (String key : mExtras.keySet()) { @@ -4567,6 +4832,7 @@ public class Intent implements Parcelable { Uri.writeToParcel(out, mData); out.writeString(mType); out.writeInt(mFlags); + out.writeString(mPackage); ComponentName.writeToParcel(mComponent, out); if (mCategories != null) { @@ -4600,6 +4866,7 @@ public class Intent implements Parcelable { mData = Uri.CREATOR.createFromParcel(in); mType = in.readString(); mFlags = in.readInt(); + mPackage = in.readString(); mComponent = ComponentName.readFromParcel(in); int N = in.readInt(); diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index e5c5dc8..365f269 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -366,6 +366,7 @@ public class IntentFilter implements Parcelable { throws MalformedMimeTypeException { mPriority = 0; mActions = new ArrayList<String>(); + addAction(action); addDataType(dataType); } diff --git a/core/java/android/content/IntentSender.aidl b/core/java/android/content/IntentSender.aidl new file mode 100644 index 0000000..741bc8c --- /dev/null +++ b/core/java/android/content/IntentSender.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content; + +parcelable IntentSender; diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java new file mode 100644 index 0000000..4da49d9 --- /dev/null +++ b/core/java/android/content/IntentSender.java @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content; + +import android.content.Context; +import android.content.Intent; +import android.content.IIntentSender; +import android.content.IIntentReceiver; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.Handler; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AndroidException; + + +/** + * A description of an Intent and target action to perform with it. + * The returned object can be + * handed to other applications so that they can perform the action you + * described on your behalf at a later time. + * + * <p>By giving a IntentSender to another application, + * you are granting it the right to perform the operation you have specified + * as if the other application was yourself (with the same permissions and + * identity). As such, you should be careful about how you build the IntentSender: + * often, for example, the base Intent you supply will have the component + * name explicitly set to one of your own components, to ensure it is ultimately + * sent there and nowhere else. + * + * <p>A IntentSender itself is simply a reference to a token maintained by + * the system describing the original data used to retrieve it. This means + * that, even if its owning application's process is killed, the + * IntentSender itself will remain usable from other processes that + * have been given it. If the creating application later re-retrieves the + * same kind of IntentSender (same operation, same Intent action, data, + * categories, and components, and same flags), it will receive a IntentSender + * representing the same token if that is still valid. + * + */ +public class IntentSender implements Parcelable { + private final IIntentSender mTarget; + + /** + * Exception thrown when trying to send through a PendingIntent that + * has been canceled or is otherwise no longer able to execute the request. + */ + public static class SendIntentException extends AndroidException { + public SendIntentException() { + } + + public SendIntentException(String name) { + super(name); + } + + public SendIntentException(Exception cause) { + super(cause); + } + } + + /** + * Callback interface for discovering when a send operation has + * completed. Primarily for use with a IntentSender that is + * performing a broadcast, this provides the same information as + * calling {@link Context#sendOrderedBroadcast(Intent, String, + * android.content.BroadcastReceiver, Handler, int, String, Bundle) + * Context.sendBroadcast()} with a final BroadcastReceiver. + */ + public interface OnFinished { + /** + * Called when a send operation as completed. + * + * @param IntentSender The IntentSender this operation was sent through. + * @param intent The original Intent that was sent. + * @param resultCode The final result code determined by the send. + * @param resultData The final data collected by a broadcast. + * @param resultExtras The final extras collected by a broadcast. + */ + void onSendFinished(IntentSender IntentSender, Intent intent, + int resultCode, String resultData, Bundle resultExtras); + } + + private static class FinishedDispatcher extends IIntentReceiver.Stub + implements Runnable { + private final IntentSender mIntentSender; + private final OnFinished mWho; + private final Handler mHandler; + private Intent mIntent; + private int mResultCode; + private String mResultData; + private Bundle mResultExtras; + FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) { + mIntentSender = pi; + mWho = who; + mHandler = handler; + } + public void performReceive(Intent intent, int resultCode, + String data, Bundle extras, boolean serialized) { + mIntent = intent; + mResultCode = resultCode; + mResultData = data; + mResultExtras = extras; + if (mHandler == null) { + run(); + } else { + mHandler.post(this); + } + } + public void run() { + mWho.onSendFinished(mIntentSender, mIntent, mResultCode, + mResultData, mResultExtras); + } + } + + /** + * Perform the operation associated with this IntentSender, allowing the + * caller to specify information about the Intent to use and be notified + * when the send has completed. + * + * @param context The Context of the caller. This may be null if + * <var>intent</var> is also null. + * @param code Result code to supply back to the IntentSender's target. + * @param intent Additional Intent data. See {@link Intent#fillIn + * Intent.fillIn()} for information on how this is applied to the + * original Intent. Use null to not modify the original Intent. + * @param onFinished The object to call back on when the send has + * completed, or null for no callback. + * @param handler Handler identifying the thread on which the callback + * should happen. If null, the callback will happen from the thread + * pool of the process. + * + * + * @throws SendIntentException Throws CanceledIntentException if the IntentSender + * is no longer allowing more intents to be sent through it. + */ + public void sendIntent(Context context, int code, Intent intent, + OnFinished onFinished, Handler handler) throws SendIntentException { + try { + String resolvedType = intent != null ? + intent.resolveTypeIfNeeded(context.getContentResolver()) + : null; + int res = mTarget.send(code, intent, resolvedType, + onFinished != null + ? new FinishedDispatcher(this, onFinished, handler) + : null); + if (res < 0) { + throw new SendIntentException(); + } + } catch (RemoteException e) { + throw new SendIntentException(); + } + } + + /** + * Comparison operator on two IntentSender objects, such that true + * is returned then they both represent the same operation from the + * same package. + */ + @Override + public boolean equals(Object otherObj) { + if (otherObj instanceof IntentSender) { + return mTarget.asBinder().equals(((IntentSender)otherObj) + .mTarget.asBinder()); + } + return false; + } + + @Override + public int hashCode() { + return mTarget.asBinder().hashCode(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(128); + sb.append("IntentSender{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(": "); + sb.append(mTarget != null ? mTarget.asBinder() : null); + sb.append('}'); + return sb.toString(); + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeStrongBinder(mTarget.asBinder()); + } + + public static final Parcelable.Creator<IntentSender> CREATOR + = new Parcelable.Creator<IntentSender>() { + public IntentSender createFromParcel(Parcel in) { + IBinder target = in.readStrongBinder(); + return target != null ? new IntentSender(target) : null; + } + + public IntentSender[] newArray(int size) { + return new IntentSender[size]; + } + }; + + /** + * Convenience function for writing either a IntentSender or null pointer to + * a Parcel. You must use this with {@link #readIntentSenderOrNullFromParcel} + * for later reading it. + * + * @param sender The IntentSender to write, or null. + * @param out Where to write the IntentSender. + */ + public static void writeIntentSenderOrNullToParcel(IntentSender sender, + Parcel out) { + out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() + : null); + } + + /** + * Convenience function for reading either a Messenger or null pointer from + * a Parcel. You must have previously written the Messenger with + * {@link #writeIntentSenderOrNullToParcel}. + * + * @param in The Parcel containing the written Messenger. + * + * @return Returns the Messenger read from the Parcel, or null if null had + * been written. + */ + public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) { + IBinder b = in.readStrongBinder(); + return b != null ? new IntentSender(b) : null; + } + + protected IntentSender(IIntentSender target) { + mTarget = target; + } + + protected IntentSender(IBinder target) { + mTarget = IIntentSender.Stub.asInterface(target); + } +} diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 9c25e73..f781e0d 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.backup.IBackupManager; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; @@ -35,6 +36,7 @@ import android.os.Message; import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.util.SparseArray; import android.util.Xml; @@ -351,8 +353,18 @@ public class SyncStorageEngine extends Handler { } } } + // Inform the backup manager about a data change + IBackupManager ibm = IBackupManager.Stub.asInterface( + ServiceManager.getService(Context.BACKUP_SERVICE)); + if (ibm != null) { + try { + ibm.dataChanged("com.android.providers.settings"); + } catch (RemoteException e) { + // Try again later + } + } } - + public boolean getSyncProviderAutomatically(String account, String providerName) { synchronized (mAuthorities) { if (account != null) { diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 85d877a..27783ef 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -235,6 +235,12 @@ public class ActivityInfo extends ComponentInfo public static final int CONFIG_ORIENTATION = 0x0080; /** * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the screen layout. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_SCREEN_LAYOUT = 0x0100; + /** + * Bit in {@link #configChanges} that indicates that the activity * can itself handle changes to the font scaling factor. Set from the * {@link android.R.attr#configChanges} attribute. This is * not a core resource configutation, but a higher-level value, so its @@ -248,8 +254,8 @@ public class ActivityInfo extends ComponentInfo * Contains any combination of {@link #CONFIG_FONT_SCALE}, * {@link #CONFIG_MCC}, {@link #CONFIG_MNC}, * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN}, - * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and - * {@link #CONFIG_ORIENTATION}. Set from the + * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, + * {@link #CONFIG_ORIENTATION}, and {@link #CONFIG_SCREEN_LAYOUT}. Set from the * {@link android.R.attr#configChanges} attribute. */ public int configChanges; diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 88ac04c..bcf95b6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -58,11 +58,22 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Class implementing the Application's manage space * functionality. From the "manageSpaceActivity" * attribute. This is an optional attribute and will be null if - * application's dont specify it in their manifest + * applications don't specify it in their manifest */ public String manageSpaceActivityName; /** + * Class implementing the Application's backup functionality. From + * the "backupAgent" attribute. This is an optional attribute and + * will be null if the application does not specify it in its manifest. + * + * <p>If android:allowBackup is set to false, this attribute is ignored. + * + * {@hide} + */ + public String backupAgentName; + + /** * Value for {@link #flags}: if set, this application is installed in the * device's system image. */ @@ -93,7 +104,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_PERSISTENT = 1<<3; /** - * Value for {@link #flags}: set to true iif this application holds the + * Value for {@link #flags}: set to true if this application holds the * {@link android.Manifest.permission#FACTORY_TEST} permission and the * device is running in factory test mode. */ @@ -123,13 +134,46 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Value for {@link #flags}: this is set of the application has set * its android:targetSdkVersion to something >= the current SDK version. */ - public static final int FLAG_TARGETS_SDK = 1<<8; + public static final int FLAG_TEST_ONLY = 1<<8; /** - * Value for {@link #flags}: this is set of the application has set - * its android:targetSdkVersion to something >= the current SDK version. + * Value for {@link #flags}: true when the application's window can be + * reduced in size for smaller screens. Corresponds to + * {@link android.R.styleable#AndroidManifestSupportsScreens_smallScreens + * android:smallScreens}. */ - public static final int FLAG_TEST_ONLY = 1<<9; + public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9; + + /** + * Value for {@link #flags}: true when the application's window can be + * displayed on normal screens. Corresponds to + * {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens + * android:normalScreens}. + */ + public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; + + /** + * Value for {@link #flags}: true when the application's window can be + * increased in size for larger screens. Corresponds to + * {@link android.R.styleable#AndroidManifestSupportsScreens_largeScreens + * android:smallScreens}. + */ + public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11; + + /** + * Value for {@link #flags}: this is false if the application has set + * its android:allowBackup to false, true otherwise. + * + * {@hide} + */ + public static final int FLAG_ALLOW_BACKUP = 1<<12; + + /** + * Indicates that the application supports any densities; + * {@hide} + */ + public static final int ANY_DENSITY = -1; + private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY }; /** * Flags associated with the application. Any combination of @@ -137,7 +181,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and * {@link #FLAG_ALLOW_TASK_REPARENTING} * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP}, - * {@link #FLAG_TARGETS_SDK}. + * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS}, + * {@link #FLAG_SUPPORTS_NORMAL_SCREENS}, + * {@link #FLAG_SUPPORTS_LARGE_SCREENS}. */ public int flags = 0; @@ -173,7 +219,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public int uid; - /** * The list of densities in DPI that application supprots. This * field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was @@ -182,6 +227,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public int[] supportsDensities; /** + * The minimum SDK version this application targets. It may run on earilier + * versions, but it knows how to work with any new behavior added at this + * version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT} + * if this is a development build and the app is targeting that. You should + * compare that this number is >= the SDK version number at which your + * behavior was introduced. + */ + public int targetSdkVersion; + + /** * When false, indicates that all components within this application are * considered disabled, regardless of their individually set enabled status. */ @@ -200,6 +255,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { pw.println(prefix + "publicSourceDir=" + publicSourceDir); pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles); pw.println(prefix + "dataDir=" + dataDir); + pw.println(prefix + "targetSdkVersion=" + targetSdkVersion); pw.println(prefix + "enabled=" + enabled); pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName); pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes)); @@ -246,6 +302,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sharedLibraryFiles = orig.sharedLibraryFiles; dataDir = orig.dataDir; uid = orig.uid; + targetSdkVersion = orig.targetSdkVersion; enabled = orig.enabled; manageSpaceActivityName = orig.manageSpaceActivityName; descriptionRes = orig.descriptionRes; @@ -276,8 +333,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeStringArray(sharedLibraryFiles); dest.writeString(dataDir); dest.writeInt(uid); + dest.writeInt(targetSdkVersion); dest.writeInt(enabled ? 1 : 0); dest.writeString(manageSpaceActivityName); + dest.writeString(backupAgentName); dest.writeInt(descriptionRes); dest.writeIntArray(supportsDensities); } @@ -305,8 +364,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sharedLibraryFiles = source.readStringArray(); dataDir = source.readString(); uid = source.readInt(); + targetSdkVersion = source.readInt(); enabled = source.readInt() != 0; manageSpaceActivityName = source.readString(); + backupAgentName = source.readString(); descriptionRes = source.readInt(); supportsDensities = source.createIntArray(); } @@ -331,4 +392,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } return null; } + + /** + * Disable compatibility mode + * + * @hide + */ + public void disableCompatibilityMode() { + flags |= FLAG_SUPPORTS_LARGE_SCREENS; + supportsDensities = ANY_DENSITIES_ARRAY; + } } diff --git a/core/java/android/content/pm/ConfigurationInfo.java b/core/java/android/content/pm/ConfigurationInfo.java index dcc7463..fb7a47f 100755 --- a/core/java/android/content/pm/ConfigurationInfo.java +++ b/core/java/android/content/pm/ConfigurationInfo.java @@ -22,7 +22,7 @@ import android.os.Parcelable; /** * Information you can retrieve about hardware configuration preferences * declared by an application. This corresponds to information collected from the - * AndroidManifest.xml's <uses-configuration> tags. + * AndroidManifest.xml's <uses-configuration> and the <uses-feature>tags. */ public class ConfigurationInfo implements Parcelable { /** @@ -70,6 +70,16 @@ public class ConfigurationInfo implements Parcelable { */ public int reqInputFeatures = 0; + /** + * Default value for {@link #reqGlEsVersion}; + */ + public static final int GL_ES_VERSION_UNDEFINED = 0; + /** + * The GLES version used by an application. The upper order 16 bits represent the + * major version and the lower order 16 bits the minor version. + */ + public int reqGlEsVersion; + public ConfigurationInfo() { } @@ -78,6 +88,7 @@ public class ConfigurationInfo implements Parcelable { reqKeyboardType = orig.reqKeyboardType; reqNavigation = orig.reqNavigation; reqInputFeatures = orig.reqInputFeatures; + reqGlEsVersion = orig.reqGlEsVersion; } public String toString() { @@ -86,7 +97,8 @@ public class ConfigurationInfo implements Parcelable { + ", touchscreen = " + reqTouchScreen + "}" + ", inputMethod = " + reqKeyboardType + "}" + ", navigation = " + reqNavigation + "}" - + ", reqInputFeatures = " + reqInputFeatures + "}"; + + ", reqInputFeatures = " + reqInputFeatures + "}" + + ", reqGlEsVersion = " + reqGlEsVersion + "}"; } public int describeContents() { @@ -98,6 +110,7 @@ public class ConfigurationInfo implements Parcelable { dest.writeInt(reqKeyboardType); dest.writeInt(reqNavigation); dest.writeInt(reqInputFeatures); + dest.writeInt(reqGlEsVersion); } public static final Creator<ConfigurationInfo> CREATOR = @@ -115,5 +128,18 @@ public class ConfigurationInfo implements Parcelable { reqKeyboardType = source.readInt(); reqNavigation = source.readInt(); reqInputFeatures = source.readInt(); + reqGlEsVersion = source.readInt(); + } + + /** + * This method extracts the major and minor version of reqGLEsVersion attribute + * and returns it as a string. Say reqGlEsVersion value of 0x00010002 is returned + * as 1.2 + * @return String representation of the reqGlEsVersion attribute + */ + public String getGlEsVersion() { + int major = ((reqGlEsVersion & 0xffff0000) >> 16); + int minor = reqGlEsVersion & 0x0000ffff; + return String.valueOf(major)+"."+String.valueOf(minor); } } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c199619..bf2a895 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -34,7 +34,7 @@ import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.net.Uri; -import android.app.PendingIntent; +import android.content.IntentSender; /** * See {@link PackageManager} for documentation on most of the APIs @@ -164,7 +164,12 @@ interface IPackageManager { void addPreferredActivity(in IntentFilter filter, int match, in ComponentName[] set, in ComponentName activity); + + void replacePreferredActivity(in IntentFilter filter, int match, + in ComponentName[] set, in ComponentName activity); + void clearPackagePreferredActivities(String packageName); + int getPreferredActivities(out List<IntentFilter> outFilters, out List<ComponentName> outActivities, String packageName); @@ -229,12 +234,12 @@ interface IPackageManager { * and the current free storage is YY, * if XX is less than YY, just return. if not free XX-YY number * of bytes if possible. - * @param opFinishedIntent PendingIntent call back used to + * @param pi IntentSender call back used to * notify when the operation is completed.May be null * to indicate that no call back is desired. */ void freeStorage(in long freeStorageSize, - in PendingIntent opFinishedIntent); + in IntentSender pi); /** * Delete all the cache files in an applications cache directory @@ -271,4 +276,11 @@ interface IPackageManager { boolean isSafeMode(); void systemReady(); boolean hasSystemUidErrors(); + + /** + * Ask the package manager to perform dex-opt (if needed) on the given + * package, if it already hasn't done mode. Only does this if running + * in the special development "no pre-dexopt" mode. + */ + boolean performDexOpt(String packageName); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 3a192f7..941ca9e 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -16,12 +16,11 @@ package android.content.pm; - -import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentSender; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; @@ -398,6 +397,15 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_TEST_ONLY = -15; /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the package being installed contains native code, but none that is + * compatible with the the device's CPU_ABI. + * @hide + */ + public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16; + + /** * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser was given a path that is not a file, or does not end with the expected @@ -563,9 +571,8 @@ public abstract class PackageManager { * launch the main activity in the package, or null if the package does * not contain such an activity. */ - public abstract Intent getLaunchIntentForPackage(String packageName) - throws NameNotFoundException; - + public abstract Intent getLaunchIntentForPackage(String packageName); + /** * Return an array of all of the secondary group-ids that have been * assigned to a package. @@ -1491,7 +1498,7 @@ public abstract class PackageManager { * @hide */ public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer); - + /** * Free storage by deleting LRU sorted list of cache files across * all applications. If the currently available free storage @@ -1509,13 +1516,13 @@ public abstract class PackageManager { * and the current free storage is YY, * if XX is less than YY, just return. if not free XX-YY number * of bytes if possible. - * @param opFinishedIntent PendingIntent call back used to + * @param pi IntentSender call back used to * notify when the operation is completed.May be null * to indicate that no call back is desired. * * @hide */ - public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent); + public abstract void freeStorage(long freeStorageSize, IntentSender pi); /** * Retrieve the size information for a package. @@ -1605,6 +1612,26 @@ public abstract class PackageManager { ComponentName[] set, ComponentName activity); /** + * Replaces an existing preferred activity mapping to the system, and if that were not present + * adds a new preferred activity. This will be used + * to automatically select the given activity component when + * {@link Context#startActivity(Intent) Context.startActivity()} finds + * multiple matching activities and also matches the given filter. + * + * @param filter The set of intents under which this activity will be + * made preferred. + * @param match The IntentFilter match category that this preference + * applies to. + * @param set The set of activities that the user was picking from when + * this preference was made. + * @param activity The component name of the activity that is to be + * preferred. + * @hide + */ + public abstract void replacePreferredActivity(IntentFilter filter, int match, + ComponentName[] set, ComponentName activity); + + /** * Remove all preferred activity mappings, previously added with * {@link #addPreferredActivity}, from the * system whose activities are implemented in the given package name. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 88907c1..558b0c3 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -55,6 +55,32 @@ import java.util.jar.JarFile; * {@hide} */ public class PackageParser { + /** @hide */ + public static class NewPermissionInfo { + public final String name; + public final int sdkVersion; + public final int fileVersion; + + public NewPermissionInfo(String name, int sdkVersion, int fileVersion) { + this.name = name; + this.sdkVersion = sdkVersion; + this.fileVersion = fileVersion; + } + } + + /** + * List of new permissions that have been added since 1.0. + * NOTE: These must be declared in SDK version order, with permissions + * added to older SDKs appearing before those added to newer SDKs. + * @hide + */ + public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = + new PackageParser.NewPermissionInfo[] { + new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + android.os.Build.VERSION_CODES.DONUT, 0), + new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE, + android.os.Build.VERSION_CODES.DONUT, 0) + }; private String mArchiveSourcePath; private String[] mSeparateProcesses; @@ -616,7 +642,6 @@ public class PackageParser { final Package pkg = new Package(pkgName); boolean foundApp = false; - boolean targetsSdk = false; TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest); @@ -643,6 +668,11 @@ public class PackageParser { } sa.recycle(); + // Resource boolean are -1, so 1 means we don't know the value. + int supportsSmallScreens = 1; + int supportsNormalScreens = 1; + int supportsLargeScreens = 1; + int outerDepth = parser.getDepth(); while ((type=parser.next()) != parser.END_DOCUMENT && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { @@ -723,6 +753,18 @@ public class PackageParser { XmlUtils.skipCurrentTag(parser); + } else if (tagName.equals("uses-feature")) { + ConfigurationInfo cPref = new ConfigurationInfo(); + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestUsesFeature); + cPref.reqGlEsVersion = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion, + ConfigurationInfo.GL_ES_VERSION_UNDEFINED); + sa.recycle(); + pkg.configPreferences.add(cPref); + + XmlUtils.skipCurrentTag(parser); + } else if (tagName.equals("uses-sdk")) { if (mSdkVersion > 0) { sa = res.obtainAttributes(attrs, @@ -740,7 +782,7 @@ public class PackageParser { targetCode = minCode = val.string.toString(); } else { // If it's not a string, it's an integer. - minVers = val.data; + targetVers = minVers = val.data; } } @@ -761,6 +803,25 @@ public class PackageParser { sa.recycle(); + if (minCode != null) { + if (!minCode.equals(mSdkCodename)) { + if (mSdkCodename != null) { + outError[0] = "Requires development platform " + minCode + + " (current platform is " + mSdkCodename + ")"; + } else { + outError[0] = "Requires development platform " + minCode + + " but this is a release platform."; + } + mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; + return null; + } + } else if (minVers > mSdkVersion) { + outError[0] = "Requires newer sdk version #" + minVers + + " (current version is #" + mSdkVersion + ")"; + mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; + return null; + } + if (targetCode != null) { if (!targetCode.equals(mSdkCodename)) { if (mSdkCodename != null) { @@ -774,18 +835,10 @@ public class PackageParser { return null; } // If the code matches, it definitely targets this SDK. - targetsSdk = true; - } else if (targetVers >= mSdkVersion) { - // If they have explicitly targeted our current version - // or something after it, then note this. - targetsSdk = true; - } - - if (minVers > mSdkVersion) { - outError[0] = "Requires newer sdk version #" + minVers - + " (current version is #" + mSdkVersion + ")"; - mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; - return null; + pkg.applicationInfo.targetSdkVersion + = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; + } else { + pkg.applicationInfo.targetSdkVersion = targetVers; } if (maxVers < mSdkVersion) { @@ -811,6 +864,42 @@ public class PackageParser { + parser.getName(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; + + + } else if (tagName.equals("supports-density")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestSupportsDensity); + + int density = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1); + + sa.recycle(); + + if (density != -1 && !pkg.supportsDensityList.contains(density)) { + pkg.supportsDensityList.add(density); + } + + XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("supports-screens")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestSupportsScreens); + + // This is a trick to get a boolean and still able to detect + // if a value was actually set. + supportsSmallScreens = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens, + supportsSmallScreens); + supportsNormalScreens = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens, + supportsNormalScreens); + supportsLargeScreens = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, + supportsLargeScreens); + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); } else { Log.w(TAG, "Bad element under <manifest>: " + parser.getName()); @@ -824,15 +913,39 @@ public class PackageParser { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; } - if (targetsSdk) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_TARGETS_SDK; + final int NP = PackageParser.NEW_PERMISSIONS.length; + for (int ip=0; ip<NP; ip++) { + final PackageParser.NewPermissionInfo npi + = PackageParser.NEW_PERMISSIONS[ip]; + if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) { + break; + } + if (!pkg.requestedPermissions.contains(npi.name)) { + Log.i(TAG, "Impliciting adding " + npi.name + " to old pkg " + + pkg.packageName); + pkg.requestedPermissions.add(npi.name); + } } if (pkg.usesLibraries.size() > 0) { pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()]; pkg.usesLibraries.toArray(pkg.usesLibraryFiles); } - + + if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 + && pkg.applicationInfo.targetSdkVersion + >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; + } + if (supportsNormalScreens != 0) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; + } + if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 + && pkg.applicationInfo.targetSdkVersion + >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; + } + int size = pkg.supportsDensityList.size(); if (size > 0) { int densities[] = pkg.supportsDensities = new int[size]; @@ -1142,6 +1255,19 @@ public class PackageParser { outError); } + boolean allowBackup = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true); + if (allowBackup) { + ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; + String backupAgent = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_backupAgent); + if (backupAgent != null) { + ai.backupAgentName = buildClassName(pkgName, backupAgent, outError); + Log.v(TAG, "android:backupAgent = " + ai.backupAgentName + + " from " + pkgName + "+" + backupAgent); + } + } + TypedValue v = sa.peekValue( com.android.internal.R.styleable.AndroidManifestApplication_label); if (v != null && (ai.labelRes=v.resourceId) == 0) { @@ -1298,21 +1424,6 @@ public class PackageParser { XmlUtils.skipCurrentTag(parser); - } else if (tagName.equals("supports-density")) { - sa = res.obtainAttributes(attrs, - com.android.internal.R.styleable.AndroidManifestSupportsDensity); - - int density = sa.getInteger( - com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1); - - sa.recycle(); - - if (density != -1 && !owner.supportsDensityList.contains(density)) { - owner.supportsDensityList.add(density); - } - - XmlUtils.skipCurrentTag(parser); - } else { if (!RIGID_PARSER) { Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); @@ -2219,6 +2330,17 @@ public class PackageParser { // preferred up order. public int mPreferredOrder = 0; + // For use by package manager service to keep track of which apps + // have been installed with forward locking. + public boolean mForwardLocked; + + // For use by the package manager to keep track of the path to the + // file an app came from. + public String mScanPath; + + // For use by package manager to keep track of where it has done dexopt. + public boolean mDidDexOpt; + // Additional data supplied by callers. public Object mExtras; @@ -2368,7 +2490,7 @@ public class PackageParser { return true; } if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0 - && p.supportsDensities != null) { + && p.supportsDensities != null) { return true; } return false; diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java index 231e3e2..a37e4e8 100644 --- a/core/java/android/content/res/AssetFileDescriptor.java +++ b/core/java/android/content/res/AssetFileDescriptor.java @@ -16,6 +16,7 @@ package android.content.res; +import android.os.MemoryFile; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; @@ -24,6 +25,8 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; /** * File descriptor of an entry in the AssetManager. This provides your own @@ -124,6 +127,13 @@ public class AssetFileDescriptor implements Parcelable { } /** + * Checks whether this file descriptor is for a memory file. + */ + private boolean isMemoryFile() throws IOException { + return MemoryFile.isMemoryFile(mFd.getFileDescriptor()); + } + + /** * Create and return a new auto-close input stream for this asset. This * will either return a full asset {@link AutoCloseInputStream}, or * an underlying {@link ParcelFileDescriptor.AutoCloseInputStream @@ -132,6 +142,12 @@ public class AssetFileDescriptor implements Parcelable { * should only call this once for a particular asset. */ public FileInputStream createInputStream() throws IOException { + if (isMemoryFile()) { + if (mLength > Integer.MAX_VALUE) { + throw new IOException("File length too large for a memory file: " + mLength); + } + return new AutoCloseMemoryFileInputStream(mFd, (int)mLength); + } if (mLength < 0) { return new ParcelFileDescriptor.AutoCloseInputStream(mFd); } @@ -262,6 +278,66 @@ public class AssetFileDescriptor implements Parcelable { } /** + * An input stream that reads from a MemoryFile and closes it when the stream is closed. + * This extends FileInputStream just because {@link #createInputStream} returns + * a FileInputStream. All the FileInputStream methods are + * overridden to use the MemoryFile instead. + */ + private static class AutoCloseMemoryFileInputStream extends FileInputStream { + private ParcelFileDescriptor mParcelFd; + private MemoryFile mFile; + private InputStream mStream; + + public AutoCloseMemoryFileInputStream(ParcelFileDescriptor fd, int length) + throws IOException { + super(fd.getFileDescriptor()); + mParcelFd = fd; + mFile = new MemoryFile(fd.getFileDescriptor(), length, "r"); + mStream = mFile.getInputStream(); + } + + @Override + public int available() throws IOException { + return mStream.available(); + } + + @Override + public void close() throws IOException { + mParcelFd.close(); // must close ParcelFileDescriptor, not just the file descriptor, + // since it could be a subclass of ParcelFileDescriptor. + // E.g. ContentResolver.ParcelFileDescriptorInner.close() releases + // a content provider + mFile.close(); // to unmap the memory file from the address space. + mStream.close(); // doesn't actually do anything + } + + @Override + public FileChannel getChannel() { + return null; + } + + @Override + public int read() throws IOException { + return mStream.read(); + } + + @Override + public int read(byte[] buffer, int offset, int count) throws IOException { + return mStream.read(buffer, offset, count); + } + + @Override + public int read(byte[] buffer) throws IOException { + return mStream.read(buffer); + } + + @Override + public long skip(long count) throws IOException { + return mStream.skip(count); + } + } + + /** * An OutputStream you can create on a ParcelFileDescriptor, which will * take care of calling {@link ParcelFileDescriptor#close * ParcelFileDescritor.close()} for you when the stream is closed. @@ -345,4 +421,16 @@ public class AssetFileDescriptor implements Parcelable { return new AssetFileDescriptor[size]; } }; + + /** + * Creates an AssetFileDescriptor from a memory file. + * + * @hide + */ + public static AssetFileDescriptor fromMemoryFile(MemoryFile memoryFile) + throws IOException { + ParcelFileDescriptor fd = memoryFile.getParcelFileDescriptor(); + return new AssetFileDescriptor(fd, 0, memoryFile.length()); + } + } diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 1c91736..5c7b01f 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -601,7 +601,7 @@ public final class AssetManager { public native final void setConfiguration(int mcc, int mnc, String locale, int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, int screenWidth, int screenHeight, - int majorVersion); + int screenLayout, int majorVersion); /** * Retrieve the resource identifier for the given resource name. diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java new file mode 100644 index 0000000..dfe304d --- /dev/null +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 + * running under. + * + * {@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(); + + /** + * The default width of the screen in portrait mode. + */ + public static final int DEFAULT_PORTRAIT_WIDTH = 320; + + /** + * The default height of the screen in portrait mode. + */ + public static final int DEFAULT_PORTRAIT_HEIGHT = 480; + + /** + * The x-shift mode that controls the position of the content or the window under + * compatibility mode. + * {@see getTranslator} + * {@see Translator#mShiftMode} + */ + 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; + + + /** + * A compatibility flags + */ + private int mCompatibilityFlags; + + /** + * 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 final float applicationScale; + + /** + * Application's inverted scale. + */ + public final float applicationInvertedScale; + + /** + * The flags from ApplicationInfo. + */ + public final int appFlags; + + /** + * Window size in Compatibility Mode, in real pixels. This is updated by + * {@link DisplayMetrics#updateMetrics}. + */ + private int mWidth; + private int mHeight; + + /** + * 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. + */ + private int mXOffset; + + public CompatibilityInfo(ApplicationInfo appInfo) { + appFlags = appInfo.flags; + + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE; + } + + float packageDensityScale = -1.0f; + if (appInfo.supportsDensities != null) { + int minDiff = Integer.MAX_VALUE; + for (int density : appInfo.supportsDensities) { + if (density == ApplicationInfo.ANY_DENSITY) { + packageDensityScale = 1.0f; + break; + } + int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density); + if (tmpDiff == 0) { + packageDensityScale = 1.0f; + break; + } + // prefer higher density (appScale>1.0), unless that's only option. + if (tmpDiff < minDiff && packageDensityScale < 1.0f) { + packageDensityScale = DisplayMetrics.DEVICE_DENSITY / (float) density; + minDiff = tmpDiff; + } + } + } + if (packageDensityScale > 0.0f) { + applicationScale = packageDensityScale; + } else { + applicationScale = + DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; + } + applicationInvertedScale = 1.0f / applicationScale; + if (applicationScale != 1.0f) { + mCompatibilityFlags |= SCALING_REQUIRED; + } + } + + private CompatibilityInfo(int appFlags, int compFlags, float scale, float invertedScale) { + this.appFlags = appFlags; + mCompatibilityFlags = compFlags; + applicationScale = scale; + applicationInvertedScale = invertedScale; + } + + private CompatibilityInfo() { + this(ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS, + EXPANDABLE | CONFIGURED_EXPANDABLE, + 1.0f, + 1.0f); + } + + /** + * Returns the copy of this instance. + */ + public CompatibilityInfo copy() { + CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags, + applicationScale, applicationInvertedScale); + info.setVisibleRect(mXOffset, mWidth, mHeight); + return info; + } + + /** + * 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) { + mCompatibilityFlags |= CompatibilityInfo.EXPANDABLE; + } else { + mCompatibilityFlags &= ~CompatibilityInfo.EXPANDABLE; + } + } + + /** + * @return true if the application is configured to be expandable. + */ + public boolean isConfiguredExpandable() { + return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0; + } + + /** + * @return true if the scaling is required + */ + public boolean isScalingRequired() { + return (mCompatibilityFlags & SCALING_REQUIRED) != 0; + } + + @Override + public String toString() { + return "CompatibilityInfo{scale=" + applicationScale + + ", compatibility flag=" + mCompatibilityFlags + "}"; + } + + /** + * 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 ( (mCompatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK) + == CompatibilityInfo.EXPANDABLE) { + if (DBG) Log.d(TAG, "no translation required"); + return null; + } + + if ((mCompatibilityFlags & 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; + } + } +} diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index bb3486c..577aa60 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -116,6 +116,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ public int orientation; + public static final int SCREENLAYOUT_UNDEFINED = 0; + public static final int SCREENLAYOUT_SMALL = 1; + public static final int SCREENLAYOUT_NORMAL = 2; + public static final int SCREENLAYOUT_LARGE = 3; + + /** + * Overall layout of the screen. May be one of + * {@link #SCREENLAYOUT_SMALL}, {@link #SCREENLAYOUT_NORMAL}, + * or {@link #SCREENLAYOUT_LARGE}. + */ + public int screenLayout; + /** * Construct an invalid Configuration. You must call {@link #setToDefaults} * for this object to be valid. {@more} @@ -141,6 +153,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration hardKeyboardHidden = o.hardKeyboardHidden; navigation = o.navigation; orientation = o.orientation; + screenLayout = o.screenLayout; } public String toString() { @@ -165,6 +178,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration sb.append(navigation); sb.append(" orien="); sb.append(orientation); + sb.append(" layout="); + sb.append(screenLayout); sb.append('}'); return sb.toString(); } @@ -183,6 +198,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; navigation = NAVIGATION_UNDEFINED; orientation = ORIENTATION_UNDEFINED; + screenLayout = SCREENLAYOUT_UNDEFINED; } /** {@hide} */ @@ -253,6 +269,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_ORIENTATION; orientation = delta.orientation; } + if (delta.screenLayout != SCREENLAYOUT_UNDEFINED + && screenLayout != delta.screenLayout) { + changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; + screenLayout = delta.screenLayout; + } return changed; } @@ -276,9 +297,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD * PackageManager.ActivityInfo.CONFIG_KEYBOARD}, * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION - * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or + * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION - * PackageManager.ActivityInfo.CONFIG_ORIENTATION}. + * PackageManager.ActivityInfo.CONFIG_ORIENTATION}, or + * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT + * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}. */ public int diff(Configuration delta) { int changed = 0; @@ -319,6 +342,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration && orientation != delta.orientation) { changed |= ActivityInfo.CONFIG_ORIENTATION; } + if (delta.screenLayout != SCREENLAYOUT_UNDEFINED + && screenLayout != delta.screenLayout) { + changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; + } return changed; } @@ -368,6 +395,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(hardKeyboardHidden); dest.writeInt(navigation); dest.writeInt(orientation); + dest.writeInt(screenLayout); } public static final Parcelable.Creator<Configuration> CREATOR @@ -399,6 +427,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration hardKeyboardHidden = source.readInt(); navigation = source.readInt(); orientation = source.readInt(); + screenLayout = source.readInt(); } public int compareTo(Configuration that) { @@ -428,6 +457,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration n = this.navigation - that.navigation; if (n != 0) return n; n = this.orientation - that.orientation; + if (n != 0) return n; + n = this.screenLayout - that.screenLayout; //if (n != 0) return n; return n; } @@ -450,6 +481,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration return ((int)this.fontScale) + this.mcc + this.mnc + this.locale.hashCode() + this.touchscreen + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden - + this.navigation + this.orientation; + + this.navigation + this.orientation + this.screenLayout; } } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 665e40c..49ad656 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -22,9 +22,9 @@ import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import android.content.pm.ApplicationInfo; import android.graphics.Movie; import android.graphics.drawable.Drawable; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.SystemProperties; @@ -33,6 +33,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; +import android.util.LongSparseArray; import java.io.IOException; import java.io.InputStream; @@ -57,19 +58,19 @@ public class Resources { // Information about preloaded resources. Note that they are not // protected by a lock, because while preloading in zygote we are all // single-threaded, and after that these are immutable. - private static final SparseArray<Drawable.ConstantState> sPreloadedDrawables - = new SparseArray<Drawable.ConstantState>(); + private static final LongSparseArray<Drawable.ConstantState> sPreloadedDrawables + = new LongSparseArray<Drawable.ConstantState>(); private static final SparseArray<ColorStateList> mPreloadedColorStateLists = new SparseArray<ColorStateList>(); private static boolean mPreloaded; - private final SparseArray<Drawable.ConstantState> mPreloadedDrawables; + private final LongSparseArray<Drawable.ConstantState> mPreloadedDrawables; /*package*/ final TypedValue mTmpValue = new TypedValue(); // These are protected by the mTmpValue lock. - private final SparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache - = new SparseArray<WeakReference<Drawable.ConstantState> >(); + private final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache + = new LongSparseArray<WeakReference<Drawable.ConstantState> >(); private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache = new SparseArray<WeakReference<ColorStateList> >(); private boolean mPreloading; @@ -84,21 +85,23 @@ public class Resources { private final Configuration mConfiguration = new Configuration(); /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics(); PluralRules mPluralRule; + + private final CompatibilityInfo mCompatibilityInfo; - private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() { + private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>() { @Override - public void put(int k, Object o) { + public void put(long k, Object o) { throw new UnsupportedOperationException(); } @Override - public void append(int k, Object o) { + public void append(long k, Object o) { throw new UnsupportedOperationException(); } }; @SuppressWarnings("unchecked") - private static <T> SparseArray<T> emptySparseArray() { - return (SparseArray<T>) EMPTY_ARRAY; + private static <T> LongSparseArray<T> emptySparseArray() { + return (LongSparseArray<T>) EMPTY_ARRAY; } /** @@ -126,26 +129,59 @@ public class Resources { */ public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { - this(assets, metrics, config, true); + this(assets, metrics, config, (ApplicationInfo) null); } /** - * Create a resource with an additional flag for preloaded - * drawable cache. Used by {@link ActivityThread}. - * + * Creates a new Resources object with ApplicationInfo. + * + * @param assets Previously created AssetManager. + * @param metrics Current display metrics to consider when + * selecting/computing resource values. + * @param config Desired device configuration to consider when + * selecting/computing resource values (optional). + * @param appInfo this resource's application info. * @hide */ public Resources(AssetManager assets, DisplayMetrics metrics, - Configuration config, boolean usePreloadedCache) { + Configuration config, ApplicationInfo appInfo) { mAssets = assets; mConfiguration.setToDefaults(); mMetrics.setToDefaults(); + if (appInfo != null) { + mCompatibilityInfo = new CompatibilityInfo(appInfo); + if (DEBUG_CONFIG) { + Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo); + } + } else { + mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; + } updateConfiguration(config, metrics); assets.ensureStringBlocks(); - if (usePreloadedCache) { - mPreloadedDrawables = sPreloadedDrawables; + if (mCompatibilityInfo.isScalingRequired()) { + mPreloadedDrawables = emptySparseArray(); } else { + mPreloadedDrawables = sPreloadedDrawables; + } + } + + /** + * Creates a new resources that uses the given compatibility info. Used to create + * a context for widgets using the container's compatibility info. + * {@see ApplicationContext#createPackageCotnext}. + * @hide + */ + public Resources(AssetManager assets, DisplayMetrics metrics, + Configuration config, CompatibilityInfo info) { + mAssets = assets; + mMetrics.setToDefaults(); + mCompatibilityInfo = info; + updateConfiguration(config, metrics); + assets.ensureStringBlocks(); + if (mCompatibilityInfo.isScalingRequired()) { mPreloadedDrawables = emptySparseArray(); + } else { + mPreloadedDrawables = sPreloadedDrawables; } } @@ -1238,7 +1274,7 @@ public class Resources { return array; } - + /** * Store the newly updated configuration. */ @@ -1251,6 +1287,8 @@ public class Resources { } if (metrics != null) { mMetrics.setTo(metrics); + mMetrics.updateMetrics(mCompatibilityInfo, + mConfiguration.orientation, mConfiguration.screenLayout); } mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; @@ -1282,7 +1320,7 @@ public class Resources { mConfiguration.touchscreen, (int)(mMetrics.density*160), mConfiguration.keyboard, keyboardHidden, mConfiguration.navigation, width, height, - sSdkVersion); + mConfiguration.screenLayout, sSdkVersion); int N = mDrawableCache.size(); if (DEBUG_CONFIG) { Log.d(TAG, "Cleaning up drawables config changes: 0x" @@ -1297,14 +1335,14 @@ public class Resources { configChanges, cs.getChangingConfigurations())) { if (DEBUG_CONFIG) { Log.d(TAG, "FLUSHING #0x" - + Integer.toHexString(mDrawableCache.keyAt(i)) + + Long.toHexString(mDrawableCache.keyAt(i)) + " / " + cs + " with changes: 0x" + Integer.toHexString(cs.getChangingConfigurations())); } mDrawableCache.setValueAt(i, null); } else if (DEBUG_CONFIG) { Log.d(TAG, "(Keeping #0x" - + Integer.toHexString(mDrawableCache.keyAt(i)) + + Long.toHexString(mDrawableCache.keyAt(i)) + " / " + cs + " with changes: 0x" + Integer.toHexString(cs.getChangingConfigurations()) + ")"); @@ -1356,6 +1394,17 @@ public class Resources { public Configuration getConfiguration() { return mConfiguration; } + + /** + * Return the compatibility mode information for the application. + * The returned object should be treated as read-only. + * + * @return compatibility info. null if the app does not require compatibility mode. + * @hide + */ + public CompatibilityInfo getCompatibilityInfo() { + return mCompatibilityInfo; + } /** * Return a resource identifier for the given resource name. A fully @@ -1624,7 +1673,7 @@ public class Resources { } } - final int key = (value.assetCookie << 24) | value.data; + final long key = (((long) value.assetCookie) << 32) | value.data; Drawable dr = getCachedDrawable(key); if (dr != null) { @@ -1704,7 +1753,7 @@ public class Resources { return dr; } - private Drawable getCachedDrawable(int key) { + private Drawable getCachedDrawable(long key) { synchronized (mTmpValue) { WeakReference<Drawable.ConstantState> wr = mDrawableCache.get(key); if (wr != null) { // we have the key @@ -1920,5 +1969,6 @@ public class Resources { updateConfiguration(null, null); mAssets.ensureStringBlocks(); mPreloadedDrawables = sPreloadedDrawables; + mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; } } 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/database/sqlite/SQLiteContentHelper.java b/core/java/android/database/sqlite/SQLiteContentHelper.java new file mode 100644 index 0000000..2800d86 --- /dev/null +++ b/core/java/android/database/sqlite/SQLiteContentHelper.java @@ -0,0 +1,92 @@ +/* + * 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.database.sqlite; + +import android.content.res.AssetFileDescriptor; +import android.database.Cursor; +import android.os.MemoryFile; + +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Some helper functions for using SQLite database to implement content providers. + * + * @hide + */ +public class SQLiteContentHelper { + + /** + * Runs an SQLite query and returns an AssetFileDescriptor for the + * blob in column 0 of the first row. If the first column does + * not contain a blob, an unspecified exception is thrown. + * + * @param db Handle to a readable database. + * @param sql SQL query, possibly with query arguments. + * @param selectionArgs Query argument values, or {@code null} for no argument. + * @return If no exception is thrown, a non-null AssetFileDescriptor is returned. + * @throws FileNotFoundException If the query returns no results or the + * value of column 0 is NULL, or if there is an error creating the + * asset file descriptor. + */ + public static AssetFileDescriptor getBlobColumnAsAssetFile(SQLiteDatabase db, String sql, + String[] selectionArgs) throws FileNotFoundException { + try { + MemoryFile file = simpleQueryForBlobMemoryFile(db, sql, selectionArgs); + if (file == null) { + throw new FileNotFoundException("No results."); + } + return AssetFileDescriptor.fromMemoryFile(file); + } catch (IOException ex) { + throw new FileNotFoundException(ex.toString()); + } + } + + /** + * Runs an SQLite query and returns a MemoryFile for the + * blob in column 0 of the first row. If the first column does + * not contain a blob, an unspecified exception is thrown. + * + * @return A memory file, or {@code null} if the query returns no results + * or the value column 0 is NULL. + * @throws IOException If there is an error creating the memory file. + */ + // TODO: make this native and use the SQLite blob API to reduce copying + private static MemoryFile simpleQueryForBlobMemoryFile(SQLiteDatabase db, String sql, + String[] selectionArgs) throws IOException { + Cursor cursor = db.rawQuery(sql, selectionArgs); + if (cursor == null) { + return null; + } + try { + if (!cursor.moveToFirst()) { + return null; + } + byte[] bytes = cursor.getBlob(0); + if (bytes == null) { + return null; + } + MemoryFile file = new MemoryFile(null, bytes.length); + file.writeBytes(bytes, 0, 0, bytes.length); + file.deactivate(); + return file; + } finally { + cursor.close(); + } + } + +} diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java index ab7c827..8a63919 100644 --- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java +++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java @@ -18,16 +18,15 @@ package android.database.sqlite; import android.database.Cursor; import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; import android.provider.BaseColumns; import android.text.TextUtils; -import android.util.Config; import android.util.Log; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; +import java.util.regex.Pattern; /** * This is a convience class that helps build SQL queries to be sent to @@ -36,10 +35,12 @@ import java.util.Map.Entry; public class SQLiteQueryBuilder { private static final String TAG = "SQLiteQueryBuilder"; + private static final Pattern sLimitPattern = + Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?"); private Map<String, String> mProjectionMap = null; private String mTables = ""; - private StringBuilder mWhereClause = new StringBuilder(64); + private final StringBuilder mWhereClause = new StringBuilder(64); private boolean mDistinct; private SQLiteDatabase.CursorFactory mFactory; @@ -169,6 +170,9 @@ public class SQLiteQueryBuilder throw new IllegalArgumentException( "HAVING clauses are only permitted when using a groupBy clause"); } + if (!TextUtils.isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) { + throw new IllegalArgumentException("invalid LIMIT clauses:" + limit); + } StringBuilder query = new StringBuilder(120); @@ -187,7 +191,7 @@ public class SQLiteQueryBuilder appendClause(query, " GROUP BY ", groupBy); appendClause(query, " HAVING ", having); appendClause(query, " ORDER BY ", orderBy); - appendClauseEscapeClause(query, " LIMIT ", limit); + appendClause(query, " LIMIT ", limit); return query.toString(); } diff --git a/core/java/android/gesture/Gesture.java b/core/java/android/gesture/Gesture.java new file mode 100755 index 0000000..2262477 --- /dev/null +++ b/core/java/android/gesture/Gesture.java @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.util.ArrayList; + +/** + * A gesture can have a single or multiple strokes + */ + +public class Gesture implements Parcelable { + private static final long GESTURE_ID_BASE = System.currentTimeMillis(); + + private static final int BITMAP_RENDERING_WIDTH = 2; + + private static final boolean BITMAP_RENDERING_ANTIALIAS = true; + private static final boolean BITMAP_RENDERING_DITHER = true; + + private static int sGestureCount = 0; + + private final RectF mBoundingBox = new RectF(); + + // the same as its instance ID + private long mGestureID; + + private final ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>(); + + public Gesture() { + mGestureID = GESTURE_ID_BASE + sGestureCount++; + } + + void recycle() { + mStrokes.clear(); + mBoundingBox.setEmpty(); + } + + /** + * @return all the strokes of the gesture + */ + public ArrayList<GestureStroke> getStrokes() { + return mStrokes; + } + + /** + * @return the number of strokes included by this gesture + */ + public int getStrokesCount() { + return mStrokes.size(); + } + + /** + * Add a stroke to the gesture + * + * @param stroke + */ + public void addStroke(GestureStroke stroke) { + mStrokes.add(stroke); + mBoundingBox.union(stroke.boundingBox); + } + + /** + * Get the total length of the gesture. When there are multiple strokes in + * the gesture, this returns the sum of the lengths of all the strokes + * + * @return the length of the gesture + */ + public float getLength() { + int len = 0; + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + for (int i = 0; i < count; i++) { + len += strokes.get(i).length; + } + + return len; + } + + /** + * @return the bounding box of the gesture + */ + public RectF getBoundingBox() { + return mBoundingBox; + } + + public Path toPath() { + return toPath(null); + } + + public Path toPath(Path path) { + if (path == null) path = new Path(); + + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + for (int i = 0; i < count; i++) { + path.addPath(strokes.get(i).getPath()); + } + + return path; + } + + public Path toPath(int width, int height, int edge, int numSample) { + return toPath(null, width, height, edge, numSample); + } + + public Path toPath(Path path, int width, int height, int edge, int numSample) { + if (path == null) path = new Path(); + + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + for (int i = 0; i < count; i++) { + path.addPath(strokes.get(i).toPath(width - 2 * edge, height - 2 * edge, numSample)); + } + + return path; + } + + /** + * Set the id of the gesture + * + * @param id + */ + void setID(long id) { + mGestureID = id; + } + + /** + * @return the id of the gesture + */ + public long getID() { + return mGestureID; + } + + /** + * draw the gesture + * + * @param canvas + */ + void draw(Canvas canvas, Paint paint) { + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + for (int i = 0; i < count; i++) { + strokes.get(i).draw(canvas, paint); + } + } + + /** + * Create a bitmap of the gesture with a transparent background + * + * @param width width of the target bitmap + * @param height height of the target bitmap + * @param edge the edge + * @param numSample + * @param color + * @return the bitmap + */ + public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) { + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + + canvas.translate(edge, edge); + + final Paint paint = new Paint(); + paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS); + paint.setDither(BITMAP_RENDERING_DITHER); + paint.setColor(color); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeJoin(Paint.Join.ROUND); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeWidth(BITMAP_RENDERING_WIDTH); + + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + for (int i = 0; i < count; i++) { + Path path = strokes.get(i).toPath(width - 2 * edge, height - 2 * edge, numSample); + canvas.drawPath(path, paint); + } + + return bitmap; + } + + /** + * Create a bitmap of the gesture with a transparent background + * + * @param width + * @param height + * @param inset + * @param color + * @return the bitmap + */ + public Bitmap toBitmap(int width, int height, int inset, int color) { + final Bitmap bitmap = Bitmap.createBitmap(width, height, + Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + + final Paint paint = new Paint(); + paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS); + paint.setDither(BITMAP_RENDERING_DITHER); + paint.setColor(color); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeJoin(Paint.Join.ROUND); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeWidth(BITMAP_RENDERING_WIDTH); + + final Path path = toPath(); + final RectF bounds = new RectF(); + path.computeBounds(bounds, true); + + final float sx = (width - 2 * inset) / bounds.width(); + final float sy = (height - 2 * inset) / bounds.height(); + final float scale = sx > sy ? sy : sx; + paint.setStrokeWidth(2.0f / scale); + + path.offset(-bounds.left + (width - bounds.width() * scale) / 2.0f, + -bounds.top + (height - bounds.height() * scale) / 2.0f); + + canvas.translate(inset, inset); + canvas.scale(scale, scale); + + canvas.drawPath(path, paint); + + return bitmap; + } + + void serialize(DataOutputStream out) throws IOException { + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + // Write gesture ID + out.writeLong(mGestureID); + // Write number of strokes + out.writeInt(count); + + for (int i = 0; i < count; i++) { + strokes.get(i).serialize(out); + } + } + + static Gesture deserialize(DataInputStream in) throws IOException { + final Gesture gesture = new Gesture(); + + // Gesture ID + gesture.mGestureID = in.readLong(); + // Number of strokes + final int count = in.readInt(); + + for (int i = 0; i < count; i++) { + gesture.addStroke(GestureStroke.deserialize(in)); + } + + return gesture; + } + + public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() { + public Gesture createFromParcel(Parcel in) { + Gesture gesture = null; + final long gestureID = in.readLong(); + + final DataInputStream inStream = new DataInputStream( + new ByteArrayInputStream(in.createByteArray())); + + try { + gesture = deserialize(inStream); + } catch (IOException e) { + Log.e(GestureConstants.LOG_TAG, "Error reading Gesture from parcel:", e); + } finally { + GestureUtilities.closeStream(inStream); + } + + if (gesture != null) { + gesture.mGestureID = gestureID; + } + + return gesture; + } + + public Gesture[] newArray(int size) { + return new Gesture[size]; + } + }; + + public void writeToParcel(Parcel out, int flags) { + out.writeLong(mGestureID); + + boolean result = false; + final ByteArrayOutputStream byteStream = + new ByteArrayOutputStream(GestureConstants.IO_BUFFER_SIZE); + final DataOutputStream outStream = new DataOutputStream(byteStream); + + try { + serialize(outStream); + result = true; + } catch (IOException e) { + Log.e(GestureConstants.LOG_TAG, "Error writing Gesture to parcel:", e); + } finally { + GestureUtilities.closeStream(outStream); + GestureUtilities.closeStream(byteStream); + } + + if (result) { + out.writeByteArray(byteStream.toByteArray()); + } + } + + public int describeContents() { + return 0; + } +} + diff --git a/core/java/android/gesture/GestureConstants.java b/core/java/android/gesture/GestureConstants.java new file mode 100644 index 0000000..230db0c --- /dev/null +++ b/core/java/android/gesture/GestureConstants.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +interface GestureConstants { + static final int STROKE_STRING_BUFFER_SIZE = 1024; + static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points + + static final int IO_BUFFER_SIZE = 32 * 1024; // 32K + + static final String LOG_TAG = "Gestures"; +} diff --git a/core/java/android/gesture/GestureLibraries.java b/core/java/android/gesture/GestureLibraries.java new file mode 100644 index 0000000..6d6c156 --- /dev/null +++ b/core/java/android/gesture/GestureLibraries.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.util.Log; +import static android.gesture.GestureConstants.*; +import android.content.Context; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.ref.WeakReference; + +public final class GestureLibraries { + private GestureLibraries() { + } + + public static GestureLibrary fromFile(String path) { + return fromFile(new File(path)); + } + + public static GestureLibrary fromFile(File path) { + return new FileGestureLibrary(path); + } + + public static GestureLibrary fromPrivateFile(Context context, String name) { + return fromFile(context.getFileStreamPath(name)); + } + + public static GestureLibrary fromRawResource(Context context, int resourceId) { + return new ResourceGestureLibrary(context, resourceId); + } + + private static class FileGestureLibrary extends GestureLibrary { + private final File mPath; + + public FileGestureLibrary(File path) { + mPath = path; + } + + @Override + public boolean isReadOnly() { + return !mPath.canWrite(); + } + + public boolean save() { + if (!mStore.hasChanged()) return true; + + final File file = mPath; + + final File parentFile = file.getParentFile(); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + return false; + } + } + + boolean result = false; + try { + //noinspection ResultOfMethodCallIgnored + file.createNewFile(); + mStore.save(new FileOutputStream(file), true); + result = true; + } catch (FileNotFoundException e) { + Log.d(LOG_TAG, "Could not save the gesture library in " + mPath, e); + } catch (IOException e) { + Log.d(LOG_TAG, "Could not save the gesture library in " + mPath, e); + } + + return result; + } + + public boolean load() { + boolean result = false; + final File file = mPath; + if (file.exists() && file.canRead()) { + try { + mStore.load(new FileInputStream(file), true); + result = true; + } catch (FileNotFoundException e) { + Log.d(LOG_TAG, "Could not load the gesture library from " + mPath, e); + } catch (IOException e) { + Log.d(LOG_TAG, "Could not load the gesture library from " + mPath, e); + } + } + + return result; + } + } + + private static class ResourceGestureLibrary extends GestureLibrary { + private final WeakReference<Context> mContext; + private final int mResourceId; + + public ResourceGestureLibrary(Context context, int resourceId) { + mContext = new WeakReference<Context>(context); + mResourceId = resourceId; + } + + @Override + public boolean isReadOnly() { + return true; + } + + public boolean save() { + return false; + } + + public boolean load() { + boolean result = false; + final Context context = mContext.get(); + if (context != null) { + final InputStream in = context.getResources().openRawResource(mResourceId); + try { + mStore.load(in, true); + result = true; + } catch (IOException e) { + Log.d(LOG_TAG, "Could not load the gesture library from raw resource " + + context.getResources().getResourceName(mResourceId), e); + } + } + + return result; + } + } +} diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java new file mode 100644 index 0000000..a29c2c8 --- /dev/null +++ b/core/java/android/gesture/GestureLibrary.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.gesture; + +import java.util.Set; +import java.util.ArrayList; + +public abstract class GestureLibrary { + protected final GestureStore mStore; + + protected GestureLibrary() { + mStore = new GestureStore(); + } + + public abstract boolean save(); + + public abstract boolean load(); + + public boolean isReadOnly() { + return false; + } + + public Learner getLearner() { + return mStore.getLearner(); + } + + public void setOrientationStyle(int style) { + mStore.setOrientationStyle(style); + } + + public int getOrientationStyle() { + return mStore.getOrientationStyle(); + } + + public void setSequenceType(int type) { + mStore.setSequenceType(type); + } + + public int getSequenceType() { + return mStore.getSequenceType(); + } + + public Set<String> getGestureEntries() { + return mStore.getGestureEntries(); + } + + public ArrayList<Prediction> recognize(Gesture gesture) { + return mStore.recognize(gesture); + } + + public void addGesture(String entryName, Gesture gesture) { + mStore.addGesture(entryName, gesture); + } + + public void removeGesture(String entryName, Gesture gesture) { + mStore.removeGesture(entryName, gesture); + } + + public void removeEntry(String entryName) { + mStore.removeEntry(entryName); + } + + public ArrayList<Gesture> getGestures(String entryName) { + return mStore.getGestures(entryName); + } +} diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java new file mode 100755 index 0000000..5bfdcc4 --- /dev/null +++ b/core/java/android/gesture/GestureOverlayView.java @@ -0,0 +1,793 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.animation.AnimationUtils; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.FrameLayout; +import android.os.SystemClock; +import com.android.internal.R; + +import java.util.ArrayList; + +/** + * A transparent overlay for gesture input that can be placed on top of other + * widgets or contain other widgets. + * + * @attr ref android.R.styleable#GestureOverlayView_eventsInterceptionEnabled + * @attr ref android.R.styleable#GestureOverlayView_fadeDuration + * @attr ref android.R.styleable#GestureOverlayView_fadeOffset + * @attr ref android.R.styleable#GestureOverlayView_fadeEnabled + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeWidth + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeAngleThreshold + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeLengthThreshold + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeSquarenessThreshold + * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType + * @attr ref android.R.styleable#GestureOverlayView_gestureColor + * @attr ref android.R.styleable#GestureOverlayView_orientation + * @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor + */ +public class GestureOverlayView extends FrameLayout { + public static final int GESTURE_STROKE_TYPE_SINGLE = 0; + public static final int GESTURE_STROKE_TYPE_MULTIPLE = 1; + + public static final int ORIENTATION_HORIZONTAL = 0; + public static final int ORIENTATION_VERTICAL = 1; + + private static final int FADE_ANIMATION_RATE = 16; + private static final boolean GESTURE_RENDERING_ANTIALIAS = true; + private static final boolean DITHER_FLAG = true; + + private final Paint mGesturePaint = new Paint(); + + private long mFadeDuration = 150; + private long mFadeOffset = 420; + private long mFadingStart; + private boolean mFadingHasStarted; + private boolean mFadeEnabled = true; + + private int mCurrentColor; + private int mCertainGestureColor = 0xFFFFFF00; + private int mUncertainGestureColor = 0x48FFFF00; + private float mGestureStrokeWidth = 12.0f; + private int mInvalidateExtraBorder = 10; + + private int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE; + private float mGestureStrokeLengthThreshold = 50.0f; + private float mGestureStrokeSquarenessTreshold = 0.275f; + private float mGestureStrokeAngleThreshold = 40.0f; + + private int mOrientation = ORIENTATION_VERTICAL; + + private final Rect mInvalidRect = new Rect(); + private final Path mPath = new Path(); + private boolean mGestureVisible = true; + + private float mX; + private float mY; + + private float mCurveEndX; + private float mCurveEndY; + + private float mTotalLength; + private boolean mIsGesturing = false; + private boolean mPreviousWasGesturing = false; + private boolean mInterceptEvents = true; + private boolean mIsListeningForGestures; + private boolean mResetGesture; + + // current gesture + private Gesture mCurrentGesture; + private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100); + + // TODO: Make this a list of WeakReferences + private final ArrayList<OnGestureListener> mOnGestureListeners = + new ArrayList<OnGestureListener>(); + // TODO: Make this a list of WeakReferences + private final ArrayList<OnGesturePerformedListener> mOnGesturePerformedListeners = + new ArrayList<OnGesturePerformedListener>(); + // TODO: Make this a list of WeakReferences + private final ArrayList<OnGesturingListener> mOnGesturingListeners = + new ArrayList<OnGesturingListener>(); + + private boolean mHandleGestureActions; + + // fading out effect + private boolean mIsFadingOut = false; + private float mFadingAlpha = 1.0f; + private final AccelerateDecelerateInterpolator mInterpolator = + new AccelerateDecelerateInterpolator(); + + private final FadeOutRunnable mFadingOut = new FadeOutRunnable(); + + public GestureOverlayView(Context context) { + super(context); + init(); + } + + public GestureOverlayView(Context context, AttributeSet attrs) { + this(context, attrs, com.android.internal.R.attr.gestureOverlayViewStyle); + } + + public GestureOverlayView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.GestureOverlayView, defStyle, 0); + + mGestureStrokeWidth = a.getFloat(R.styleable.GestureOverlayView_gestureStrokeWidth, + mGestureStrokeWidth); + mInvalidateExtraBorder = Math.max(1, ((int) mGestureStrokeWidth) - 1); + mCertainGestureColor = a.getColor(R.styleable.GestureOverlayView_gestureColor, + mCertainGestureColor); + mUncertainGestureColor = a.getColor(R.styleable.GestureOverlayView_uncertainGestureColor, + mUncertainGestureColor); + mFadeDuration = a.getInt(R.styleable.GestureOverlayView_fadeDuration, (int) mFadeDuration); + mFadeOffset = a.getInt(R.styleable.GestureOverlayView_fadeOffset, (int) mFadeOffset); + mGestureStrokeType = a.getInt(R.styleable.GestureOverlayView_gestureStrokeType, + mGestureStrokeType); + mGestureStrokeLengthThreshold = a.getFloat( + R.styleable.GestureOverlayView_gestureStrokeLengthThreshold, + mGestureStrokeLengthThreshold); + mGestureStrokeAngleThreshold = a.getFloat( + R.styleable.GestureOverlayView_gestureStrokeAngleThreshold, + mGestureStrokeAngleThreshold); + mGestureStrokeSquarenessTreshold = a.getFloat( + R.styleable.GestureOverlayView_gestureStrokeSquarenessThreshold, + mGestureStrokeSquarenessTreshold); + mInterceptEvents = a.getBoolean(R.styleable.GestureOverlayView_eventsInterceptionEnabled, + mInterceptEvents); + mFadeEnabled = a.getBoolean(R.styleable.GestureOverlayView_fadeEnabled, + mFadeEnabled); + mOrientation = a.getInt(R.styleable.GestureOverlayView_orientation, mOrientation); + + a.recycle(); + + init(); + } + + private void init() { + setWillNotDraw(false); + + final Paint gesturePaint = mGesturePaint; + gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS); + gesturePaint.setColor(mCertainGestureColor); + gesturePaint.setStyle(Paint.Style.STROKE); + gesturePaint.setStrokeJoin(Paint.Join.ROUND); + gesturePaint.setStrokeCap(Paint.Cap.ROUND); + gesturePaint.setStrokeWidth(mGestureStrokeWidth); + gesturePaint.setDither(DITHER_FLAG); + + mCurrentColor = mCertainGestureColor; + setPaintAlpha(255); + } + + public ArrayList<GesturePoint> getCurrentStroke() { + return mStrokeBuffer; + } + + public int getOrientation() { + return mOrientation; + } + + public void setOrientation(int orientation) { + mOrientation = orientation; + } + + public void setGestureColor(int color) { + mCertainGestureColor = color; + } + + public void setUncertainGestureColor(int color) { + mUncertainGestureColor = color; + } + + public int getUncertainGestureColor() { + return mUncertainGestureColor; + } + + public int getGestureColor() { + return mCertainGestureColor; + } + + public float getGestureStrokeWidth() { + return mGestureStrokeWidth; + } + + public void setGestureStrokeWidth(float gestureStrokeWidth) { + mGestureStrokeWidth = gestureStrokeWidth; + mInvalidateExtraBorder = Math.max(1, ((int) gestureStrokeWidth) - 1); + mGesturePaint.setStrokeWidth(gestureStrokeWidth); + } + + public int getGestureStrokeType() { + return mGestureStrokeType; + } + + public void setGestureStrokeType(int gestureStrokeType) { + mGestureStrokeType = gestureStrokeType; + } + + public float getGestureStrokeLengthThreshold() { + return mGestureStrokeLengthThreshold; + } + + public void setGestureStrokeLengthThreshold(float gestureStrokeLengthThreshold) { + mGestureStrokeLengthThreshold = gestureStrokeLengthThreshold; + } + + public float getGestureStrokeSquarenessTreshold() { + return mGestureStrokeSquarenessTreshold; + } + + public void setGestureStrokeSquarenessTreshold(float gestureStrokeSquarenessTreshold) { + mGestureStrokeSquarenessTreshold = gestureStrokeSquarenessTreshold; + } + + public float getGestureStrokeAngleThreshold() { + return mGestureStrokeAngleThreshold; + } + + public void setGestureStrokeAngleThreshold(float gestureStrokeAngleThreshold) { + mGestureStrokeAngleThreshold = gestureStrokeAngleThreshold; + } + + public boolean isEventsInterceptionEnabled() { + return mInterceptEvents; + } + + public void setEventsInterceptionEnabled(boolean enabled) { + mInterceptEvents = enabled; + } + + public boolean isFadeEnabled() { + return mFadeEnabled; + } + + public void setFadeEnabled(boolean fadeEnabled) { + mFadeEnabled = fadeEnabled; + } + + public Gesture getGesture() { + return mCurrentGesture; + } + + public void setGesture(Gesture gesture) { + if (mCurrentGesture != null) { + clear(false); + } + + setCurrentColor(mCertainGestureColor); + mCurrentGesture = gesture; + + final Path path = mCurrentGesture.toPath(); + final RectF bounds = new RectF(); + path.computeBounds(bounds, true); + + // TODO: The path should also be scaled to fit inside this view + mPath.rewind(); + mPath.addPath(path, -bounds.left + (getWidth() - bounds.width()) / 2.0f, + -bounds.top + (getHeight() - bounds.height()) / 2.0f); + + mResetGesture = true; + + invalidate(); + } + + public Path getGesturePath() { + return mPath; + } + + public Path getGesturePath(Path path) { + path.set(mPath); + return path; + } + + public boolean isGestureVisible() { + return mGestureVisible; + } + + public void setGestureVisible(boolean visible) { + mGestureVisible = visible; + } + + public long getFadeOffset() { + return mFadeOffset; + } + + public void setFadeOffset(long fadeOffset) { + mFadeOffset = fadeOffset; + } + + public void addOnGestureListener(OnGestureListener listener) { + mOnGestureListeners.add(listener); + } + + public void removeOnGestureListener(OnGestureListener listener) { + mOnGestureListeners.remove(listener); + } + + public void removeAllOnGestureListeners() { + mOnGestureListeners.clear(); + } + + public void addOnGesturePerformedListener(OnGesturePerformedListener listener) { + mOnGesturePerformedListeners.add(listener); + if (mOnGesturePerformedListeners.size() > 0) { + mHandleGestureActions = true; + } + } + + public void removeOnGesturePerformedListener(OnGesturePerformedListener listener) { + mOnGesturePerformedListeners.remove(listener); + if (mOnGesturePerformedListeners.size() <= 0) { + mHandleGestureActions = false; + } + } + + public void removeAllOnGesturePerformedListeners() { + mOnGesturePerformedListeners.clear(); + mHandleGestureActions = false; + } + + public void addOnGesturingListener(OnGesturingListener listener) { + mOnGesturingListeners.add(listener); + } + + public void removeOnGesturingListener(OnGesturingListener listener) { + mOnGesturingListeners.remove(listener); + } + + public void removeAllOnGesturingListeners() { + mOnGesturingListeners.clear(); + } + + public boolean isGesturing() { + return mIsGesturing; + } + + private void setCurrentColor(int color) { + mCurrentColor = color; + if (mFadingHasStarted) { + setPaintAlpha((int) (255 * mFadingAlpha)); + } else { + setPaintAlpha(255); + } + invalidate(); + } + + /** + * @hide + */ + public Paint getGesturePaint() { + return mGesturePaint; + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + if (mCurrentGesture != null && mGestureVisible) { + canvas.drawPath(mPath, mGesturePaint); + } + } + + private void setPaintAlpha(int alpha) { + alpha += alpha >> 7; + final int baseAlpha = mCurrentColor >>> 24; + final int useAlpha = baseAlpha * alpha >> 8; + mGesturePaint.setColor((mCurrentColor << 8 >>> 8) | (useAlpha << 24)); + } + + public void clear(boolean animated) { + clear(animated, false, true); + } + + private void clear(boolean animated, boolean fireActionPerformed, boolean immediate) { + setPaintAlpha(255); + removeCallbacks(mFadingOut); + mResetGesture = false; + mFadingOut.fireActionPerformed = fireActionPerformed; + mFadingOut.resetMultipleStrokes = false; + + if (animated && mCurrentGesture != null) { + mFadingAlpha = 1.0f; + mIsFadingOut = true; + mFadingHasStarted = false; + mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset; + + postDelayed(mFadingOut, mFadeOffset); + } else { + mFadingAlpha = 1.0f; + mIsFadingOut = false; + mFadingHasStarted = false; + + if (immediate) { + mCurrentGesture = null; + mPath.rewind(); + invalidate(); + } else if (fireActionPerformed) { + postDelayed(mFadingOut, mFadeOffset); + } else if (mGestureStrokeType == GESTURE_STROKE_TYPE_MULTIPLE) { + mFadingOut.resetMultipleStrokes = true; + postDelayed(mFadingOut, mFadeOffset); + } else { + mCurrentGesture = null; + mPath.rewind(); + invalidate(); + } + } + } + + public void cancelClearAnimation() { + setPaintAlpha(255); + mIsFadingOut = false; + mFadingHasStarted = false; + removeCallbacks(mFadingOut); + mPath.rewind(); + mCurrentGesture = null; + } + + public void cancelGesture() { + mIsListeningForGestures = false; + + // add the stroke to the current gesture + mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer)); + + // pass the event to handlers + final long now = SystemClock.uptimeMillis(); + final MotionEvent event = MotionEvent.obtain(now, now, + MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); + + final ArrayList<OnGestureListener> listeners = mOnGestureListeners; + int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureCancelled(this, event); + } + + event.recycle(); + + clear(false); + mIsGesturing = false; + mPreviousWasGesturing = false; + mStrokeBuffer.clear(); + + final ArrayList<OnGesturingListener> otherListeners = mOnGesturingListeners; + count = otherListeners.size(); + for (int i = 0; i < count; i++) { + otherListeners.get(i).onGesturingEnded(this); + } + } + + @Override + protected void onDetachedFromWindow() { + cancelClearAnimation(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (isEnabled()) { + final boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null && + mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) && + mInterceptEvents; + + processEvent(event); + + if (cancelDispatch) { + event.setAction(MotionEvent.ACTION_CANCEL); + } + + super.dispatchTouchEvent(event); + + return true; + } + + return super.dispatchTouchEvent(event); + } + + private boolean processEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + touchDown(event); + invalidate(); + return true; + case MotionEvent.ACTION_MOVE: + if (mIsListeningForGestures) { + Rect rect = touchMove(event); + if (rect != null) { + invalidate(rect); + } + return true; + } + break; + case MotionEvent.ACTION_UP: + if (mIsListeningForGestures) { + touchUp(event, false); + invalidate(); + return true; + } + break; + case MotionEvent.ACTION_CANCEL: + if (mIsListeningForGestures) { + touchUp(event, true); + invalidate(); + return true; + } + } + + return false; + } + + private void touchDown(MotionEvent event) { + mIsListeningForGestures = true; + + float x = event.getX(); + float y = event.getY(); + + mX = x; + mY = y; + + mTotalLength = 0; + mIsGesturing = false; + + if (mGestureStrokeType == GESTURE_STROKE_TYPE_SINGLE || mResetGesture) { + if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor); + mResetGesture = false; + mCurrentGesture = null; + mPath.rewind(); + } else if (mCurrentGesture == null || mCurrentGesture.getStrokesCount() == 0) { + if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor); + } + + // if there is fading out going on, stop it. + if (mFadingHasStarted) { + cancelClearAnimation(); + } else if (mIsFadingOut) { + setPaintAlpha(255); + mIsFadingOut = false; + mFadingHasStarted = false; + removeCallbacks(mFadingOut); + } + + if (mCurrentGesture == null) { + mCurrentGesture = new Gesture(); + } + + mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); + mPath.moveTo(x, y); + + final int border = mInvalidateExtraBorder; + mInvalidRect.set((int) x - border, (int) y - border, (int) x + border, (int) y + border); + + mCurveEndX = x; + mCurveEndY = y; + + // pass the event to handlers + final ArrayList<OnGestureListener> listeners = mOnGestureListeners; + final int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureStarted(this, event); + } + } + + private Rect touchMove(MotionEvent event) { + Rect areaToRefresh = null; + + final float x = event.getX(); + final float y = event.getY(); + + final float previousX = mX; + final float previousY = mY; + + final float dx = Math.abs(x - previousX); + final float dy = Math.abs(y - previousY); + + if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) { + areaToRefresh = mInvalidRect; + + // start with the curve end + final int border = mInvalidateExtraBorder; + areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border, + (int) mCurveEndX + border, (int) mCurveEndY + border); + + float cX = mCurveEndX = (x + previousX) / 2; + float cY = mCurveEndY = (y + previousY) / 2; + + mPath.quadTo(previousX, previousY, cX, cY); + + // union with the control point of the new curve + areaToRefresh.union((int) previousX - border, (int) previousY - border, + (int) previousX + border, (int) previousY + border); + + // union with the end point of the new curve + areaToRefresh.union((int) cX - border, (int) cY - border, + (int) cX + border, (int) cY + border); + + mX = x; + mY = y; + + mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); + + if (mHandleGestureActions && !mIsGesturing) { + mTotalLength += (float) Math.sqrt(dx * dx + dy * dy); + + if (mTotalLength > mGestureStrokeLengthThreshold) { + final OrientedBoundingBox box = + GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer); + + float angle = Math.abs(box.orientation); + if (angle > 90) { + angle = 180 - angle; + } + + if (box.squareness > mGestureStrokeSquarenessTreshold || + (mOrientation == ORIENTATION_VERTICAL ? + angle < mGestureStrokeAngleThreshold : + angle > mGestureStrokeAngleThreshold)) { + + mIsGesturing = true; + setCurrentColor(mCertainGestureColor); + + final ArrayList<OnGesturingListener> listeners = mOnGesturingListeners; + int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGesturingStarted(this); + } + } + } + } + + // pass the event to handlers + final ArrayList<OnGestureListener> listeners = mOnGestureListeners; + final int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGesture(this, event); + } + } + + return areaToRefresh; + } + + private void touchUp(MotionEvent event, boolean cancel) { + mIsListeningForGestures = false; + + // A gesture wasn't started or was cancelled + if (mCurrentGesture != null) { + // add the stroke to the current gesture + mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer)); + + if (!cancel) { + // pass the event to handlers + final ArrayList<OnGestureListener> listeners = mOnGestureListeners; + int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureEnded(this, event); + } + + clear(mHandleGestureActions && mFadeEnabled, mHandleGestureActions && mIsGesturing, + false); + } else { + cancelGesture(event); + + } + } else { + cancelGesture(event); + } + + mStrokeBuffer.clear(); + mPreviousWasGesturing = mIsGesturing; + mIsGesturing = false; + + final ArrayList<OnGesturingListener> listeners = mOnGesturingListeners; + int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGesturingEnded(this); + } + } + + private void cancelGesture(MotionEvent event) { + // pass the event to handlers + final ArrayList<OnGestureListener> listeners = mOnGestureListeners; + final int count = listeners.size(); + for (int i = 0; i < count; i++) { + listeners.get(i).onGestureCancelled(this, event); + } + + clear(false); + } + + private void fireOnGesturePerformed() { + final ArrayList<OnGesturePerformedListener> actionListeners = mOnGesturePerformedListeners; + final int count = actionListeners.size(); + for (int i = 0; i < count; i++) { + actionListeners.get(i).onGesturePerformed(GestureOverlayView.this, mCurrentGesture); + } + } + + private class FadeOutRunnable implements Runnable { + boolean fireActionPerformed; + boolean resetMultipleStrokes; + + public void run() { + if (mIsFadingOut) { + final long now = AnimationUtils.currentAnimationTimeMillis(); + final long duration = now - mFadingStart; + + if (duration > mFadeDuration) { + if (fireActionPerformed) { + fireOnGesturePerformed(); + } + + mPreviousWasGesturing = false; + mIsFadingOut = false; + mFadingHasStarted = false; + mPath.rewind(); + mCurrentGesture = null; + setPaintAlpha(255); + } else { + mFadingHasStarted = true; + float interpolatedTime = Math.max(0.0f, + Math.min(1.0f, duration / (float) mFadeDuration)); + mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime); + setPaintAlpha((int) (255 * mFadingAlpha)); + postDelayed(this, FADE_ANIMATION_RATE); + } + } else if (resetMultipleStrokes) { + mResetGesture = true; + } else { + fireOnGesturePerformed(); + + mFadingHasStarted = false; + mPath.rewind(); + mCurrentGesture = null; + mPreviousWasGesturing = false; + setPaintAlpha(255); + } + + invalidate(); + } + } + + public static interface OnGesturingListener { + void onGesturingStarted(GestureOverlayView overlay); + + void onGesturingEnded(GestureOverlayView overlay); + } + + public static interface OnGestureListener { + void onGestureStarted(GestureOverlayView overlay, MotionEvent event); + + void onGesture(GestureOverlayView overlay, MotionEvent event); + + void onGestureEnded(GestureOverlayView overlay, MotionEvent event); + + void onGestureCancelled(GestureOverlayView overlay, MotionEvent event); + } + + public static interface OnGesturePerformedListener { + void onGesturePerformed(GestureOverlayView overlay, Gesture gesture); + } +} diff --git a/core/java/android/gesture/GesturePoint.java b/core/java/android/gesture/GesturePoint.java new file mode 100644 index 0000000..3698011 --- /dev/null +++ b/core/java/android/gesture/GesturePoint.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * A timed point of a gesture stroke + */ + +public class GesturePoint { + public final float x; + public final float y; + + public final long timestamp; + + public GesturePoint(float x, float y, long t) { + this.x = x; + this.y = y; + timestamp = t; + } + + static GesturePoint deserialize(DataInputStream in) throws IOException { + // Read X and Y + final float x = in.readFloat(); + final float y = in.readFloat(); + // Read timestamp + final long timeStamp = in.readLong(); + return new GesturePoint(x, y, timeStamp); + } +} diff --git a/core/java/android/gesture/GestureStore.java b/core/java/android/gesture/GestureStore.java new file mode 100644 index 0000000..5f1a445 --- /dev/null +++ b/core/java/android/gesture/GestureStore.java @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.util.Log; +import android.os.SystemClock; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; +import java.util.Map; + +import static android.gesture.GestureConstants.LOG_TAG; + +/** + * GestureLibrary maintains gesture examples and makes predictions on a new + * gesture + */ +// +// File format for GestureStore: +// +// Nb. bytes Java type Description +// ----------------------------------- +// Header +// 2 bytes short File format version number +// 4 bytes int Number of entries +// Entry +// X bytes UTF String Entry name +// 4 bytes int Number of gestures +// Gesture +// 8 bytes long Gesture ID +// 4 bytes int Number of strokes +// Stroke +// 4 bytes int Number of points +// Point +// 4 bytes float X coordinate of the point +// 4 bytes float Y coordinate of the point +// 8 bytes long Time stamp +// +public class GestureStore { + public static final int SEQUENCE_INVARIANT = 1; + // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed + public static final int SEQUENCE_SENSITIVE = 2; + + // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures + public static final int ORIENTATION_INVARIANT = 1; + public static final int ORIENTATION_SENSITIVE = 2; + + private static final short FILE_FORMAT_VERSION = 1; + + private static final boolean PROFILE_LOADING_SAVING = false; + + private int mSequenceType = SEQUENCE_SENSITIVE; + private int mOrientationStyle = ORIENTATION_SENSITIVE; + + private final HashMap<String, ArrayList<Gesture>> mNamedGestures = + new HashMap<String, ArrayList<Gesture>>(); + + private Learner mClassifier; + + private boolean mChanged = false; + + public GestureStore() { + mClassifier = new InstanceLearner(); + } + + /** + * Specify how the gesture library will handle orientation. + * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE + * + * @param style + */ + public void setOrientationStyle(int style) { + mOrientationStyle = style; + } + + public int getOrientationStyle() { + return mOrientationStyle; + } + + /** + * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE + */ + public void setSequenceType(int type) { + mSequenceType = type; + } + + /** + * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE + */ + public int getSequenceType() { + return mSequenceType; + } + + /** + * Get all the gesture entry names in the library + * + * @return a set of strings + */ + public Set<String> getGestureEntries() { + return mNamedGestures.keySet(); + } + + /** + * Recognize a gesture + * + * @param gesture the query + * @return a list of predictions of possible entries for a given gesture + */ + public ArrayList<Prediction> recognize(Gesture gesture) { + Instance instance = Instance.createInstance(mSequenceType, + mOrientationStyle, gesture, null); + return mClassifier.classify(mSequenceType, instance.vector); + } + + /** + * Add a gesture for the entry + * + * @param entryName entry name + * @param gesture + */ + public void addGesture(String entryName, Gesture gesture) { + if (entryName == null || entryName.length() == 0) { + return; + } + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); + if (gestures == null) { + gestures = new ArrayList<Gesture>(); + mNamedGestures.put(entryName, gestures); + } + gestures.add(gesture); + mClassifier.addInstance( + Instance.createInstance(mSequenceType, mOrientationStyle, gesture, entryName)); + mChanged = true; + } + + /** + * Remove a gesture from the library. If there are no more gestures for the + * given entry, the gesture entry will be removed. + * + * @param entryName entry name + * @param gesture + */ + public void removeGesture(String entryName, Gesture gesture) { + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); + if (gestures == null) { + return; + } + + gestures.remove(gesture); + + // if there are no more samples, remove the entry automatically + if (gestures.isEmpty()) { + mNamedGestures.remove(entryName); + } + + mClassifier.removeInstance(gesture.getID()); + + mChanged = true; + } + + /** + * Remove a entry of gestures + * + * @param entryName the entry name + */ + public void removeEntry(String entryName) { + mNamedGestures.remove(entryName); + mClassifier.removeInstances(entryName); + mChanged = true; + } + + /** + * Get all the gestures of an entry + * + * @param entryName + * @return the list of gestures that is under this name + */ + public ArrayList<Gesture> getGestures(String entryName) { + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); + if (gestures != null) { + return new ArrayList<Gesture>(gestures); + } else { + return null; + } + } + + public boolean hasChanged() { + return mChanged; + } + + /** + * Save the gesture library + */ + public void save(OutputStream stream) throws IOException { + save(stream, false); + } + + public void save(OutputStream stream, boolean closeStream) throws IOException { + DataOutputStream out = null; + + try { + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures; + + out = new DataOutputStream((stream instanceof BufferedOutputStream) ? stream : + new BufferedOutputStream(stream, GestureConstants.IO_BUFFER_SIZE)); + // Write version number + out.writeShort(FILE_FORMAT_VERSION); + // Write number of entries + out.writeInt(maps.size()); + + for (Map.Entry<String, ArrayList<Gesture>> entry : maps.entrySet()) { + final String key = entry.getKey(); + final ArrayList<Gesture> examples = entry.getValue(); + final int count = examples.size(); + + // Write entry name + out.writeUTF(key); + // Write number of examples for this entry + out.writeInt(count); + + for (int i = 0; i < count; i++) { + examples.get(i).serialize(out); + } + } + + out.flush(); + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms"); + } + + mChanged = false; + } finally { + if (closeStream) GestureUtilities.closeStream(out); + } + } + + /** + * Load the gesture library + */ + public void load(InputStream stream) throws IOException { + load(stream, false); + } + + public void load(InputStream stream, boolean closeStream) throws IOException { + DataInputStream in = null; + try { + in = new DataInputStream((stream instanceof BufferedInputStream) ? stream : + new BufferedInputStream(stream, GestureConstants.IO_BUFFER_SIZE)); + + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + // Read file format version number + final short versionNumber = in.readShort(); + switch (versionNumber) { + case 1: + readFormatV1(in); + break; + } + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms"); + } + } finally { + if (closeStream) GestureUtilities.closeStream(in); + } + } + + private void readFormatV1(DataInputStream in) throws IOException { + final Learner classifier = mClassifier; + final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures; + namedGestures.clear(); + + // Number of entries in the library + final int entriesCount = in.readInt(); + + for (int i = 0; i < entriesCount; i++) { + // Entry name + final String name = in.readUTF(); + // Number of gestures + final int gestureCount = in.readInt(); + + final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount); + for (int j = 0; j < gestureCount; j++) { + final Gesture gesture = Gesture.deserialize(in); + gestures.add(gesture); + classifier.addInstance( + Instance.createInstance(mSequenceType, mOrientationStyle, gesture, name)); + } + + namedGestures.put(name, gestures); + } + } + + Learner getLearner() { + return mClassifier; + } +} diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java new file mode 100644 index 0000000..598eb85 --- /dev/null +++ b/core/java/android/gesture/GestureStroke.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; + +import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; +import java.util.ArrayList; + +/** + * A gesture stroke started on a touch down and ended on a touch up. + */ +public class GestureStroke { + static final float TOUCH_TOLERANCE = 8; + + public final RectF boundingBox; + + public final float length; + public final float[] points; + + private final long[] timestamps; + private Path mCachedPath; + + /** + * Construct a gesture stroke from a list of gesture points + * + * @param points + */ + public GestureStroke(ArrayList<GesturePoint> points) { + final int count = points.size(); + final float[] tmpPoints = new float[count * 2]; + final long[] times = new long[count]; + + RectF bx = null; + float len = 0; + int index = 0; + + for (int i = 0; i < count; i++) { + final GesturePoint p = points.get(i); + tmpPoints[i * 2] = p.x; + tmpPoints[i * 2 + 1] = p.y; + times[index] = p.timestamp; + + if (bx == null) { + bx = new RectF(); + bx.top = p.y; + bx.left = p.x; + bx.right = p.x; + bx.bottom = p.y; + len = 0; + } else { + len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2) + + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2)); + bx.union(p.x, p.y); + } + index++; + } + + timestamps = times; + this.points = tmpPoints; + boundingBox = bx; + length = len; + } + + /** + * Draw the gesture with a given canvas and paint + * + * @param canvas + */ + void draw(Canvas canvas, Paint paint) { + if (mCachedPath == null) { + makePath(); + } + + canvas.drawPath(mCachedPath, paint); + } + + public Path getPath() { + if (mCachedPath == null) { + makePath(); + } + + return mCachedPath; + } + + private void makePath() { + final float[] localPoints = points; + final int count = localPoints.length; + + Path path = null; + + float mX = 0; + float mY = 0; + + for (int i = 0; i < count; i += 2) { + float x = localPoints[i]; + float y = localPoints[i + 1]; + if (path == null) { + path = new Path(); + path.moveTo(x, y); + mX = x; + mY = y; + } else { + float dx = Math.abs(x - mX); + float dy = Math.abs(y - mY); + if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { + path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); + mX = x; + mY = y; + } + } + } + + mCachedPath = path; + } + + /** + * Convert the stroke to a Path based on the number of points + * + * @param width the width of the bounding box of the target path + * @param height the height of the bounding box of the target path + * @param numSample the number of points needed + * + * @return the path + */ + public Path toPath(float width, float height, int numSample) { + final float[] pts = GestureUtilities.temporalSampling(this, numSample); + final RectF rect = boundingBox; + + GestureUtilities.translate(pts, -rect.left, -rect.top); + + float sx = width / rect.width(); + float sy = height / rect.height(); + float scale = sx > sy ? sy : sx; + GestureUtilities.scale(pts, scale, scale); + + float mX = 0; + float mY = 0; + + Path path = null; + + final int count = pts.length; + + for (int i = 0; i < count; i += 2) { + float x = pts[i]; + float y = pts[i + 1]; + if (path == null) { + path = new Path(); + path.moveTo(x, y); + mX = x; + mY = y; + } else { + float dx = Math.abs(x - mX); + float dy = Math.abs(y - mY); + if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { + path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); + mX = x; + mY = y; + } + } + } + + return path; + } + + void serialize(DataOutputStream out) throws IOException { + final float[] pts = points; + final long[] times = timestamps; + final int count = points.length; + + // Write number of points + out.writeInt(count / 2); + + for (int i = 0; i < count; i += 2) { + // Write X + out.writeFloat(pts[i]); + // Write Y + out.writeFloat(pts[i + 1]); + // Write timestamp + out.writeLong(times[i / 2]); + } + } + + static GestureStroke deserialize(DataInputStream in) throws IOException { + // Number of points + final int count = in.readInt(); + + final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(count); + for (int i = 0; i < count; i++) { + points.add(GesturePoint.deserialize(in)); + } + + return new GestureStroke(points); + } + + /** + * Invalidate the cached path that is used to render the stroke + */ + public void clearPath() { + if (mCachedPath != null) mCachedPath.rewind(); + } + + /** + * Compute an oriented bounding box of the stroke + * @return OrientedBoundingBox + */ + public OrientedBoundingBox computeOrientedBoundingBox() { + return GestureUtilities.computeOrientedBoundingBox(points); + } +} diff --git a/core/java/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java new file mode 100755 index 0000000..40d7029 --- /dev/null +++ b/core/java/android/gesture/GestureUtilities.java @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.graphics.RectF; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Arrays; +import java.io.Closeable; +import java.io.IOException; + +import static android.gesture.GestureConstants.*; + +final class GestureUtilities { + private static final int TEMPORAL_SAMPLING_RATE = 16; + + private GestureUtilities() { + } + + /** + * Closes the specified stream. + * + * @param stream The stream to close. + */ + static void closeStream(Closeable stream) { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + Log.e(LOG_TAG, "Could not close stream", e); + } + } + } + + static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension) { + final float targetPatchSize = sampleMatrixDimension - 1; // edge inclusive + float[] sample = new float[sampleMatrixDimension * sampleMatrixDimension]; + Arrays.fill(sample, 0); + + RectF rect = gesture.getBoundingBox(); + float sx = targetPatchSize / rect.width(); + float sy = targetPatchSize / rect.height(); + float scale = sx < sy ? sx : sy; + + float preDx = -rect.centerX(); + float preDy = -rect.centerY(); + float postDx = targetPatchSize / 2; + float postDy = targetPatchSize / 2; + + final ArrayList<GestureStroke> strokes = gesture.getStrokes(); + final int count = strokes.size(); + + int size; + float xpos; + float ypos; + + for (int index = 0; index < count; index++) { + final GestureStroke stroke = strokes.get(index); + float[] strokepoints = stroke.points; + size = strokepoints.length; + + final float[] pts = new float[size]; + + for (int i = 0; i < size; i += 2) { + pts[i] = (strokepoints[i] + preDx) * scale + postDx; + pts[i + 1] = (strokepoints[i + 1] + preDy) * scale + postDy; + } + + float segmentEndX = -1; + float segmentEndY = -1; + + for (int i = 0; i < size; i += 2) { + + float segmentStartX = pts[i] < 0 ? 0 : pts[i]; + float segmentStartY = pts[i + 1] < 0 ? 0 : pts[i + 1]; + + if (segmentStartX > targetPatchSize) { + segmentStartX = targetPatchSize; + } + + if (segmentStartY > targetPatchSize) { + segmentStartY = targetPatchSize; + } + + plot(segmentStartX, segmentStartY, sample, sampleMatrixDimension); + + if (segmentEndX != -1) { + // evaluate horizontally + if (segmentEndX > segmentStartX) { + xpos = (float) Math.ceil(segmentStartX); + float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); + while (xpos < segmentEndX) { + ypos = slope * (xpos - segmentStartX) + segmentStartY; + plot(xpos, ypos, sample, sampleMatrixDimension); + xpos++; + } + } else if (segmentEndX < segmentStartX){ + xpos = (float) Math.ceil(segmentEndX); + float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); + while (xpos < segmentStartX) { + ypos = slope * (xpos - segmentStartX) + segmentStartY; + plot(xpos, ypos, sample, sampleMatrixDimension); + xpos++; + } + } + + // evaluating vertically + if (segmentEndY > segmentStartY) { + ypos = (float) Math.ceil(segmentStartY); + float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); + while (ypos < segmentEndY) { + xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; + plot(xpos, ypos, sample, sampleMatrixDimension); + ypos++; + } + } else if (segmentEndY < segmentStartY) { + ypos = (float) Math.ceil(segmentEndY); + float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); + while (ypos < segmentStartY) { + xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; + plot(xpos, ypos, sample, sampleMatrixDimension); + ypos++; + } + } + } + + segmentEndX = segmentStartX; + segmentEndY = segmentStartY; + } + } + + + return sample; + } + + private static void plot(float x, float y, float[] sample, int sampleSize) { + x = x < 0 ? 0 : x; + y = y < 0 ? 0 : y; + int xFloor = (int) Math.floor(x); + int xCeiling = (int) Math.ceil(x); + int yFloor = (int) Math.floor(y); + int yCeiling = (int) Math.ceil(y); + + // if it's an integer + if (x == xFloor && y == yFloor) { + int index = yCeiling * sampleSize + xCeiling; + if (sample[index] < 1){ + sample[index] = 1; + } + } else { + double topLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yFloor - y, 2)); + double topRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yFloor - y, 2)); + double btmLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yCeiling - y, 2)); + double btmRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yCeiling - y, 2)); + double sum = topLeft + topRight + btmLeft + btmRight; + + double value = topLeft / sum; + int index = yFloor * sampleSize + xFloor; + if (value > sample[index]){ + sample[index] = (float) value; + } + + value = topRight / sum; + index = yFloor * sampleSize + xCeiling; + if (value > sample[index]){ + sample[index] = (float) value; + } + + value = btmLeft / sum; + index = yCeiling * sampleSize + xFloor; + if (value > sample[index]){ + sample[index] = (float) value; + } + + value = btmRight / sum; + index = yCeiling * sampleSize + xCeiling; + if (value > sample[index]){ + sample[index] = (float) value; + } + } + } + + /** + * Featurize a stroke into a vector of a given number of elements + * + * @param stroke + * @param sampleSize + * @return a float array + */ + static float[] temporalSampling(GestureStroke stroke, int sampleSize) { + final float increment = stroke.length / (sampleSize - 1); + int vectorLength = sampleSize * 2; + float[] vector = new float[vectorLength]; + float distanceSoFar = 0; + float[] pts = stroke.points; + float lstPointX = pts[0]; + float lstPointY = pts[1]; + int index = 0; + float currentPointX = Float.MIN_VALUE; + float currentPointY = Float.MIN_VALUE; + vector[index] = lstPointX; + index++; + vector[index] = lstPointY; + index++; + int i = 0; + int count = pts.length / 2; + while (i < count) { + if (currentPointX == Float.MIN_VALUE) { + i++; + if (i >= count) { + break; + } + currentPointX = pts[i * 2]; + currentPointY = pts[i * 2 + 1]; + } + float deltaX = currentPointX - lstPointX; + float deltaY = currentPointY - lstPointY; + float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY); + if (distanceSoFar + distance >= increment) { + float ratio = (increment - distanceSoFar) / distance; + float nx = lstPointX + ratio * deltaX; + float ny = lstPointY + ratio * deltaY; + vector[index] = nx; + index++; + vector[index] = ny; + index++; + lstPointX = nx; + lstPointY = ny; + distanceSoFar = 0; + } else { + lstPointX = currentPointX; + lstPointY = currentPointY; + currentPointX = Float.MIN_VALUE; + currentPointY = Float.MIN_VALUE; + distanceSoFar += distance; + } + } + + for (i = index; i < vectorLength; i += 2) { + vector[i] = lstPointX; + vector[i + 1] = lstPointY; + } + return vector; + } + + /** + * Calculate the centroid + * + * @param points + * @return the centroid + */ + static float[] computeCentroid(float[] points) { + float centerX = 0; + float centerY = 0; + int count = points.length; + for (int i = 0; i < count; i++) { + centerX += points[i]; + i++; + centerY += points[i]; + } + float[] center = new float[2]; + center[0] = 2 * centerX / count; + center[1] = 2 * centerY / count; + + return center; + } + + /** + * calculate the variance-covariance matrix, treat each point as a sample + * + * @param points + * @return the covariance matrix + */ + private static double[][] computeCoVariance(float[] points) { + double[][] array = new double[2][2]; + array[0][0] = 0; + array[0][1] = 0; + array[1][0] = 0; + array[1][1] = 0; + int count = points.length; + for (int i = 0; i < count; i++) { + float x = points[i]; + i++; + float y = points[i]; + array[0][0] += x * x; + array[0][1] += x * y; + array[1][0] = array[0][1]; + array[1][1] += y * y; + } + array[0][0] /= (count / 2); + array[0][1] /= (count / 2); + array[1][0] /= (count / 2); + array[1][1] /= (count / 2); + + return array; + } + + static float computeTotalLength(float[] points) { + float sum = 0; + int count = points.length - 4; + for (int i = 0; i < count; i += 2) { + float dx = points[i + 2] - points[i]; + float dy = points[i + 3] - points[i + 1]; + sum += Math.sqrt(dx * dx + dy * dy); + } + return sum; + } + + static double computeStraightness(float[] points) { + float totalLen = computeTotalLength(points); + float dx = points[2] - points[0]; + float dy = points[3] - points[1]; + return Math.sqrt(dx * dx + dy * dy) / totalLen; + } + + static double computeStraightness(float[] points, float totalLen) { + float dx = points[2] - points[0]; + float dy = points[3] - points[1]; + return Math.sqrt(dx * dx + dy * dy) / totalLen; + } + + /** + * Calculate the squared Euclidean distance between two vectors + * + * @param vector1 + * @param vector2 + * @return the distance + */ + static double squaredEuclideanDistance(float[] vector1, float[] vector2) { + double squaredDistance = 0; + int size = vector1.length; + for (int i = 0; i < size; i++) { + float difference = vector1[i] - vector2[i]; + squaredDistance += difference * difference; + } + return squaredDistance / size; + } + + /** + * Calculate the cosine distance between two instances + * + * @param vector1 + * @param vector2 + * @return the distance between 0 and Math.PI + */ + static double cosineDistance(float[] vector1, float[] vector2) { + float sum = 0; + int len = vector1.length; + for (int i = 0; i < len; i++) { + sum += vector1[i] * vector2[i]; + } + return Math.acos(sum); + } + + static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) { + GestureStroke stroke = new GestureStroke(pts); + float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE); + return computeOrientedBoundingBox(points); + } + + static OrientedBoundingBox computeOrientedBoundingBox(float[] points) { + float[] meanVector = computeCentroid(points); + return computeOrientedBoundingBox(points, meanVector); + } + + static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) { + translate(points, -centroid[0], -centroid[1]); + + double[][] array = computeCoVariance(points); + double[] targetVector = computeOrientation(array); + + float angle; + if (targetVector[0] == 0 && targetVector[1] == 0) { + angle = (float) -Math.PI/2; + } else { // -PI<alpha<PI + angle = (float) Math.atan2(targetVector[1], targetVector[0]); + rotate(points, -angle); + } + + float minx = Float.MAX_VALUE; + float miny = Float.MAX_VALUE; + float maxx = Float.MIN_VALUE; + float maxy = Float.MIN_VALUE; + int count = points.length; + for (int i = 0; i < count; i++) { + if (points[i] < minx) { + minx = points[i]; + } + if (points[i] > maxx) { + maxx = points[i]; + } + i++; + if (points[i] < miny) { + miny = points[i]; + } + if (points[i] > maxy) { + maxy = points[i]; + } + } + + return new OrientedBoundingBox((float) (angle * 180 / Math.PI), centroid[0], centroid[1], maxx - minx, maxy - miny); + } + + private static double[] computeOrientation(double[][] covarianceMatrix) { + double[] targetVector = new double[2]; + if (covarianceMatrix[0][1] == 0 || covarianceMatrix[1][0] == 0) { + targetVector[0] = 1; + targetVector[1] = 0; + } + + double a = -covarianceMatrix[0][0] - covarianceMatrix[1][1]; + double b = covarianceMatrix[0][0] * covarianceMatrix[1][1] - covarianceMatrix[0][1] + * covarianceMatrix[1][0]; + double value = a / 2; + double rightside = Math.sqrt(Math.pow(value, 2) - b); + double lambda1 = -value + rightside; + double lambda2 = -value - rightside; + if (lambda1 == lambda2) { + targetVector[0] = 0; + targetVector[1] = 0; + } else { + double lambda = lambda1 > lambda2 ? lambda1 : lambda2; + targetVector[0] = 1; + targetVector[1] = (lambda - covarianceMatrix[0][0]) / covarianceMatrix[0][1]; + } + return targetVector; + } + + + static float[] rotate(float[] points, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + int size = points.length; + for (int i = 0; i < size; i += 2) { + float x = (float) (points[i] * cos - points[i + 1] * sin); + float y = (float) (points[i] * sin + points[i + 1] * cos); + points[i] = x; + points[i + 1] = y; + } + return points; + } + + static float[] translate(float[] points, float dx, float dy) { + int size = points.length; + for (int i = 0; i < size; i += 2) { + points[i] += dx; + points[i + 1] += dy; + } + return points; + } + + static float[] scale(float[] points, float sx, float sy) { + int size = points.length; + for (int i = 0; i < size; i += 2) { + points[i] *= sx; + points[i + 1] *= sy; + } + return points; + } +} diff --git a/core/java/android/gesture/Instance.java b/core/java/android/gesture/Instance.java new file mode 100755 index 0000000..ef208ac --- /dev/null +++ b/core/java/android/gesture/Instance.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + + +/** + * An instance represents a sample if the label is available or a query if the + * label is null. + */ +class Instance { + private static final int SEQUENCE_SAMPLE_SIZE = 16; + + private static final int PATCH_SAMPLE_SIZE = 16; + + private final static float[] ORIENTATIONS = { + 0, (float) (Math.PI / 4), (float) (Math.PI / 2), (float) (Math.PI * 3 / 4), + (float) Math.PI, -0, (float) (-Math.PI / 4), (float) (-Math.PI / 2), + (float) (-Math.PI * 3 / 4), (float) -Math.PI + }; + + // the feature vector + final float[] vector; + + // the label can be null + final String label; + + // the id of the instance + final long id; + + private Instance(long id, float[] sample, String sampleName) { + this.id = id; + vector = sample; + label = sampleName; + } + + private void normalize() { + float[] sample = vector; + float sum = 0; + + int size = sample.length; + for (int i = 0; i < size; i++) { + sum += sample[i] * sample[i]; + } + + float magnitude = (float)Math.sqrt(sum); + for (int i = 0; i < size; i++) { + sample[i] /= magnitude; + } + } + + /** + * create a learning instance for a single stroke gesture + * + * @param gesture + * @param label + * @return the instance + */ + static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) { + float[] pts; + Instance instance; + if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) { + pts = temporalSampler(orientationType, gesture); + instance = new Instance(gesture.getID(), pts, label); + instance.normalize(); + } else { + pts = spatialSampler(gesture); + instance = new Instance(gesture.getID(), pts, label); + } + return instance; + } + + private static float[] spatialSampler(Gesture gesture) { + return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE); + } + + private static float[] temporalSampler(int orientationType, Gesture gesture) { + float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0), + SEQUENCE_SAMPLE_SIZE); + float[] center = GestureUtilities.computeCentroid(pts); + float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]); + + float adjustment = -orientation; + if (orientationType == GestureStore.ORIENTATION_SENSITIVE) { + int count = ORIENTATIONS.length; + for (int i = 0; i < count; i++) { + float delta = ORIENTATIONS[i] - orientation; + if (Math.abs(delta) < Math.abs(adjustment)) { + adjustment = delta; + } + } + } + + GestureUtilities.translate(pts, -center[0], -center[1]); + GestureUtilities.rotate(pts, adjustment); + + return pts; + } + +} diff --git a/core/java/android/gesture/InstanceLearner.java b/core/java/android/gesture/InstanceLearner.java new file mode 100644 index 0000000..b93b76f --- /dev/null +++ b/core/java/android/gesture/InstanceLearner.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.TreeMap; + +/** + * An implementation of an instance-based learner + */ + +class InstanceLearner extends Learner { + private static final Comparator<Prediction> sComparator = new Comparator<Prediction>() { + public int compare(Prediction object1, Prediction object2) { + double score1 = object1.score; + double score2 = object2.score; + if (score1 > score2) { + return -1; + } else if (score1 < score2) { + return 1; + } else { + return 0; + } + } + }; + + @Override + ArrayList<Prediction> classify(int sequenceType, float[] vector) { + ArrayList<Prediction> predictions = new ArrayList<Prediction>(); + ArrayList<Instance> instances = getInstances(); + int count = instances.size(); + TreeMap<String, Double> label2score = new TreeMap<String, Double>(); + for (int i = 0; i < count; i++) { + Instance sample = instances.get(i); + if (sample.vector.length != vector.length) { + continue; + } + double distance; + if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) { + distance = GestureUtilities.cosineDistance(sample.vector, vector); + } else { + distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector); + } + double weight; + if (distance == 0) { + weight = Double.MAX_VALUE; + } else { + weight = 1 / distance; + } + Double score = label2score.get(sample.label); + if (score == null || weight > score) { + label2score.put(sample.label, weight); + } + } + +// double sum = 0; + for (String name : label2score.keySet()) { + double score = label2score.get(name); +// sum += score; + predictions.add(new Prediction(name, score)); + } + + // normalize +// for (Prediction prediction : predictions) { +// prediction.score /= sum; +// } + + Collections.sort(predictions, sComparator); + + return predictions; + } +} diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java new file mode 100755 index 0000000..feacde5 --- /dev/null +++ b/core/java/android/gesture/Learner.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import java.util.ArrayList; + +/** + * The abstract class of a gesture learner + */ +abstract class Learner { + private final ArrayList<Instance> mInstances = new ArrayList<Instance>(); + + /** + * Add an instance to the learner + * + * @param instance + */ + void addInstance(Instance instance) { + mInstances.add(instance); + } + + /** + * Retrieve all the instances + * + * @return instances + */ + ArrayList<Instance> getInstances() { + return mInstances; + } + + /** + * Remove an instance based on its id + * + * @param id + */ + void removeInstance(long id) { + ArrayList<Instance> instances = mInstances; + int count = instances.size(); + for (int i = 0; i < count; i++) { + Instance instance = instances.get(i); + if (id == instance.id) { + instances.remove(instance); + return; + } + } + } + + /** + * Remove all the instances of a category + * + * @param name the category name + */ + void removeInstances(String name) { + final ArrayList<Instance> toDelete = new ArrayList<Instance>(); + final ArrayList<Instance> instances = mInstances; + final int count = instances.size(); + + for (int i = 0; i < count; i++) { + final Instance instance = instances.get(i); + // the label can be null, as specified in Instance + if ((instance.label == null && name == null) || instance.label.equals(name)) { + toDelete.add(instance); + } + } + instances.removeAll(toDelete); + } + + abstract ArrayList<Prediction> classify(int gestureType, float[] vector); +} diff --git a/core/java/android/gesture/OrientedBoundingBox.java b/core/java/android/gesture/OrientedBoundingBox.java new file mode 100644 index 0000000..f1335ee --- /dev/null +++ b/core/java/android/gesture/OrientedBoundingBox.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +import android.graphics.Matrix; +import android.graphics.Path; + +/** + * An oriented bounding box + */ +public class OrientedBoundingBox { + public final float squareness; + + public final float width; + public final float height; + + public final float orientation; + + public final float centerX; + public final float centerY; + + OrientedBoundingBox(float angle, float cx, float cy, float w, float h) { + orientation = angle; + width = w; + height = h; + centerX = cx; + centerY = cy; + float ratio = w / h; + if (ratio > 1) { + squareness = 1 / ratio; + } else { + squareness = ratio; + } + } + + /** + * Currently used for debugging purpose only. + * + * @hide + */ + public Path toPath() { + Path path = new Path(); + float[] point = new float[2]; + point[0] = -width / 2; + point[1] = height / 2; + Matrix matrix = new Matrix(); + matrix.setRotate(orientation); + matrix.postTranslate(centerX, centerY); + matrix.mapPoints(point); + path.moveTo(point[0], point[1]); + + point[0] = -width / 2; + point[1] = -height / 2; + matrix.mapPoints(point); + path.lineTo(point[0], point[1]); + + point[0] = width / 2; + point[1] = -height / 2; + matrix.mapPoints(point); + path.lineTo(point[0], point[1]); + + point[0] = width / 2; + point[1] = height / 2; + matrix.mapPoints(point); + path.lineTo(point[0], point[1]); + + path.close(); + + return path; + } +} diff --git a/core/java/android/gesture/Prediction.java b/core/java/android/gesture/Prediction.java new file mode 100755 index 0000000..ce6ad57 --- /dev/null +++ b/core/java/android/gesture/Prediction.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gesture; + +public class Prediction { + public final String name; + + public double score; + + Prediction(String label, double predictionScore) { + name = label; + score = predictionScore; + } + + @Override + public String toString() { + return name; + } +} diff --git a/core/java/android/gesture/package.html b/core/java/android/gesture/package.html new file mode 100644 index 0000000..a54a017 --- /dev/null +++ b/core/java/android/gesture/package.html @@ -0,0 +1,5 @@ +<HTML> +<BODY> +@hide +</BODY> +</HTML> diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index ca579b6..091bc17 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -39,13 +39,16 @@ import android.os.Message; public class Camera { private static final String TAG = "Camera"; - // These match the enum in libs/android_runtime/android_hardware_Camera.cpp - private static final int SHUTTER_CALLBACK = 0; - private static final int RAW_PICTURE_CALLBACK = 1; - private static final int JPEG_PICTURE_CALLBACK = 2; - private static final int PREVIEW_CALLBACK = 3; - private static final int AUTOFOCUS_CALLBACK = 4; - private static final int ERROR_CALLBACK = 5; + // These match the enums in frameworks/base/include/ui/Camera.h + private static final int CAMERA_MSG_ERROR = 0; + private static final int CAMERA_MSG_SHUTTER = 1; + private static final int CAMERA_MSG_FOCUS = 2; + private static final int CAMERA_MSG_ZOOM = 3; + private static final int CAMERA_MSG_PREVIEW_FRAME = 4; + private static final int CAMERA_MSG_VIDEO_FRAME = 5; + private static final int CAMERA_MSG_POSTVIEW_FRAME = 6; + private static final int CAMERA_MSG_RAW_IMAGE = 7; + private static final int CAMERA_MSG_COMPRESSED_IMAGE = 8; private int mNativeContext; // accessed by native methods private EventHandler mEventHandler; @@ -152,7 +155,11 @@ public class Camera { * @throws IOException if the method fails. */ public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { - setPreviewDisplay(holder.getSurface()); + if (holder != null) { + setPreviewDisplay(holder.getSurface()); + } else { + setPreviewDisplay((Surface)null); + } } private native final void setPreviewDisplay(Surface surface); @@ -231,22 +238,23 @@ public class Camera { @Override public void handleMessage(Message msg) { switch(msg.what) { - case SHUTTER_CALLBACK: + case CAMERA_MSG_SHUTTER: if (mShutterCallback != null) { mShutterCallback.onShutter(); } return; - case RAW_PICTURE_CALLBACK: + + case CAMERA_MSG_RAW_IMAGE: if (mRawImageCallback != null) mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera); return; - case JPEG_PICTURE_CALLBACK: + case CAMERA_MSG_COMPRESSED_IMAGE: if (mJpegCallback != null) mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); return; - case PREVIEW_CALLBACK: + case CAMERA_MSG_PREVIEW_FRAME: if (mPreviewCallback != null) { mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera); if (mOneShot) { @@ -255,12 +263,12 @@ public class Camera { } return; - case AUTOFOCUS_CALLBACK: + case CAMERA_MSG_FOCUS: if (mAutoFocusCallback != null) mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera); return; - case ERROR_CALLBACK: + case CAMERA_MSG_ERROR : Log.e(TAG, "Error " + msg.arg1); if (mErrorCallback != null) mErrorCallback.onError(msg.arg1, mCamera); @@ -363,7 +371,7 @@ public class Camera { } private native final void native_takePicture(); - // These match the enum in libs/android_runtime/android_hardware_Camera.cpp + // These match the enum in include/ui/Camera.h /** Unspecified camerar error. @see #ErrorCallback */ public static final int CAMERA_ERROR_UNKNOWN = 1; /** Media server died. In this case, the application must release the diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl index 04af2ae..67180bd 100644 --- a/core/java/android/hardware/ISensorService.aidl +++ b/core/java/android/hardware/ISensorService.aidl @@ -17,13 +17,13 @@ package android.hardware; -import android.os.ParcelFileDescriptor; +import android.os.Bundle; /** * {@hide} */ interface ISensorService { - ParcelFileDescriptor getDataChanel(); + Bundle getDataChannel(); boolean enableSensor(IBinder listener, String name, int sensor, int enable); } diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 67df23b..bf945ec 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -18,7 +18,9 @@ package android.hardware; import android.content.Context; import android.os.Binder; +import android.os.Bundle; import android.os.Looper; +import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; @@ -280,8 +282,8 @@ public class SensorManager void startLocked(ISensorService service) { try { if (mThread == null) { - ParcelFileDescriptor fd = service.getDataChanel(); - mThread = new Thread(new SensorThreadRunnable(fd), + Bundle dataChannel = service.getDataChannel(); + mThread = new Thread(new SensorThreadRunnable(dataChannel), SensorThread.class.getName()); mThread.start(); } @@ -291,10 +293,52 @@ public class SensorManager } private class SensorThreadRunnable implements Runnable { - private ParcelFileDescriptor mSensorDataFd; - SensorThreadRunnable(ParcelFileDescriptor fd) { - mSensorDataFd = fd; + private Bundle mDataChannel; + SensorThreadRunnable(Bundle dataChannel) { + mDataChannel = dataChannel; } + + private boolean open() { + if (mDataChannel == null) { + Log.e(TAG, "mDataChannel == NULL, exiting"); + synchronized (sListeners) { + mThread = null; + } + return false; + } + + // this thread is guaranteed to be unique + Parcelable[] pfds = mDataChannel.getParcelableArray("fds"); + FileDescriptor[] fds; + if (pfds != null) { + int length = pfds.length; + fds = new FileDescriptor[length]; + for (int i = 0; i < length; i++) { + ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i]; + fds[i] = pfd.getFileDescriptor(); + } + } else { + fds = null; + } + int[] ints = mDataChannel.getIntArray("ints"); + sensors_data_open(fds, ints); + if (pfds != null) { + try { + // close our copies of the file descriptors, + // since we are just passing these to the JNI code and not using them here. + for (int i = pfds.length - 1; i >= 0; i--) { + ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i]; + pfd.close(); + } + } catch (IOException e) { + // *shrug* + Log.e(TAG, "IOException: ", e); + } + } + mDataChannel = null; + return true; + } + public void run() { //Log.d(TAG, "entering main sensor thread"); final float[] values = new float[3]; @@ -302,23 +346,9 @@ public class SensorManager final long timestamp[] = new long[1]; Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); - if (mSensorDataFd == null) { - Log.e(TAG, "mSensorDataFd == NULL, exiting"); - synchronized (sListeners) { - mThread = null; - } + if (!open()) { return; } - // this thread is guaranteed to be unique - sensors_data_open(mSensorDataFd.getFileDescriptor()); - try { - mSensorDataFd.close(); - } catch (IOException e) { - // *shrug* - Log.e(TAG, "IOException: ", e); - } - mSensorDataFd = null; - while (true) { // wait for an event @@ -1469,7 +1499,7 @@ public class SensorManager // Used within this module from outside SensorManager, don't make private static native int sensors_data_init(); static native int sensors_data_uninit(); - static native int sensors_data_open(FileDescriptor fd); + static native int sensors_data_open(FileDescriptor[] fds, int[] ints); static native int sensors_data_close(); static native int sensors_data_poll(float[] values, int[] status, long[] timestamp); } diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java index c4ee5b0..6a97951 100644 --- a/core/java/android/net/http/RequestHandle.java +++ b/core/java/android/net/http/RequestHandle.java @@ -159,11 +159,11 @@ public class RequestHandle { e.printStackTrace(); } - // update the "cookie" header based on the redirected url - mHeaders.remove("cookie"); + // update the "Cookie" header based on the redirected url + mHeaders.remove("Cookie"); String cookie = CookieManager.getInstance().getCookie(mUri); if (cookie != null && cookie.length() > 0) { - mHeaders.put("cookie", cookie); + mHeaders.put("Cookie", cookie); } if ((statusCode == 302 || statusCode == 303) && mMethod.equals("POST")) { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 6c13582..abfb274 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -127,12 +127,12 @@ import java.util.concurrent.atomic.AtomicInteger; public abstract class AsyncTask<Params, Progress, Result> { private static final String LOG_TAG = "AsyncTask"; - private static final int CORE_POOL_SIZE = 1; - private static final int MAXIMUM_POOL_SIZE = 10; + private static final int CORE_POOL_SIZE = 5; + private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 10; private static final BlockingQueue<Runnable> sWorkQueue = - new LinkedBlockingQueue<Runnable>(MAXIMUM_POOL_SIZE); + new LinkedBlockingQueue<Runnable>(10); private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 8a0fd58..528def5 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -69,6 +69,20 @@ public abstract class BatteryStats implements Parcelable { public static final int WIFI_MULTICAST_ENABLED = 7; /** + * A constant indicating an audio turn on timer + * + * {@hide} + */ + public static final int AUDIO_TURNED_ON = 7; + + /** + * A constant indicating a video turn on timer + * + * {@hide} + */ + public static final int VIDEO_TURNED_ON = 8; + + /** * Include all of the data in the stats, including previously saved data. */ public static final int STATS_TOTAL = 0; @@ -164,7 +178,7 @@ public abstract class BatteryStats implements Parcelable { * @return a time in microseconds */ public abstract long getTotalTimeLocked(long batteryRealtime, int which); - + /** * Temporary for debugging. */ @@ -234,11 +248,17 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteScanWifiLockReleasedLocked(); public abstract void noteWifiMulticastEnabledLocked(); public abstract void noteWifiMulticastDisabledLocked(); + public abstract void noteAudioTurnedOnLocked(); + public abstract void noteAudioTurnedOffLocked(); + public abstract void noteVideoTurnedOnLocked(); + public abstract void noteVideoTurnedOffLocked(); public abstract long getWifiTurnedOnTime(long batteryRealtime, int which); public abstract long getFullWifiLockTime(long batteryRealtime, int which); public abstract long getScanWifiLockTime(long batteryRealtime, int which); public abstract long getWifiMulticastTime(long batteryRealtime, int which); + public abstract long getAudioTurnedOnTime(long batteryRealtime, int which); + public abstract long getVideoTurnedOnTime(long batteryRealtime, int which); /** * Note that these must match the constants in android.os.LocalPowerManager. @@ -287,6 +307,13 @@ public abstract class BatteryStats implements Parcelable { * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. */ public abstract int getStarts(int which); + + /** + * Returns the cpu time spent in microseconds while the process was in the foreground. + * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED + * @return foreground cpu time in microseconds + */ + public abstract long getForegroundTime(int which); } /** @@ -344,7 +371,7 @@ public abstract class BatteryStats implements Parcelable { public abstract int getStartCount(); /** - * Returns the time in milliseconds that the screen has been on while the device was + * Returns the time in microseconds that the screen has been on while the device was * running on battery. * * {@hide} @@ -364,7 +391,7 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5; /** - * Returns the time in milliseconds that the screen has been on with + * Returns the time in microseconds that the screen has been on with * the given brightness * * {@hide} @@ -375,7 +402,7 @@ public abstract class BatteryStats implements Parcelable { public abstract int getInputEventCount(int which); /** - * Returns the time in milliseconds that the phone has been on while the device was + * Returns the time in microseconds that the phone has been on while the device was * running on battery. * * {@hide} @@ -395,7 +422,7 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_SIGNAL_STRENGTH_BINS = 5; /** - * Returns the time in milliseconds that the phone has been running with + * Returns the time in microseconds that the phone has been running with * the given signal strength. * * {@hide} @@ -423,7 +450,7 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_DATA_CONNECTION_TYPES = 5; /** - * Returns the time in milliseconds that the phone has been running with + * Returns the time in microseconds that the phone has been running with * the given data connection. * * {@hide} @@ -440,7 +467,7 @@ public abstract class BatteryStats implements Parcelable { public abstract int getPhoneDataConnectionCount(int dataType, int which); /** - * Returns the time in milliseconds that wifi has been on while the device was + * Returns the time in microseconds that wifi has been on while the device was * running on battery. * * {@hide} @@ -448,7 +475,7 @@ public abstract class BatteryStats implements Parcelable { public abstract long getWifiOnTime(long batteryRealtime, int which); /** - * Returns the time in milliseconds that wifi has been on and the driver has + * Returns the time in microseconds that wifi has been on and the driver has * been in the running state while the device was running on battery. * * {@hide} @@ -456,7 +483,7 @@ public abstract class BatteryStats implements Parcelable { public abstract long getWifiRunningTime(long batteryRealtime, int which); /** - * Returns the time in milliseconds that bluetooth has been on while the device was + * Returns the time in microseconds that bluetooth has been on while the device was * running on battery. * * {@hide} diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 5487c54..830b0bd 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -38,6 +38,12 @@ public class Build { /** The name of the underlying board, like "goldfish". */ public static final String BOARD = getString("ro.product.board"); + /** The name of the instruction set (CPU type + ABI convention) of native code. */ + public static final String CPU_ABI = getString("ro.product.cpu.abi"); + + /** The manufacturer of the product/hardware. */ + public static final String MANUFACTURER = getString("ro.product.manufacturer"); + /** The brand (e.g., carrier) the software is customized for, if any. */ public static final String BRAND = getString("ro.product.brand"); @@ -87,6 +93,12 @@ public class Build { */ public static class VERSION_CODES { /** + * Magic version number for a current development build, which has + * not yet turned into an official release. + */ + public static final int CUR_DEVELOPMENT = 10000; + + /** * October 2008: The original, first, version of Android. Yay! */ public static final int BASE = 1; @@ -98,6 +110,19 @@ public class Build { * May 2009: Android 1.5. */ public static final int CUPCAKE = 3; + /** + * Current work on "Donut" development branch. + * + * <p>Applications targeting this or a later release will get these + * new changes in behavior:</p> + * <ul> + * <li> They must explicitly request the + * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission to be + * able to modify the contents of the SD card. (Apps targeting + * earlier versions will always request the permission.) + * </ul> + */ + public static final int DONUT = CUR_DEVELOPMENT; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index b669fa2..a91655f 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -78,6 +78,10 @@ public final class Bundle implements Parcelable, Cloneable { readFromParcel(parcelledData); } + /* package */ Bundle(Parcel parcelledData, int length) { + readFromParcelInner(parcelledData, length); + } + /** * Constructs a new, empty Bundle that uses a specific ClassLoader for * instantiating Parcelable and Serializable objects. @@ -155,13 +159,14 @@ public final class Bundle implements Parcelable, Cloneable { return; } - mParcelledData.setDataPosition(0); - Bundle b = mParcelledData.readBundleUnpacked(mClassLoader); - mMap = b.mMap; - - mHasFds = mParcelledData.hasFileDescriptors(); - mFdsKnown = true; - + int N = mParcelledData.readInt(); + if (N < 0) { + return; + } + if (mMap == null) { + mMap = new HashMap<String, Object>(); + } + mParcelledData.readMapInternal(mMap, N, mClassLoader); mParcelledData.recycle(); mParcelledData = null; } @@ -1427,7 +1432,25 @@ public final class Bundle implements Parcelable, Cloneable { * @param parcel The parcel to copy this bundle to. */ public void writeToParcel(Parcel parcel, int flags) { - parcel.writeBundle(this); + if (mParcelledData != null) { + int length = mParcelledData.dataSize(); + parcel.writeInt(length); + parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' + parcel.appendFrom(mParcelledData, 0, length); + } else { + parcel.writeInt(-1); // dummy, will hold length + parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' + + int oldPos = parcel.dataPosition(); + parcel.writeMapInternal(mMap); + int newPos = parcel.dataPosition(); + + // Backpatch length + parcel.setDataPosition(oldPos - 8); + int length = newPos - oldPos; + parcel.writeInt(length); + parcel.setDataPosition(newPos); + } } /** @@ -1436,8 +1459,33 @@ public final class Bundle implements Parcelable, Cloneable { * @param parcel The parcel to overwrite this bundle from. */ public void readFromParcel(Parcel parcel) { - mParcelledData = parcel; - mHasFds = mParcelledData.hasFileDescriptors(); + int length = parcel.readInt(); + if (length < 0) { + throw new RuntimeException("Bad length in parcel: " + length); + } + readFromParcelInner(parcel, length); + } + + void readFromParcelInner(Parcel parcel, int length) { + int magic = parcel.readInt(); + if (magic != 0x4C444E42) { + //noinspection ThrowableInstanceNeverThrown + String st = Log.getStackTraceString(new RuntimeException()); + Log.e("Bundle", "readBundle: bad magic number"); + Log.e("Bundle", "readBundle: trace = " + st); + } + + // Advance within this Parcel + int offset = parcel.dataPosition(); + parcel.setDataPosition(offset + length); + + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.appendFrom(parcel, offset, length); + p.setDataPosition(0); + + mParcelledData = p; + mHasFds = p.hasFileDescriptors(); mFdsKnown = true; } diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 8fcb4d7..d40ea6b 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/os/MemoryFile.java b/core/java/android/os/MemoryFile.java index 76e4f47..c14925c 100644 --- a/core/java/android/os/MemoryFile.java +++ b/core/java/android/os/MemoryFile.java @@ -18,6 +18,7 @@ package android.os; import android.util.Log; +import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -35,48 +36,120 @@ import java.io.OutputStream; public class MemoryFile { private static String TAG = "MemoryFile"; - - // returns fd - private native int native_open(String name, int length); + + // mmap(2) protection flags from <sys/mman.h> + private static final int PROT_READ = 0x1; + private static final int PROT_WRITE = 0x2; + + private static native FileDescriptor native_open(String name, int length) throws IOException; // returns memory address for ashmem region - private native int native_mmap(int fd, int length); - private native void native_close(int fd); - private native int native_read(int fd, int address, byte[] buffer, - int srcOffset, int destOffset, int count, boolean isUnpinned); - private native void native_write(int fd, int address, byte[] buffer, - int srcOffset, int destOffset, int count, boolean isUnpinned); - private native void native_pin(int fd, boolean pin); - - private int mFD; // ashmem file descriptor + private static native int native_mmap(FileDescriptor fd, int length, int mode) + throws IOException; + private static native void native_munmap(int addr, int length) throws IOException; + private static native void native_close(FileDescriptor fd); + private static native int native_read(FileDescriptor fd, int address, byte[] buffer, + int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException; + private static native void native_write(FileDescriptor fd, int address, byte[] buffer, + int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException; + private static native void native_pin(FileDescriptor fd, boolean pin) throws IOException; + private static native boolean native_is_ashmem_region(FileDescriptor fd) throws IOException; + + private FileDescriptor mFD; // ashmem file descriptor private int mAddress; // address of ashmem memory private int mLength; // total length of our ashmem region private boolean mAllowPurging = false; // true if our ashmem region is unpinned + private final boolean mOwnsRegion; // false if this is a ref to an existing ashmem region /** - * MemoryFile constructor. + * Allocates a new ashmem region. The region is initially not purgable. * * @param name optional name for the file (can be null). * @param length of the memory file in bytes. + * @throws IOException if the memory file could not be created. */ - public MemoryFile(String name, int length) { + public MemoryFile(String name, int length) throws IOException { mLength = length; mFD = native_open(name, length); - mAddress = native_mmap(mFD, length); + mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE); + mOwnsRegion = true; } /** - * Closes and releases all resources for the memory file. + * Creates a reference to an existing memory file. Changes to the original file + * will be available through this reference. + * Calls to {@link #allowPurging(boolean)} on the returned MemoryFile will fail. + * + * @param fd File descriptor for an existing memory file, as returned by + * {@link #getFileDescriptor()}. This file descriptor will be closed + * by {@link #close()}. + * @param length Length of the memory file in bytes. + * @param mode File mode. Currently only "r" for read-only access is supported. + * @throws NullPointerException if <code>fd</code> is null. + * @throws IOException If <code>fd</code> does not refer to an existing memory file, + * or if the file mode of the existing memory file is more restrictive + * than <code>mode</code>. + * + * @hide + */ + public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException { + if (fd == null) { + throw new NullPointerException("File descriptor is null."); + } + if (!isMemoryFile(fd)) { + throw new IllegalArgumentException("Not a memory file."); + } + mLength = length; + mFD = fd; + mAddress = native_mmap(mFD, length, modeToProt(mode)); + mOwnsRegion = false; + } + + /** + * Closes the memory file. If there are no other open references to the memory + * file, it will be deleted. */ public void close() { - if (mFD > 0) { + deactivate(); + if (!isClosed()) { native_close(mFD); - mFD = 0; } } + /** + * Unmaps the memory file from the process's memory space, but does not close it. + * After this method has been called, read and write operations through this object + * will fail, but {@link #getFileDescriptor()} will still return a valid file descriptor. + * + * @hide + */ + public void deactivate() { + if (!isDeactivated()) { + try { + native_munmap(mAddress, mLength); + mAddress = 0; + } catch (IOException ex) { + Log.e(TAG, ex.toString()); + } + } + } + + /** + * Checks whether the memory file has been deactivated. + */ + private boolean isDeactivated() { + return mAddress == 0; + } + + /** + * Checks whether the memory file has been closed. + */ + private boolean isClosed() { + return !mFD.valid(); + } + @Override protected void finalize() { - if (mFD > 0) { + if (!isClosed()) { Log.e(TAG, "MemoryFile.finalize() called while ashmem still open"); close(); } @@ -108,6 +181,9 @@ public class MemoryFile * @return previous value of allowPurging */ synchronized public boolean allowPurging(boolean allowPurging) throws IOException { + if (!mOwnsRegion) { + throw new IOException("Only the owner can make ashmem regions purgable."); + } boolean oldValue = mAllowPurging; if (oldValue != allowPurging) { native_pin(mFD, !allowPurging); @@ -131,7 +207,6 @@ public class MemoryFile @return OutputStream */ public OutputStream getOutputStream() { - return new MemoryOutputStream(); } @@ -144,9 +219,13 @@ public class MemoryFile * @param destOffset offset into the byte array buffer to read into. * @param count number of bytes to read. * @return number of bytes read. + * @throws IOException if the memory file has been purged or deactivated. */ public int readBytes(byte[] buffer, int srcOffset, int destOffset, int count) throws IOException { + if (isDeactivated()) { + throw new IOException("Can't read from deactivated memory file."); + } if (destOffset < 0 || destOffset > buffer.length || count < 0 || count > buffer.length - destOffset || srcOffset < 0 || srcOffset > mLength @@ -164,9 +243,13 @@ public class MemoryFile * @param srcOffset offset into the byte array buffer to write from. * @param destOffset offset into the memory file to write to. * @param count number of bytes to write. + * @throws IOException if the memory file has been purged or deactivated. */ public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count) throws IOException { + if (isDeactivated()) { + throw new IOException("Can't write to deactivated memory file."); + } if (srcOffset < 0 || srcOffset > buffer.length || count < 0 || count > buffer.length - srcOffset || destOffset < 0 || destOffset > mLength @@ -176,6 +259,64 @@ public class MemoryFile native_write(mFD, mAddress, buffer, srcOffset, destOffset, count, mAllowPurging); } + /** + * Gets a ParcelFileDescriptor for the memory file. See {@link #getFileDescriptor()} + * for caveats. This must be here to allow classes outside <code>android.os</code< to + * make ParcelFileDescriptors from MemoryFiles, as + * {@link ParcelFileDescriptor#ParcelFileDescriptor(FileDescriptor)} is package private. + * + * + * @return The file descriptor owned by this memory file object. + * The file descriptor is not duplicated. + * @throws IOException If the memory file has been closed. + * + * @hide + */ + public ParcelFileDescriptor getParcelFileDescriptor() throws IOException { + return new ParcelFileDescriptor(getFileDescriptor()); + } + + /** + * Gets a FileDescriptor for the memory file. Note that this file descriptor + * is only safe to pass to {@link #MemoryFile(FileDescriptor,int)}). It + * should not be used with file descriptor operations that expect a file descriptor + * for a normal file. + * + * The returned file descriptor is not duplicated. + * + * @throws IOException If the memory file has been closed. + * + * @hide + */ + public FileDescriptor getFileDescriptor() throws IOException { + return mFD; + } + + /** + * Checks whether the given file descriptor refers to a memory file. + * + * @throws IOException If <code>fd</code> is not a valid file descriptor. + * + * @hide + */ + public static boolean isMemoryFile(FileDescriptor fd) throws IOException { + return native_is_ashmem_region(fd); + } + + /** + * Converts a file mode string to a <code>prot</code> value as expected by + * native_mmap(). + * + * @throws IllegalArgumentException if the file mode is invalid. + */ + private static int modeToProt(String mode) { + if ("r".equals(mode)) { + return PROT_READ; + } else { + throw new IllegalArgumentException("Unsupported file mode: '" + mode + "'"); + } + } + private class MemoryInputStream extends InputStream { private int mMark = 0; @@ -212,13 +353,22 @@ public class MemoryFile } int result = read(mSingleByte, 0, 1); if (result != 1) { - throw new IOException("read() failed"); + return -1; } return mSingleByte[0]; } @Override public int read(byte buffer[], int offset, int count) throws IOException { + if (offset < 0 || count < 0 || offset + count > buffer.length) { + // readBytes() also does this check, but we need to do it before + // changing count. + throw new IndexOutOfBoundsException(); + } + count = Math.min(count, available()); + if (count < 1) { + return -1; + } int result = readBytes(buffer, mOffset, offset, count); if (result > 0) { mOffset += result; diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 9a71f6e..6cfccee 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -457,7 +457,7 @@ public final class Parcel { * Flatten a Map into the parcel at the current dataPosition(), * growing dataCapacity() if needed. The Map keys must be String objects. */ - private void writeMapInternal(Map<String,Object> val) { + /* package */ void writeMapInternal(Map<String,Object> val) { if (val == null) { writeInt(-1); return; @@ -480,23 +480,7 @@ public final class Parcel { return; } - if (val.mParcelledData != null) { - int length = val.mParcelledData.dataSize(); - appendFrom(val.mParcelledData, 0, length); - } else { - writeInt(-1); // dummy, will hold length - int oldPos = dataPosition(); - writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' - - writeMapInternal(val.mMap); - int newPos = dataPosition(); - - // Backpatch length - setDataPosition(oldPos - 4); - int length = newPos - oldPos; - writeInt(length); - setDataPosition(newPos); - } + val.writeToParcel(this, 0); } /** @@ -1352,27 +1336,12 @@ public final class Parcel { * Returns null if the previously written Bundle object was null. */ public final Bundle readBundle(ClassLoader loader) { - int offset = dataPosition(); int length = readInt(); if (length < 0) { return null; } - int magic = readInt(); - if (magic != 0x4C444E42) { - //noinspection ThrowableInstanceNeverThrown - String st = Log.getStackTraceString(new RuntimeException()); - Log.e("Bundle", "readBundle: bad magic number"); - Log.e("Bundle", "readBundle: trace = " + st); - } - - // Advance within this Parcel - setDataPosition(offset + length + 4); - - Parcel p = new Parcel(0); - p.setDataPosition(0); - p.appendFrom(this, offset, length + 4); - p.setDataPosition(0); - final Bundle bundle = new Bundle(p); + + final Bundle bundle = new Bundle(this, length); if (loader != null) { bundle.setClassLoader(loader); } @@ -1380,33 +1349,6 @@ public final class Parcel { } /** - * Read and return a new Bundle object from the parcel at the current - * dataPosition(). Returns null if the previously written Bundle object was - * null. The returned bundle will have its contents fully unpacked using - * the given ClassLoader. - */ - /* package */ Bundle readBundleUnpacked(ClassLoader loader) { - int length = readInt(); - if (length == -1) { - return null; - } - int magic = readInt(); - if (magic != 0x4C444E42) { - //noinspection ThrowableInstanceNeverThrown - String st = Log.getStackTraceString(new RuntimeException()); - Log.e("Bundle", "readBundleUnpacked: bad magic number"); - Log.e("Bundle", "readBundleUnpacked: trace = " + st); - } - Bundle m = new Bundle(loader); - int N = readInt(); - if (N < 0) { - return null; - } - readMapInternal(m.mMap, N, loader); - return m; - } - - /** * Read and return a byte[] object from the parcel. */ public final native byte[] createByteArray(); @@ -1998,7 +1940,7 @@ public final class Parcel { private native void init(int obj); private native void destroy(); - private void readMapInternal(Map outVal, int N, + /* package */ void readMapInternal(Map outVal, int N, ClassLoader loader) { while (N > 0) { Object key = readValue(loader); diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 30acef9..1214abc 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -573,7 +573,21 @@ public class Process { * directly to a gid. */ public static final native int getGidForName(String name); - + + /** + * Returns a uid for a currently running process. + * @param pid the process id + * @return the uid of the process, or -1 if the process is not running. + * @hide pending API council review + */ + public static final int getUidForPid(int pid) { + String[] procStatusLabels = { "Uid:" }; + long[] procStatusValues = new long[1]; + procStatusValues[0] = -1; + Process.readProcLines("/proc/" + pid + "/status", procStatusLabels, procStatusValues); + return (int) procStatusValues[0]; + } + /** * Set the priority of a thread, based on Linux priorities. * @@ -604,6 +618,20 @@ public class Process { */ public static final native void setThreadGroup(int tid, int group) throws IllegalArgumentException, SecurityException; + /** + * Sets the scheduling group for a process and all child threads + * @hide + * @param pid The indentifier of the process to change. + * @param group The target group for this process. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * <var>tid</var> does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + */ + public static final native void setProcessGroup(int pid, int group) + throws IllegalArgumentException, SecurityException; /** * Set the priority of the calling thread, based on Linux priorities. See diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java index edf69ee..3ea9b4a 100644 --- a/core/java/android/pim/EventRecurrence.java +++ b/core/java/android/pim/EventRecurrence.java @@ -408,13 +408,13 @@ public class EventRecurrence private String dayToString(Resources r, int day) { switch (day) { - case SU: return r.getString(com.android.internal.R.string.sunday); - case MO: return r.getString(com.android.internal.R.string.monday); - case TU: return r.getString(com.android.internal.R.string.tuesday); - case WE: return r.getString(com.android.internal.R.string.wednesday); - case TH: return r.getString(com.android.internal.R.string.thursday); - case FR: return r.getString(com.android.internal.R.string.friday); - case SA: return r.getString(com.android.internal.R.string.saturday); + case SU: return r.getString(com.android.internal.R.string.day_of_week_long_sunday); + case MO: return r.getString(com.android.internal.R.string.day_of_week_long_monday); + case TU: return r.getString(com.android.internal.R.string.day_of_week_long_tuesday); + case WE: return r.getString(com.android.internal.R.string.day_of_week_long_wednesday); + case TH: return r.getString(com.android.internal.R.string.day_of_week_long_thursday); + case FR: return r.getString(com.android.internal.R.string.day_of_week_long_friday); + case SA: return r.getString(com.android.internal.R.string.day_of_week_long_saturday); default: throw new IllegalArgumentException("bad day argument: " + day); } } diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java index 1e9b7ae..cf5664c 100644 --- a/core/java/android/preference/CheckBoxPreference.java +++ b/core/java/android/preference/CheckBoxPreference.java @@ -16,6 +16,7 @@ package android.preference; +import android.app.Service; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; @@ -23,6 +24,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.widget.Checkable; import android.widget.TextView; @@ -42,6 +45,9 @@ public class CheckBoxPreference extends Preference { private CharSequence mSummaryOff; private boolean mChecked; + private boolean mSendAccessibilityEventViewClickedType; + + private AccessibilityManager mAccessibilityManager; private boolean mDisableDependentsState; @@ -55,6 +61,9 @@ public class CheckBoxPreference extends Preference { mDisableDependentsState = a.getBoolean( com.android.internal.R.styleable.CheckBoxPreference_disableDependentsState, false); a.recycle(); + + mAccessibilityManager = + (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE); } public CheckBoxPreference(Context context, AttributeSet attrs) { @@ -64,14 +73,26 @@ public class CheckBoxPreference extends Preference { public CheckBoxPreference(Context context) { this(context, null); } - + @Override protected void onBindView(View view) { super.onBindView(view); - + View checkboxView = view.findViewById(com.android.internal.R.id.checkbox); if (checkboxView != null && checkboxView instanceof Checkable) { ((Checkable) checkboxView).setChecked(mChecked); + + // send an event to announce the value change of the CheckBox and is done here + // because clicking a preference does not immediately change the checked state + // for example when enabling the WiFi + if (mSendAccessibilityEventViewClickedType && + mAccessibilityManager.isEnabled() && + checkboxView.isEnabled()) { + mSendAccessibilityEventViewClickedType = false; + + int eventType = AccessibilityEvent.TYPE_VIEW_CLICKED; + checkboxView.sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); + } } // Sync the summary view @@ -85,7 +106,7 @@ public class CheckBoxPreference extends Preference { summaryView.setText(mSummaryOff); useDefaultSummary = false; } - + if (useDefaultSummary) { final CharSequence summary = getSummary(); if (summary != null) { @@ -111,6 +132,10 @@ public class CheckBoxPreference extends Preference { boolean newValue = !isChecked(); + // in onBindView() an AccessibilityEventViewClickedType is sent to announce the change + // not sending + mSendAccessibilityEventViewClickedType = true; + if (!callChangeListener(newValue)) { return; } @@ -124,10 +149,11 @@ public class CheckBoxPreference extends Preference { * @param checked The checked state. */ public void setChecked(boolean checked) { + mChecked = checked; persistBoolean(checked); - + notifyDependencyChange(shouldDisableDependents()); notifyChanged(); diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java index 5353b53..95e5432 100644 --- a/core/java/android/preference/PreferenceScreen.java +++ b/core/java/android/preference/PreferenceScreen.java @@ -22,6 +22,7 @@ import android.content.DialogInterface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.widget.Adapter; @@ -147,13 +148,20 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi ListView listView = new ListView(context); bind(listView); - Dialog dialog = mDialog = new Dialog(context, com.android.internal.R.style.Theme_NoTitleBar); + // Set the title bar if title is available, else no title bar + final CharSequence title = getTitle(); + Dialog dialog = mDialog = new Dialog(context, TextUtils.isEmpty(title) + ? com.android.internal.R.style.Theme_NoTitleBar + : com.android.internal.R.style.Theme); dialog.setContentView(listView); + if (!TextUtils.isEmpty(title)) { + dialog.setTitle(title); + } dialog.setOnDismissListener(this); if (state != null) { dialog.onRestoreInstanceState(state); } - + // Add the screen to the list of preferences screens opened as dialogs getPreferenceManager().addPreferencesScreen(dialog); diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java index c597b3c..1ba5e25 100644 --- a/core/java/android/provider/Browser.java +++ b/core/java/android/provider/Browser.java @@ -34,6 +34,12 @@ public class Browser { Uri.parse("content://browser/bookmarks"); /** + * The inline scheme to show embedded content in a browser. + * @hide + */ + public static final Uri INLINE_URI = Uri.parse("inline:"); + + /** * The name of extra data when starting Browser with ACTION_VIEW or * ACTION_SEARCH intent. * <p> @@ -53,7 +59,48 @@ public class Browser { * identifier. */ public static final String EXTRA_APPLICATION_ID = - "com.android.browser.application_id"; + "com.android.browser.application_id"; + + /** + * The content to be rendered when url's scheme is inline. + * @hide + */ + public static final String EXTRA_INLINE_CONTENT ="com.android.browser.inline.content"; + + /** + * The encoding of the inlined content for inline scheme. + * @hide + */ + public static final String EXTRA_INLINE_ENCODING ="com.android.browser.inline.encoding"; + + /** + * The url used when the inline content is falied to render. + * @hide + */ + public static final String EXTRA_INLINE_FAILURL ="com.android.browser.inline.failurl"; + + /** + * The name of the extra data in the VIEW intent. The data is in boolean. + * <p> + * If the Browser is handling the intent and the setting for + * USE_LOCATION_FOR_SERVICES is allow, the Browser will send the location in + * the POST data if this extra data is presented and it is true. + * <p> + * pending api approval + * @hide + */ + public static final String EXTRA_APPEND_LOCATION = "com.android.browser.append_location"; + + /** + * The name of the extra data in the VIEW intent. The data is in the format of + * a byte array. + * <p> + * Any value sent here will be passed in the http request to the provided url as post data. + * <p> + * pending api approval + * @hide + */ + public static final String EXTRA_POST_DATA = "com.android.browser.post_data"; /* if you change column order you must also change indices below */ @@ -132,6 +179,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 @@ -143,6 +191,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 @@ -154,6 +203,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 @@ -203,6 +254,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. */ @@ -236,6 +289,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. */ @@ -261,6 +315,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) { @@ -270,6 +325,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. @@ -332,6 +389,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. @@ -359,6 +417,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. */ @@ -372,6 +431,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. */ @@ -401,6 +462,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) { @@ -415,6 +477,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/CallLog.java b/core/java/android/provider/CallLog.java index abd6934..7d03801 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -151,6 +151,9 @@ public class CallLog { int presentation, int callType, long start, int duration) { final ContentResolver resolver = context.getContentResolver(); + // TODO(Moto): Which is correct: original code, this only changes the + // number if the number is empty and never changes the caller info name. + if (false) { if (TextUtils.isEmpty(number)) { if (presentation == Connection.PRESENTATION_RESTRICTED) { number = CallerInfo.PRIVATE_NUMBER; @@ -160,7 +163,22 @@ public class CallLog { number = CallerInfo.UNKNOWN_NUMBER; } } - + } else { + // NEWCODE: From Motorola + + //If this is a private number then set the number to Private, otherwise check + //if the number field is empty and set the number to Unavailable + if (presentation == Connection.PRESENTATION_RESTRICTED) { + number = CallerInfo.PRIVATE_NUMBER; + ci.name = ""; + } else if (presentation == Connection.PRESENTATION_PAYPHONE) { + number = CallerInfo.PAYPHONE_NUMBER; + ci.name = ""; + } else if (TextUtils.isEmpty(number) || presentation == Connection.PRESENTATION_UNKNOWN) { + number = CallerInfo.UNKNOWN_NUMBER; + ci.name = ""; + } + } ContentValues values = new ContentValues(5); values.put(NUMBER, number); diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java index 3c23db0..f2c275e 100644 --- a/core/java/android/provider/Checkin.java +++ b/core/java/android/provider/Checkin.java @@ -137,6 +137,8 @@ public final class Checkin { CRASHES_TRUNCATED, ELAPSED_REALTIME_SEC, ELAPSED_UPTIME_SEC, + HTTP_REQUEST, + HTTP_REUSED, HTTP_STATUS, PHONE_GSM_REGISTERED, PHONE_GPRS_ATTEMPTED, @@ -351,6 +353,3 @@ public final class Checkin { } } } - - - diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java index 3141f1a..84fe184 100644 --- a/core/java/android/provider/Contacts.java +++ b/core/java/android/provider/Contacts.java @@ -340,27 +340,33 @@ public class Contacts { } /** - * Adds a person to the My Contacts group. - * - * @param resolver the resolver to use - * @param personId the person to add to the group - * @return the URI of the group membership row - * @throws IllegalStateException if the My Contacts group can't be found + * @hide Used in vCard parser code. */ - public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) { - long groupId = 0; + public static long tryGetMyContactsGroupId(ContentResolver resolver) { Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION, Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null); if (groupsCursor != null) { try { if (groupsCursor.moveToFirst()) { - groupId = groupsCursor.getLong(0); + return groupsCursor.getLong(0); } } finally { groupsCursor.close(); } } + return 0; + } + /** + * Adds a person to the My Contacts group. + * + * @param resolver the resolver to use + * @param personId the person to add to the group + * @return the URI of the group membership row + * @throws IllegalStateException if the My Contacts group can't be found + */ + public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) { + long groupId = tryGetMyContactsGroupId(resolver); if (groupId == 0) { throw new IllegalStateException("Failed to find the My Contacts group"); } @@ -869,6 +875,17 @@ public class Contacts { public static final int TYPE_OTHER = 3; /** + * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. + */ + public static final int MOBILE_EMAIL_TYPE_INDEX = 2; + + /** + * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. + * This is not "mobile" but "CELL" since vCard uses it for identifying mobile phone. + */ + public static final String MOBILE_EMAIL_TYPE_NAME = "_AUTO_CELL"; + + /** * The user defined label for the the contact method. * <P>Type: TEXT</P> */ @@ -1005,7 +1022,13 @@ public class Contacts { } } else { if (!TextUtils.isEmpty(label)) { - display = label; + if (label.toString().equals(MOBILE_EMAIL_TYPE_NAME)) { + display = + context.getString( + com.android.internal.R.string.mobileEmailTypeName); + } else { + display = label; + } } } break; diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index b6f96c4..21e5865 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -344,7 +344,10 @@ public final class MediaStore // Check if file exists with a FileInputStream FileInputStream stream = new FileInputStream(imagePath); try { - return insertImage(cr, BitmapFactory.decodeFile(imagePath), name, description); + Bitmap bm = BitmapFactory.decodeFile(imagePath); + String ret = insertImage(cr, bm, name, description); + bm.recycle(); + return ret; } finally { try { stream.close(); @@ -719,9 +722,15 @@ public final class MediaStore */ public static String keyFor(String name) { if (name != null) { + boolean sortfirst = false; if (name.equals(android.media.MediaFile.UNKNOWN_STRING)) { return "\001"; } + // Check if the first character is \001. We use this to + // force sorting of certain special files, like the silent ringtone. + if (name.startsWith("\001")) { + sortfirst = true; + } name = name.trim().toLowerCase(); if (name.startsWith("the ")) { name = name.substring(4); @@ -737,7 +746,7 @@ public final class MediaStore name.endsWith(", a") || name.endsWith(",a")) { name = name.substring(0, name.lastIndexOf(',')); } - name = name.replaceAll("[\\[\\]\\(\\)'.,?!]", "").trim(); + name = name.replaceAll("[\\[\\]\\(\\)\"'.,?!]", "").trim(); if (name.length() > 0) { // Insert a separator between the characters to avoid // matches on a partial character. If we ever change @@ -750,7 +759,11 @@ public final class MediaStore b.append('.'); } name = b.toString(); - return DatabaseUtils.getCollationKey(name); + String key = DatabaseUtils.getCollationKey(name); + if (sortfirst) { + key = "\001" + key; + } + return key; } else { return ""; } @@ -797,7 +810,7 @@ public final class MediaStore /** * The default sort order for this table */ - public static final String DEFAULT_SORT_ORDER = TITLE; + public static final String DEFAULT_SORT_ORDER = TITLE_KEY; /** * Activity Action: Start SoundRecorder application. @@ -894,7 +907,7 @@ public final class MediaStore /** * The default sort order for this table */ - public static final String DEFAULT_SORT_ORDER = TITLE; + public static final String DEFAULT_SORT_ORDER = TITLE_KEY; /** * The ID of the audio file diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4dd6524..aa583ac 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -148,7 +148,7 @@ public final class Settings { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS"; - + /** * Activity Action: Show settings to allow configuration of a static IP * address for Wi-Fi. @@ -305,7 +305,7 @@ public final class Settings { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; - + /** * Activity Action: Show settings to manage installed applications. * <p> @@ -319,7 +319,7 @@ public final class Settings { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS"; - + /** * Activity Action: Show settings for system update functionality. * <p> @@ -329,7 +329,7 @@ public final class Settings { * Input: Nothing. * <p> * Output: Nothing. - * + * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -349,7 +349,7 @@ public final class Settings { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS"; - + /** * Activity Action: Show settings for selecting the network operator. * <p> @@ -404,7 +404,7 @@ public final class Settings { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS"; - + // End of Intent actions for Settings private static final String JID_RESOURCE_PREFIX = "android"; @@ -495,7 +495,7 @@ public final class Settings { public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version"; private static volatile NameValueCache mNameValueCache = null; - + private static final HashSet<String> MOVED_TO_SECURE; static { MOVED_TO_SECURE = new HashSet<String>(30); @@ -901,12 +901,12 @@ public final class Settings { * plugged in. */ public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; - + /** * Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep. */ public static final int WIFI_SLEEP_POLICY_NEVER = 2; - + /** * Whether to use static IP and other static network attributes. * <p> @@ -1025,6 +1025,14 @@ public final class Settings { public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout"; /** + * If 0, the compatibility mode is off for all applications. + * If 1, older applications run under compatibility mode. + * TODO: remove this settings before code freeze (bug/1907571) + * @hide + */ + public static final String COMPATIBILITY_MODE = "compatibility_mode"; + + /** * The screen backlight brightness between 0 and 255. */ public static final String SCREEN_BRIGHTNESS = "screen_brightness"; @@ -1115,12 +1123,12 @@ public final class Settings { * Note: This is a one-off setting that will be removed in the future * when there is profile support. For this reason, it is kept hidden * from the public APIs. - * + * * @hide */ - public static final String NOTIFICATIONS_USE_RING_VOLUME = + public static final String NOTIFICATIONS_USE_RING_VOLUME = "notifications_use_ring_volume"; - + /** * The mapping of stream type (integer) to its setting. */ @@ -1188,7 +1196,7 @@ public final class Settings { * feature converts two spaces to a "." and space. */ public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate"; - + /** * Setting to showing password characters in text editors. 1 = On, 0 = Off */ @@ -1266,17 +1274,125 @@ public final class Settings { public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone"; /** + * CDMA only settings + * DTMF tone type played by the dialer when dialing. + * 0 = Normal + * 1 = Long + * @hide + */ + public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type"; + + /** + * CDMA only settings + * Emergency Tone 0 = Off + * 1 = Alert + * 2 = Vibrate + * @hide + */ + public static final String EMERGENCY_TONE = "emergency_tone"; + + /** + * CDMA only settings + * Whether the auto retry is enabled. The value is + * boolean (1 or 0). + * @hide + */ + public static final String CALL_AUTO_RETRY = "call_auto_retry"; + + /** + * Whether the hearing aid is enabled. The value is + * boolean (1 or 0). + * @hide + */ + public static final String HEARING_AID = "hearing_aid"; + + /** + * CDMA only settings + * TTY Mode + * 0 = OFF + * 1 = FULL + * 2 = VCO + * 3 = HCO + * @hide + */ + public static final String TTY_MODE = "tty_mode"; + + /** * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is * boolean (1 or 0). */ public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled"; - + /** * Whether the haptic feedback (long presses, ...) are enabled. The value is * boolean (1 or 0). */ public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled"; + /** + * Whether live web suggestions while the user types into search dialogs are + * enabled. Browsers and other search UIs should respect this, as it allows + * a user to avoid sending partial queries to a search engine, if it poses + * any privacy concern. The value is boolean (1 or 0). + */ + public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions"; + + /** + * Settings to backup. This is here so that it's in the same place as the settings + * keys and easy to update. + * @hide + */ + public static final String[] SETTINGS_TO_BACKUP = { + STAY_ON_WHILE_PLUGGED_IN, + END_BUTTON_BEHAVIOR, + WIFI_SLEEP_POLICY, + WIFI_USE_STATIC_IP, + WIFI_STATIC_IP, + WIFI_STATIC_GATEWAY, + WIFI_STATIC_NETMASK, + WIFI_STATIC_DNS1, + WIFI_STATIC_DNS2, + BLUETOOTH_DISCOVERABILITY, + BLUETOOTH_DISCOVERABILITY_TIMEOUT, + DIM_SCREEN, + SCREEN_OFF_TIMEOUT, + SCREEN_BRIGHTNESS, + VIBRATE_ON, + NOTIFICATIONS_USE_RING_VOLUME, + MODE_RINGER, + MODE_RINGER_STREAMS_AFFECTED, + MUTE_STREAMS_AFFECTED, + VOLUME_VOICE, + VOLUME_SYSTEM, + VOLUME_RING, + VOLUME_MUSIC, + VOLUME_ALARM, + VOLUME_NOTIFICATION, + VOLUME_VOICE + APPEND_FOR_LAST_AUDIBLE, + VOLUME_SYSTEM + APPEND_FOR_LAST_AUDIBLE, + VOLUME_RING + APPEND_FOR_LAST_AUDIBLE, + VOLUME_MUSIC + APPEND_FOR_LAST_AUDIBLE, + VOLUME_ALARM + APPEND_FOR_LAST_AUDIBLE, + VOLUME_NOTIFICATION + APPEND_FOR_LAST_AUDIBLE, + TEXT_AUTO_REPLACE, + TEXT_AUTO_CAPS, + TEXT_AUTO_PUNCTUATE, + TEXT_SHOW_PASSWORD, + AUTO_TIME, + TIME_12_24, + DATE_FORMAT, + ACCELEROMETER_ROTATION, + DTMF_TONE_WHEN_DIALING, + DTMF_TONE_TYPE_WHEN_DIALING, + EMERGENCY_TONE, + CALL_AUTO_RETRY, + HEARING_AID, + TTY_MODE, + SOUND_EFFECTS_ENABLED, + HAPTIC_FEEDBACK_ENABLED, + SHOW_WEB_SUGGESTIONS + }; + // Settings moved to Settings.Secure /** @@ -1321,7 +1437,7 @@ public final class Settings { */ @Deprecated public static final String INSTALL_NON_MARKET_APPS = Secure.INSTALL_NON_MARKET_APPS; - + /** * @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED} * instead @@ -1334,7 +1450,7 @@ public final class Settings { */ @Deprecated public static final String LOGGING_ID = Secure.LOGGING_ID; - + /** * @deprecated Use {@link android.provider.Settings.Secure#NETWORK_PREFERENCE} instead */ @@ -1374,7 +1490,7 @@ public final class Settings { */ @Deprecated public static final String USB_MASS_STORAGE_ENABLED = Secure.USB_MASS_STORAGE_ENABLED; - + /** * @deprecated Use {@link android.provider.Settings.Secure#USE_GOOGLE_MAIL} instead */ @@ -1412,7 +1528,7 @@ public final class Settings { @Deprecated public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY; - + /** * @deprecated Use {@link android.provider.Settings.Secure#WIFI_NUM_OPEN_NETWORKS_KEPT} * instead @@ -1448,7 +1564,7 @@ public final class Settings { @Deprecated public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS; - + /** * @deprecated Use * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED} instead @@ -1824,19 +1940,19 @@ public final class Settings { * Whether the device has been provisioned (0 = false, 1 = true) */ public static final String DEVICE_PROVISIONED = "device_provisioned"; - + /** * List of input methods that are currently enabled. This is a string * containing the IDs of all enabled input methods, each ID separated * by ':'. */ public static final String ENABLED_INPUT_METHODS = "enabled_input_methods"; - + /** * Host name and port for a user-selected proxy. */ public static final String HTTP_PROXY = "http_proxy"; - + /** * Whether the package installer should allow installation of apps downloaded from * sources other than the Android Market (vending machine). @@ -1845,12 +1961,12 @@ public final class Settings { * 0 = only allow installing from the Android Market */ public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; - + /** * Comma-separated list of location providers that activities may access. */ public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed"; - + /** * The Logging ID (a unique 64-bit value) as a hex string. * Used as a pseudonymous identifier for logging. @@ -1872,19 +1988,19 @@ public final class Settings { * connectivity service should touch this. */ public static final String NETWORK_PREFERENCE = "network_preference"; - - /** + + /** */ public static final String PARENTAL_CONTROL_ENABLED = "parental_control_enabled"; - - /** + + /** */ public static final String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update"; - - /** + + /** */ public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url"; - + /** * Settings classname to launch when Settings is clicked from All * Applications. Needed because of user testing between the old @@ -1892,18 +2008,67 @@ public final class Settings { */ // TODO: 881807 public static final String SETTINGS_CLASSNAME = "settings_classname"; - + /** * USB Mass Storage Enabled */ public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled"; - + /** * If this setting is set (to anything), then all references * to Gmail on the device must change to Google Mail. */ public static final String USE_GOOGLE_MAIL = "use_google_mail"; - + + /** + * If accessibility is enabled. + */ + public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled"; + + /** + * List of the enabled accessibility providers. + */ + public static final String ENABLED_ACCESSIBILITY_SERVICES = + "enabled_accessibility_services"; + + /** + * Setting to always use the default text-to-speech settings regardless + * of the application settings. + * 1 = override application settings, + * 0 = use application settings (if specified). + */ + public static final String TTS_USE_DEFAULTS = "tts_use_defaults"; + + /** + * Default text-to-speech engine speech rate. 100 = 1x + */ + public static final String TTS_DEFAULT_RATE = "tts_default_rate"; + + /** + * Default text-to-speech engine pitch. 100 = 1x + */ + public static final String TTS_DEFAULT_PITCH = "tts_default_pitch"; + + /** + * Default text-to-speech engine. + */ + public static final String TTS_DEFAULT_SYNTH = "tts_default_synth"; + + /** + * Default text-to-speech language. + */ + public static final String TTS_DEFAULT_LANG = "tts_default_lang"; + + /** + * Default text-to-speech country. + */ + public static final String TTS_DEFAULT_COUNTRY = "tts_default_country"; + + /** + * Default text-to-speech locale variant. + */ + public static final String TTS_DEFAULT_VARIANT = "tts_default_variant"; + /** * Whether to notify the user of open networks. * <p> @@ -1915,64 +2080,64 @@ public final class Settings { */ public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on"; - + /** * Delay (in seconds) before repeating the Wi-Fi networks available notification. * Connecting to a network will reset the timer. */ public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay"; - + /** * The number of radio channels that are allowed in the local * 802.11 regulatory domain. * @hide */ public static final String WIFI_NUM_ALLOWED_CHANNELS = "wifi_num_allowed_channels"; - + /** * When the number of open networks exceeds this number, the * least-recently-used excess networks will be removed. */ public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept"; - + /** * Whether the Wi-Fi should be on. Only the Wi-Fi service should touch this. */ public static final String WIFI_ON = "wifi_on"; - + /** * The acceptable packet loss percentage (range 0 - 100) before trying * another AP on the same network. */ public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage"; - + /** * The number of access points required for a network in order for the * watchdog to monitor it. */ public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count"; - + /** * The delay between background checks. */ public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms"; - + /** * Whether the Wi-Fi watchdog is enabled for background checking even * after it thinks the user has connected to a good access point. */ public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled"; - + /** * The timeout for a background ping */ public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms"; - + /** * The number of initial pings to perform that *may* be ignored if they * fail. Again, if these fail, they will *not* be used in packet loss @@ -1981,7 +2146,7 @@ public final class Settings { */ public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count"; - + /** * The maximum number of access points (per network) to attempt to test. * If this number is reached, the watchdog will no longer monitor the @@ -1989,7 +2154,7 @@ public final class Settings { * networks containing multiple APs whose DNS does not respond to pings. */ public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks"; - + /** * Whether the Wi-Fi watchdog is enabled. */ @@ -2004,24 +2169,24 @@ public final class Settings { * The number of pings to test if an access point is a good connection. */ public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count"; - + /** * The delay between pings. */ public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms"; - + /** * The timeout per ping. */ public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms"; - + /** * The maximum number of times we will retry a connection to an access * point for which we have failed in acquiring an IP address from DHCP. * A value of N means that we will make N+1 connection attempts in all. */ public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count"; - + /** * Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile * data connectivity to be established after a disconnect from Wi-Fi. @@ -2051,20 +2216,29 @@ public final class Settings { public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode"; /** - * represents current active phone class - * 1 = GSM-Phone, 0 = CDMA-Phone + * The preferred network mode 7 = Global + * 6 = EvDo only + * 5 = CDMA w/o EvDo + * 4 = CDMA / EvDo auto + * 3 = GSM / WCDMA auto + * 2 = WCDMA only + * 1 = GSM only + * 0 = GSM / WCDMA preferred * @hide */ - public static final String CURRENT_ACTIVE_PHONE = "current_active_phone"; + public static final String PREFERRED_NETWORK_MODE = + "preferred_network_mode"; /** - * The preferred network mode 7 = Global, CDMA default - * 4 = CDMA only - * 3 = GSM/UMTS only + * The preferred TTY mode 0 = TTy Off, CDMA default + * 1 = TTY Full + * 2 = TTY HCO + * 3 = TTY VCO * @hide */ - public static final String PREFERRED_NETWORK_MODE = - "preferred_network_mode"; + public static final String PREFERRED_TTY_MODE = + "preferred_tty_mode"; + /** * CDMA Cell Broadcast SMS @@ -2100,6 +2274,71 @@ public final class Settings { public static final String TTY_MODE_ENABLED = "tty_mode_enabled"; /** + * Flag for allowing service provider to use location information to improve products and + * services. + * Type: int ( 0 = disallow, 1 = allow ) + * @hide + */ + public static final String USE_LOCATION_FOR_SERVICES = "use_location"; + + /** + * Controls whether settings backup is enabled. + * Type: int ( 0 = disabled, 1 = enabled ) + * @hide + */ + public static final String BACKUP_ENABLED = "backup_enabled"; + + /** + * Indicates whether settings backup has been fully provisioned. + * Type: int ( 0 = unprovisioned, 1 = fully provisioned ) + * @hide + */ + public static final String BACKUP_PROVISIONED = "backup_provisioned"; + + /** + * Component of the transport to use for backup/restore. + * @hide + */ + public static final String BACKUP_TRANSPORT = "backup_transport"; + + /** + * Version for which the setup wizard was last shown. Bumped for + * each release when there is new setup information to show. + * @hide + */ + public static final String LAST_SETUP_SHOWN = "last_setup_shown"; + + /** + * @hide + */ + public static final String[] SETTINGS_TO_BACKUP = { + ADB_ENABLED, + ALLOW_MOCK_LOCATION, + INSTALL_NON_MARKET_APPS, + PARENTAL_CONTROL_ENABLED, + PARENTAL_CONTROL_REDIRECT_URL, + USB_MASS_STORAGE_ENABLED, + ACCESSIBILITY_ENABLED, + ENABLED_ACCESSIBILITY_SERVICES, + TTS_USE_DEFAULTS, + TTS_DEFAULT_RATE, + TTS_DEFAULT_PITCH, + TTS_DEFAULT_SYNTH, + TTS_DEFAULT_LANG, + TTS_DEFAULT_COUNTRY, + WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + WIFI_NUM_ALLOWED_CHANNELS, + WIFI_NUM_OPEN_NETWORKS_KEPT, + BACKGROUND_DATA, + PREFERRED_NETWORK_MODE, + PREFERRED_TTY_MODE, + CDMA_CELL_BROADCAST_SMS, + PREFERRED_CDMA_SUBSCRIPTION, + ENHANCED_VOICE_PRIVACY_ENABLED + }; + + /** * Helper method for determining if a location provider is enabled. * @param cr the content resolver to use * @param provider the location provider to query @@ -2115,7 +2354,7 @@ public final class Settings { allowedProviders.startsWith(provider + ",") || allowedProviders.endsWith("," + provider)); } - return false; + return false; } /** @@ -2139,7 +2378,7 @@ public final class Settings { putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); } } - + /** * Gservices settings, containing the network names for Google's * various services. This table holds simple name/addr pairs. @@ -2160,6 +2399,13 @@ public final class Settings { public static final String CHANGED_ACTION = "com.google.gservices.intent.action.GSERVICES_CHANGED"; + /** + * Intent action to override Gservices for testing. (Requires WRITE_GSERVICES permission.) + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String OVERRIDE_ACTION = + "com.google.gservices.intent.action.GSERVICES_OVERRIDE"; + private static volatile NameValueCache mNameValueCache = null; private static final Object mNameValueCacheLock = new Object(); @@ -2260,7 +2506,7 @@ public final class Settings { * Event tags from the kernel event log to upload during checkin. */ public static final String CHECKIN_EVENTS = "checkin_events"; - + /** * Event tags for list of services to upload during checkin. */ @@ -2428,12 +2674,34 @@ public final class Settings { public static final String GMAIL_BUFFER_SERVER_RESPONSE = "gmail_buffer_server_response"; /** + * The maximum size in bytes allowed for the provider to gzip a protocol buffer uploaded to + * the server. + */ + public static final String GMAIL_MAX_GZIP_SIZE = "gmail_max_gzip_size_bytes"; + + /** * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be * an integer where non-zero means true. Defaults to 1. */ public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op"; /** + * Controls how many attempts Gmail will try to upload an uphill operations before it + * abandons the operation. Defaults to 20. + */ + public static final String GMAIL_NUM_RETRY_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"; @@ -2561,6 +2829,21 @@ public final class Settings { "gtalk_ssl_handshake_timeout_ms"; /** + * Compress the gtalk stream. + */ + public static final String GTALK_COMPRESS = "gtalk_compress"; + + /** + * This is the timeout for which Google Talk will send the message using bareJID. In a + * established chat between two XMPP endpoints, Google Talk uses fullJID in the format + * of user@domain/resource in order to send the message to the specific client. However, + * if Google Talk hasn't received a message from that client after some time, it would + * fall back to use the bareJID, which would broadcast the message to all clients for + * the other user. + */ + public static final String GTALK_USE_BARE_JID_TIMEOUT_MS = "gtalk_use_barejid_timeout_ms"; + + /** * Enable use of ssl session caching. * 'db' - save each session in a (per process) database * 'file' - save each session in a (per process) file @@ -2657,6 +2940,20 @@ public final class Settings { public static final String VENDING_TAB_2_TITLE = "vending_tab_2_title"; /** + * Frequency in milliseconds at which we should request MCS heartbeats + * from the Vending Machine client. + */ + public static final String VENDING_HEARTBEAT_FREQUENCY_MS = + "vending_heartbeat_frequency_ms"; + + /** + * Frequency in milliseconds at which we should resend pending download + * requests to the API Server from the Vending Machine client. + */ + public static final String VENDING_PENDING_DOWNLOAD_RESEND_FREQUENCY_MS = + "vending_pd_resend_frequency_ms"; + + /** * URL that points to the legal terms of service to display in Settings. * <p> * This should be a https URL. For a pretty user-friendly URL, use @@ -2796,12 +3093,12 @@ public final class Settings { * out without asking for use permit, to limit the un-authorized SMS * usage. */ - public static final String SMS_OUTGOING_CEHCK_INTERVAL_MS = + public static final String SMS_OUTGOING_CHECK_INTERVAL_MS = "sms_outgoing_check_interval_ms"; /** * The number of outgoing SMS sent without asking for user permit - * (of {@link #SMS_OUTGOING_CEHCK_INTERVAL_MS} + * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS} */ public static final String SMS_OUTGOING_CEHCK_MAX_COUNT = "sms_outgoing_check_max_count"; @@ -2950,13 +3247,21 @@ public final class Settings { public static final String BATTERY_DISCHARGE_DURATION_THRESHOLD = "battery_discharge_duration_threshold"; public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold"; - + /** * An email address that anr bugreports should be sent to. */ public static final String ANR_BUGREPORT_RECIPIENT = "anr_bugreport_recipient"; /** + * Flag for allowing service provider to use location information to improve products and + * services. + * Type: int ( 0 = disallow, 1 = allow ) + * @deprecated + */ + public static final String USE_LOCATION_FOR_SERVICES = "use_location"; + + /** * @deprecated * @hide */ @@ -3094,7 +3399,7 @@ public final class Settings { /** * Add a new bookmark to the system. - * + * * @param cr The ContentResolver to query. * @param intent The desired target of the bookmark. * @param title Bookmark title that is shown to the user; null if none @@ -3159,7 +3464,7 @@ public final class Settings { /** * Return the title as it should be displayed to the user. This takes * care of localizing bookmarks that point to activities. - * + * * @param context A context. * @param cursor A cursor pointing to the row whose title should be * returned. The cursor must contain at least the {@link #TITLE} @@ -3174,24 +3479,24 @@ public final class Settings { throw new IllegalArgumentException( "The cursor must contain the TITLE and INTENT columns."); } - + String title = cursor.getString(titleColumn); if (!TextUtils.isEmpty(title)) { return title; } - + String intentUri = cursor.getString(intentColumn); if (TextUtils.isEmpty(intentUri)) { return ""; } - + Intent intent; try { intent = Intent.getIntent(intentUri); } catch (URISyntaxException e) { return ""; } - + PackageManager packageManager = context.getPackageManager(); ResolveInfo info = packageManager.resolveActivity(intent, 0); return info != null ? info.loadLabel(packageManager) : ""; @@ -3247,4 +3552,3 @@ public final class Settings { return "android-" + Long.toHexString(androidId); } } - diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index a4145c4..4078fa6 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -466,6 +466,24 @@ public final class Telephony { */ public static final class Intents { /** + * Set by BroadcastReceiver. Indicates the message was handled + * successfully. + */ + public static final int RESULT_SMS_HANDLED = 1; + + /** + * Set by BroadcastReceiver. Indicates a generic error while + * processing the message. + */ + public static final int RESULT_SMS_GENERIC_ERROR = 2; + + /** + * Set by BroadcastReceiver. Indicates insufficient memory to store + * the message. + */ + public static final int RESULT_SMS_OUT_OF_MEMORY = 3; + + /** * Broadcast Action: A new text based SMS message has been received * by the device. The intent will have the following extra * values:</p> @@ -476,7 +494,10 @@ public final class Telephony { * </ul> * * <p>The extra values can be extracted using - * {@link #getMessagesFromIntent(Intent)}</p> + * {@link #getMessagesFromIntent(Intent)}.</p> + * + * <p>If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.</p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = @@ -493,7 +514,10 @@ public final class Telephony { * </ul> * * <p>The extra values can be extracted using - * {@link #getMessagesFromIntent(Intent)}</p> + * {@link #getMessagesFromIntent(Intent)}.</p> + * + * <p>If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.</p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = @@ -510,6 +534,9 @@ public final class Telephony { * <li><em>pduType (Integer)</em> - The WAP PDU type</li> * <li><em>data</em> - The data payload of the message</li> * </ul> + * + * <p>If a BroadcastReceiver encounters an error while processing + * this intent it should set the result code appropriately.</p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 8e5cee9..8c843ef 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -372,6 +372,10 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { mEventLoop.onModeChanged(getModeNative()); } + if (mIsAirplaneSensitive && isAirplaneModeOn()) { + disable(false); + } + } } @@ -1220,6 +1224,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { break; } pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); + pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint()); + headset.close(); } diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index 03623d6..373e61f 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -17,48 +17,69 @@ package android.server.search; import android.app.ISearchManager; +import android.app.ISearchManagerCallback; +import android.app.SearchDialog; +import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; +import android.os.Bundle; import android.os.Handler; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; /** * This is a simplified version of the Search Manager service. It no longer handles - * presentation (UI). Its function is to maintain the map & list of "searchable" + * presentation (UI). Its function is to maintain the map & list of "searchable" * items, which provides a mapping from individual activities (where a user might have * invoked search) to specific searchable activities (where the search will be dispatched). */ public class SearchManagerService extends ISearchManager.Stub + implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { // general debugging support private static final String TAG = "SearchManagerService"; - private static final boolean DEBUG = false; - - // configuration choices - private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true; + private static final boolean DBG = false; // class maintenance and general shared data private final Context mContext; private final Handler mHandler; private boolean mSearchablesDirty; - private Searchables mSearchables; - + private final Searchables mSearchables; + + final SearchDialog mSearchDialog; + ISearchManagerCallback mCallback = null; + + private final boolean mDisabledOnBoot; + + private static final String DISABLE_SEARCH_PROPERTY = "dev.disablesearchdialog"; + /** * Initializes the Search Manager service in the provided system context. * Only one instance of this object should be created! * * @param context to use for accessing DB, window manager, etc. */ - public SearchManagerService(Context context) { + public SearchManagerService(Context context) { mContext = context; mHandler = new Handler(); mSearchablesDirty = true; mSearchables = new Searchables(context); - + mSearchDialog = new SearchDialog(context); + mSearchDialog.setOnCancelListener(this); + mSearchDialog.setOnDismissListener(this); + // Setup the infrastructure for updating and maintaining the list // of searchable activities. IntentFilter filter = new IntentFilter(); @@ -67,17 +88,18 @@ public class SearchManagerService extends ISearchManager.Stub filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); - + // After startup settles down, preload the searchables list, // which will reduce the delay when the search UI is invoked. - if (IMMEDIATE_SEARCHABLES_UPDATE) { - mHandler.post(mRunUpdateSearchable); - } + mHandler.post(mRunUpdateSearchable); + + // allows disabling of search dialog for stress testing runs + mDisabledOnBoot = !TextUtils.isEmpty(SystemProperties.get(DISABLE_SEARCH_PROPERTY)); } - + /** * Listens for intent broadcasts. - * + * * The primary purpose here is to refresh the "searchables" list * if packages are added/removed. */ @@ -85,29 +107,25 @@ public class SearchManagerService extends ISearchManager.Stub @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - + // First, test for intents that matter at any time if (action.equals(Intent.ACTION_PACKAGE_ADDED) || action.equals(Intent.ACTION_PACKAGE_REMOVED) || action.equals(Intent.ACTION_PACKAGE_CHANGED)) { mSearchablesDirty = true; - if (IMMEDIATE_SEARCHABLES_UPDATE) { - mHandler.post(mRunUpdateSearchable); - } + mHandler.post(mRunUpdateSearchable); return; } } }; - + /** * This runnable (for the main handler / UI thread) will update the searchables list. */ private Runnable mRunUpdateSearchable = new Runnable() { public void run() { - if (mSearchablesDirty) { - updateSearchables(); - } - } + updateSearchablesIfDirty(); + } }; /** @@ -115,42 +133,251 @@ public class SearchManagerService extends ISearchManager.Stub * a package add/remove broadcast message. */ private void updateSearchables() { + if (DBG) debug("updateSearchables()"); mSearchables.buildSearchableList(); mSearchablesDirty = false; } /** + * Updates the list of searchables if needed. + */ + private void updateSearchablesIfDirty() { + if (mSearchablesDirty) { + updateSearchables(); + } + } + + /** * Returns the SearchableInfo for a given activity * * @param launchActivity The activity from which we're launching this search. * @param globalSearch If false, this will only launch the search that has been specifically - * defined by the application (which is usually defined as a local search). If no default + * defined by the application (which is usually defined as a local search). If no default * search is defined in the current application or activity, no search will be launched. * If true, this will always launch a platform-global (e.g. web-based) search instead. * @return Returns a SearchableInfo record describing the parameters of the search, * or null if no searchable metadata was available. */ public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) { - // final check. however we should try to avoid this, because - // it slows down the entry into the UI. - if (mSearchablesDirty) { - updateSearchables(); - } + updateSearchablesIfDirty(); SearchableInfo si = null; if (globalSearch) { si = mSearchables.getDefaultSearchable(); } else { + if (launchActivity == null) { + Log.e(TAG, "getSearchableInfo(), activity == null"); + return null; + } si = mSearchables.getSearchableInfo(launchActivity); } return si; } - + /** * Returns a list of the searchable activities that can be included in global search. */ public List<SearchableInfo> getSearchablesInGlobalSearch() { + updateSearchablesIfDirty(); return mSearchables.getSearchablesInGlobalSearchList(); } + /** + * Launches the search UI on the main thread of the service. + * + * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean) + */ + public void startSearch(final String initialQuery, + final boolean selectInitialQuery, + final ComponentName launchActivity, + final Bundle appSearchData, + final boolean globalSearch, + final ISearchManagerCallback searchManagerCallback) { + if (DBG) debug("startSearch()"); + Runnable task = new Runnable() { + public void run() { + performStartSearch(initialQuery, + selectInitialQuery, + launchActivity, + appSearchData, + globalSearch, + searchManagerCallback); + } + }; + mHandler.post(task); + } + + /** + * Actually launches the search. This must be called on the service UI thread. + */ + /*package*/ void performStartSearch(String initialQuery, + boolean selectInitialQuery, + ComponentName launchActivity, + Bundle appSearchData, + boolean globalSearch, + ISearchManagerCallback searchManagerCallback) { + if (DBG) debug("performStartSearch()"); + + if (mDisabledOnBoot) { + Log.d(TAG, "ignoring start search request because " + DISABLE_SEARCH_PROPERTY + + " system property is set."); + return; + } + + mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, + globalSearch); + if (searchManagerCallback != null) { + mCallback = searchManagerCallback; + } + } + + /** + * Cancels the search dialog. Can be called from any thread. + */ + public void stopSearch() { + if (DBG) debug("stopSearch()"); + mHandler.post(new Runnable() { + public void run() { + performStopSearch(); + } + }); + } + + /** + * Cancels the search dialog. Must be called from the service UI thread. + */ + /*package*/ void performStopSearch() { + if (DBG) debug("performStopSearch()"); + mSearchDialog.cancel(); + } + + /** + * Determines if the Search UI is currently displayed. + * + * @see SearchManager#isVisible() + */ + public boolean isVisible() { + return postAndWait(mIsShowing, false, "isShowing()"); + } + + private final Callable<Boolean> mIsShowing = new Callable<Boolean>() { + public Boolean call() { + return mSearchDialog.isShowing(); + } + }; + + public Bundle onSaveInstanceState() { + return postAndWait(mOnSaveInstanceState, null, "onSaveInstanceState()"); + } + + private final Callable<Bundle> mOnSaveInstanceState = new Callable<Bundle>() { + public Bundle call() { + if (mSearchDialog.isShowing()) { + return mSearchDialog.onSaveInstanceState(); + } else { + return null; + } + } + }; + + public void onRestoreInstanceState(final Bundle searchDialogState) { + if (searchDialogState != null) { + mHandler.post(new Runnable() { + public void run() { + mSearchDialog.onRestoreInstanceState(searchDialogState); + } + }); + } + } + + public void onConfigurationChanged(final Configuration newConfig) { + mHandler.post(new Runnable() { + public void run() { + if (mSearchDialog.isShowing()) { + mSearchDialog.onConfigurationChanged(newConfig); + } + } + }); + } + + /** + * Called by {@link SearchDialog} when it goes away. + */ + public void onDismiss(DialogInterface dialog) { + if (DBG) debug("onDismiss()"); + if (mCallback != null) { + try { + mCallback.onDismiss(); + } catch (RemoteException ex) { + Log.e(TAG, "onDismiss() failed: " + ex); + } + } + } + + /** + * Called by {@link SearchDialog} when the user or activity cancels search. + * When this is called, {@link #onDismiss} is called too. + */ + public void onCancel(DialogInterface dialog) { + if (DBG) debug("onCancel()"); + if (mCallback != null) { + try { + mCallback.onCancel(); + } catch (RemoteException ex) { + Log.e(TAG, "onCancel() failed: " + ex); + } + } + } + + /** + * Returns a list of the searchable activities that handle web searches. + */ + public List<SearchableInfo> getSearchablesForWebSearch() { + updateSearchablesIfDirty(); + return mSearchables.getSearchablesForWebSearchList(); + } + + /** + * Returns the default searchable activity for web searches. + */ + public SearchableInfo getDefaultSearchableForWebSearch() { + updateSearchablesIfDirty(); + return mSearchables.getDefaultSearchableForWebSearch(); + } + + /** + * Sets the default searchable activity for web searches. + */ + public void setDefaultWebSearch(ComponentName component) { + mSearchables.setDefaultWebSearch(component); + } + + /** + * Runs an operation on the handler for the service, blocks until it returns, + * and returns the value returned by the operation. + * + * @param <V> Return value type. + * @param callable Operation to run. + * @param errorResult Value to return if the operations throws an exception. + * @param name Operation name to include in error log messages. + * @return The value returned by the operation. + */ + private <V> V postAndWait(Callable<V> callable, V errorResult, String name) { + FutureTask<V> task = new FutureTask<V>(callable); + mHandler.post(task); + try { + return task.get(); + } catch (InterruptedException ex) { + Log.e(TAG, "Error calling " + name + ": " + ex); + return errorResult; + } catch (ExecutionException ex) { + Log.e(TAG, "Error calling " + name + ": " + ex); + return errorResult; + } + } + + private static void debug(String msg) { + Thread thread = Thread.currentThread(); + Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")"); + } } diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index 842fc75..8ef1f15 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -40,7 +40,7 @@ import java.util.HashMap; public final class SearchableInfo implements Parcelable { // general debugging support - private static final boolean DBG = true; + private static final boolean DBG = false; private static final String LOG_TAG = "SearchableInfo"; // static strings used for XML lookups. @@ -66,6 +66,8 @@ public final class SearchableInfo implements Parcelable { private final int mSearchInputType; private final int mSearchImeOptions; private final boolean mIncludeInGlobalSearch; + private final boolean mQueryAfterZeroResults; + private final String mSettingsDescription; private final String mSuggestAuthority; private final String mSuggestPath; private final String mSuggestSelection; @@ -133,6 +135,14 @@ public final class SearchableInfo implements Parcelable { public boolean shouldRewriteQueryFromText() { return 0 != (mSearchMode & SEARCH_MODE_QUERY_REWRITE_FROM_TEXT); } + + /** + * Gets the description to use for this source in system search settings, or null if + * none has been specified. + */ + public String getSettingsDescription() { + return mSettingsDescription; + } /** * Retrieve the path for obtaining search suggestions. @@ -276,7 +286,11 @@ public final class SearchableInfo implements Parcelable { EditorInfo.IME_ACTION_SEARCH); mIncludeInGlobalSearch = a.getBoolean( com.android.internal.R.styleable.Searchable_includeInGlobalSearch, false); + mQueryAfterZeroResults = a.getBoolean( + com.android.internal.R.styleable.Searchable_queryAfterZeroResults, false); + mSettingsDescription = a.getString( + com.android.internal.R.styleable.Searchable_searchSettingsDescription); mSuggestAuthority = a.getString( com.android.internal.R.styleable.Searchable_searchSuggestAuthority); mSuggestPath = a.getString( @@ -317,7 +331,7 @@ public final class SearchableInfo implements Parcelable { // for now, implement some form of rules - minimal data if (mLabelId == 0) { - throw new IllegalArgumentException("No label."); + throw new IllegalArgumentException("Search label must be a resource reference."); } } @@ -438,13 +452,18 @@ public final class SearchableInfo implements Parcelable { xml.close(); if (DBG) { - Log.d(LOG_TAG, "Checked " + activityInfo.name - + ",label=" + searchable.getLabelId() - + ",icon=" + searchable.getIconId() - + ",suggestAuthority=" + searchable.getSuggestAuthority() - + ",target=" + searchable.getSearchActivity().getClassName() - + ",global=" + searchable.shouldIncludeInGlobalSearch() - + ",threshold=" + searchable.getSuggestThreshold()); + if (searchable != null) { + Log.d(LOG_TAG, "Checked " + activityInfo.name + + ",label=" + searchable.getLabelId() + + ",icon=" + searchable.getIconId() + + ",suggestAuthority=" + searchable.getSuggestAuthority() + + ",target=" + searchable.getSearchActivity().getClassName() + + ",global=" + searchable.shouldIncludeInGlobalSearch() + + ",settingsDescription=" + searchable.getSettingsDescription() + + ",threshold=" + searchable.getSuggestThreshold()); + } else { + Log.d(LOG_TAG, "Checked " + activityInfo.name + ", no searchable meta-data"); + } } return searchable; } @@ -637,6 +656,17 @@ public final class SearchableInfo implements Parcelable { } /** + * Checks whether this searchable activity should be invoked after a query returned zero + * results. + * + * @return The value of the <code>queryAfterZeroResults</code> attribute, + * or <code>false</code> if the attribute is not set. + */ + public boolean queryAfterZeroResults() { + return mQueryAfterZeroResults; + } + + /** * Support for parcelable and aidl operations. */ public static final Parcelable.Creator<SearchableInfo> CREATOR @@ -667,7 +697,9 @@ public final class SearchableInfo implements Parcelable { mSearchInputType = in.readInt(); mSearchImeOptions = in.readInt(); mIncludeInGlobalSearch = in.readInt() != 0; - + mQueryAfterZeroResults = in.readInt() != 0; + + mSettingsDescription = in.readString(); mSuggestAuthority = in.readString(); mSuggestPath = in.readString(); mSuggestSelection = in.readString(); @@ -702,7 +734,9 @@ public final class SearchableInfo implements Parcelable { dest.writeInt(mSearchInputType); dest.writeInt(mSearchImeOptions); dest.writeInt(mIncludeInGlobalSearch ? 1 : 0); + dest.writeInt(mQueryAfterZeroResults ? 1 : 0); + dest.writeString(mSettingsDescription); dest.writeString(mSuggestAuthority); dest.writeString(mSuggestPath); dest.writeString(mSuggestSelection); diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java index 9586d56..c7cc8ed 100644 --- a/core/java/android/server/search/Searchables.java +++ b/core/java/android/server/search/Searchables.java @@ -16,49 +16,64 @@ package android.server.search; +import com.android.internal.app.ResolverActivity; +import com.android.internal.R; + import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Resources; import android.os.Bundle; +import android.util.Log; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * This class maintains the information about all searchable activities. + * This class maintains the information about all searchable activities. */ public class Searchables { + private static final String LOG_TAG = "Searchables"; + // static strings used for XML lookups, etc. - // TODO how should these be documented for the developer, in a more structured way than + // TODO how should these be documented for the developer, in a more structured way than // the current long wordy javadoc in SearchManager.java ? private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable"; private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; - + private Context mContext; - + private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; private ArrayList<SearchableInfo> mSearchablesList = null; private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null; + private ArrayList<SearchableInfo> mSearchablesForWebSearchList = null; 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. */ public Searchables (Context context) { mContext = context; } - + /** * Look up, or construct, based on the activity. - * - * The activities fall into three cases, based on meta-data found in + * + * The activities fall into three cases, based on meta-data found in * the manifest entry: * <ol> * <li>The activity itself implements search. This is indicated by the @@ -70,16 +85,16 @@ public class Searchables { * case the factory will "redirect" and return the searchable data.</li> * <li>No searchability data is provided. We return null here and other * code will insert the "default" (e.g. contacts) search. - * + * * TODO: cache the result in the map, and check the map first. * TODO: it might make sense to implement the searchable reference as * an application meta-data entry. This way we don't have to pepper each * and every activity. * TODO: can we skip the constructor step if it's a non-searchable? - * TODO: does it make sense to plug the default into a slot here for + * TODO: does it make sense to plug the default into a slot here for * automatic return? Probably not, but it's one way to do it. * - * @param activity The name of the current activity, or null if the + * @param activity The name of the current activity, or null if the * activity does not define any explicit searchable metadata. */ public SearchableInfo getSearchableInfo(ComponentName activity) { @@ -89,18 +104,18 @@ public class Searchables { result = mSearchablesMap.get(activity); if (result != null) return result; } - + // Step 2. See if the current activity references a searchable. // Note: Conceptually, this could be a while(true) loop, but there's - // no point in implementing reference chaining here and risking a loop. + // no point in implementing reference chaining here and risking a loop. // References must point directly to searchable activities. - + ActivityInfo ai = null; try { ai = mContext.getPackageManager(). getActivityInfo(activity, PackageManager.GET_META_DATA ); String refActivityName = null; - + // First look for activity-specific reference Bundle md = ai.metaData; if (md != null) { @@ -113,11 +128,11 @@ public class Searchables { refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); } } - + // Irrespective of source, if a reference was found, follow it. if (refActivityName != null) { - // An app or activity can declare that we should simply launch + // An app or activity can declare that we should simply launch // "system default search" if search is invoked. if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) { return getDefaultSearchable(); @@ -143,95 +158,212 @@ public class Searchables { } catch (PackageManager.NameNotFoundException e) { // case 3: no metadata } - + // Step 3. None found. Return null. return null; - + } - + /** * Provides the system-default search activity, which you can use * whenever getSearchableInfo() returns null; - * + * * @return Returns the system-default search activity, null if never defined */ public synchronized SearchableInfo getDefaultSearchable() { return mDefaultSearchable; } - + public synchronized boolean isDefaultSearchable(SearchableInfo searchable) { return searchable == mDefaultSearchable; } - + /** - * Builds an entire list (suitable for display) of - * activities that are searchable, by iterating the entire set of - * ACTION_SEARCH intents. - * + * Builds an entire list (suitable for display) of + * activities that are searchable, by iterating the entire set of + * ACTION_SEARCH & ACTION_WEB_SEARCH intents. + * * Also clears the hash of all activities -> searches which will * refill as the user clicks "search". - * + * * This should only be done at startup and again if we know that the * list has changed. - * + * * TODO: every activity that provides a ACTION_SEARCH intent should * also provide searchability meta-data. There are a bunch of checks here * that, if data is not found, silently skip to the next activity. This * won't help a developer trying to figure out why their activity isn't * showing up in the list, but an exception here is too rough. I would * like to find a better notification mechanism. - * + * * TODO: sort the list somehow? UI choice. */ public void buildSearchableList() { - // These will become the new values at the end of the method - HashMap<ComponentName, SearchableInfo> newSearchablesMap + HashMap<ComponentName, SearchableInfo> newSearchablesMap = new HashMap<ComponentName, SearchableInfo>(); ArrayList<SearchableInfo> newSearchablesList = new ArrayList<SearchableInfo>(); ArrayList<SearchableInfo> newSearchablesInGlobalSearchList = new ArrayList<SearchableInfo>(); + ArrayList<SearchableInfo> newSearchablesForWebSearchList + = new ArrayList<SearchableInfo>(); final PackageManager pm = mContext.getPackageManager(); - - // use intent resolver to generate list of ACTION_SEARCH receivers - List<ResolveInfo> infoList; + + // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers. + List<ResolveInfo> searchList; final Intent intent = new Intent(Intent.ACTION_SEARCH); - infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA); - + searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA); + + List<ResolveInfo> webSearchInfoList; + final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH); + webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA); + // analyze each one, generate a Searchables record, and record - if (infoList != null) { - int count = infoList.size(); + if (searchList != null || webSearchInfoList != null) { + int search_count = (searchList == null ? 0 : searchList.size()); + int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size()); + int count = search_count + web_search_count; for (int ii = 0; ii < count; ii++) { // for each component, try to find metadata - ResolveInfo info = infoList.get(ii); + ResolveInfo info = (ii < search_count) + ? searchList.get(ii) + : webSearchInfoList.get(ii - search_count); ActivityInfo ai = info.activityInfo; - SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai); - if (searchable != null) { - newSearchablesList.add(searchable); - newSearchablesMap.put(searchable.getSearchActivity(), searchable); - if (searchable.shouldIncludeInGlobalSearch()) { - newSearchablesInGlobalSearchList.add(searchable); + // Check first to avoid duplicate entries. + if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) { + SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai); + if (searchable != null) { + newSearchablesList.add(searchable); + newSearchablesMap.put(searchable.getSearchActivity(), searchable); + if (searchable.shouldIncludeInGlobalSearch()) { + newSearchablesInGlobalSearchList.add(searchable); + } } } } } - + + if (webSearchInfoList != null) { + for (int i = 0; i < webSearchInfoList.size(); ++i) { + ActivityInfo ai = webSearchInfoList.get(i).activityInfo; + ComponentName component = new ComponentName(ai.packageName, ai.name); + newSearchablesForWebSearchList.add(newSearchablesMap.get(component)); + } + } + // Find the global search provider Intent globalSearchIntent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); ComponentName globalSearchActivity = globalSearchIntent.resolveActivity(pm); SearchableInfo newDefaultSearchable = newSearchablesMap.get(globalSearchActivity); + if (newDefaultSearchable == null) { + Log.w(LOG_TAG, "No searchable info found for new default searchable activity " + + globalSearchActivity); + } + + // Find the default web search provider. + ComponentName webSearchActivity = getPreferredWebSearchActivity(); + SearchableInfo newDefaultSearchableForWebSearch = null; + if (webSearchActivity != null) { + newDefaultSearchableForWebSearch = newSearchablesMap.get(webSearchActivity); + } + if (newDefaultSearchableForWebSearch == null) { + Log.w(LOG_TAG, "No searchable info found for new default web search activity " + + webSearchActivity); + } + // Store a consistent set of new values synchronized (this) { mSearchablesMap = newSearchablesMap; mSearchablesList = newSearchablesList; mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList; + mSearchablesForWebSearchList = newSearchablesForWebSearchList; mDefaultSearchable = newDefaultSearchable; + mDefaultSearchableForWebSearch = newDefaultSearchableForWebSearch; + } + + // Inform all listeners that the list of searchables has been updated. + mContext.sendBroadcast(new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED)); + } + + /** + * Checks if the given activity component is present in the system and if so makes it the + * preferred activity for handling ACTION_WEB_SEARCH. + * @param component Name of the component to check and set as preferred. + * @param action Intent action for which this activity is to be set as preferred. + * @return true if component was detected and set as preferred activity, false if not. + */ + private boolean setPreferredActivity(ComponentName component, String action) { + Log.d(LOG_TAG, "Checking component " + component); + PackageManager pm = mContext.getPackageManager(); + ActivityInfo ai; + try { + ai = pm.getActivityInfo(component, 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + + // The code here to find the value for bestMatch is heavily inspired by the code + // in ResolverActivity where the preferred activity is set. + Intent intent = new Intent(action); + intent.addCategory(Intent.CATEGORY_DEFAULT); + List<ResolveInfo> webSearchActivities = pm.queryIntentActivities(intent, 0); + ComponentName set[] = new ComponentName[webSearchActivities.size()]; + int bestMatch = 0; + for (int i = 0; i < webSearchActivities.size(); ++i) { + ResolveInfo ri = webSearchActivities.get(i); + set[i] = new ComponentName(ri.activityInfo.packageName, + ri.activityInfo.name); + if (ri.match > bestMatch) bestMatch = ri.match; + } + + Log.d(LOG_TAG, "Setting preferred web search activity to " + component); + IntentFilter filter = new IntentFilter(action); + filter.addCategory(Intent.CATEGORY_DEFAULT); + pm.replacePreferredActivity(filter, bestMatch, set, component); + return true; + } + + public ComponentName getPreferredWebSearchActivity() { + // Check if we have a preferred web search activity. + Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); + PackageManager pm = mContext.getPackageManager(); + ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); + + if (ri == null || ri.activityInfo.name.equals(ResolverActivity.class.getName())) { + Log.d(LOG_TAG, "No preferred activity set for action web search."); + + // The components in the providers array are checked in the order of declaration so the + // first one has the highest priority. If the component exists in the system it is set + // as the preferred activity to handle intent action web search. + String[] preferredActivities = mContext.getResources().getStringArray( + com.android.internal.R.array.default_web_search_providers); + for (String componentName : preferredActivities) { + ComponentName component = ComponentName.unflattenFromString(componentName); + if (setPreferredActivity(component, Intent.ACTION_WEB_SEARCH)) { + 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; + return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); } - + /** * Returns the list of searchable activities. */ @@ -239,11 +371,33 @@ public class Searchables { ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList); return result; } - + /** * Returns a list of the searchable activities that can be included in global search. */ public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() { return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList); } + + /** + * Returns a list of the searchable activities that handle web searches. + */ + public synchronized ArrayList<SearchableInfo> getSearchablesForWebSearchList() { + return new ArrayList<SearchableInfo>(mSearchablesForWebSearchList); + } + + /** + * Returns the default searchable activity for web searches. + */ + public synchronized SearchableInfo getDefaultSearchableForWebSearch() { + return mDefaultSearchableForWebSearch; + } + + /** + * Sets the default searchable activity for web searches. + */ + public synchronized void setDefaultWebSearch(ComponentName component) { + setPreferredActivity(component, Intent.ACTION_WEB_SEARCH); + buildSearchableList(); + } } diff --git a/core/java/android/speech/IRecognitionListener.aidl b/core/java/android/speech/IRecognitionListener.aidl index 6ed32b5..2da2258 100644 --- a/core/java/android/speech/IRecognitionListener.aidl +++ b/core/java/android/speech/IRecognitionListener.aidl @@ -17,6 +17,7 @@ package android.speech; import android.os.Bundle; +import android.speech.RecognitionResult; /** * Listener for speech recognition events, used with RecognitionService. @@ -43,13 +44,17 @@ interface IRecognitionListener { /** Called after the user stops speaking. */ void onEndOfSpeech(); - /** A network or recognition error occurred. */ - void onError(in String error); + /** + * A network or recognition error occurred. The code is defined in + * {@link android.speech.RecognitionResult} + */ + void onError(in int error); /** - * Called when recognition transcripts are ready. - * results: an ordered list of the most likely transcripts (N-best list). - * @hide + * Called when recognition results are ready. + * @param results: an ordered list of the most likely results (N-best list). + * @param key: a key associated with the results. The same results can + * be retrieved asynchronously later using the key, if available. */ - void onResults(in List<String> results); + void onResults(in List<RecognitionResult> results, long key); } diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl index 36d12e9a..a18c380 100644 --- a/core/java/android/speech/IRecognitionService.aidl +++ b/core/java/android/speech/IRecognitionService.aidl @@ -18,6 +18,7 @@ package android.speech; import android.content.Intent; import android.speech.IRecognitionListener; +import android.speech.RecognitionResult; // A Service interface to speech recognition. Call startListening when // you want to begin capturing audio; RecognitionService will automatically @@ -29,6 +30,8 @@ interface IRecognitionService { // see RecognizerIntent.java for constants used to specify the intent. void startListening(in Intent recognizerIntent, in IRecognitionListener listener); + + List<RecognitionResult> getRecognitionResults(in long key); void cancel(); } diff --git a/core/java/android/speech/RecognitionResult.aidl b/core/java/android/speech/RecognitionResult.aidl new file mode 100644 index 0000000..59e53ab --- /dev/null +++ b/core/java/android/speech/RecognitionResult.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.speech; + +parcelable RecognitionResult; diff --git a/core/java/android/speech/RecognitionResult.java b/core/java/android/speech/RecognitionResult.java new file mode 100644 index 0000000..8d031fc --- /dev/null +++ b/core/java/android/speech/RecognitionResult.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package android.speech; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * RecognitionResult is a passive object that stores a single recognized + * query and its search result. + * TODO: revisit and improve. May be we should have a separate result + * object for each type, and put them (type/value) in bundle? + * + * {@hide} + */ +public class RecognitionResult implements Parcelable { + /** + * Status of the recognize request. + */ + public static final int NETWORK_TIMEOUT = 1; // Network operation timed out. + public static final int NETWORK_ERROR = 2; // Other networkrelated errors. + public static final int AUDIO_ERROR = 3; // Audio recording error. + public static final int SERVER_ERROR = 4; // Server sends error status. + public static final int CLIENT_ERROR = 5; // Other client side errors. + public static final int SPEECH_TIMEOUT = 6; // No speech input + public static final int NO_MATCH = 7; // No recognition result matched. + public static final int SERVICE_BUSY = 8; // RecognitionService busy. + + /** + * Type of the recognition results. + */ + public static final int RAW_RECOGNITION_RESULT = 0; + public static final int WEB_SEARCH_RESULT = 1; + public static final int CONTACT_RESULT = 2; + + /** + * A factory method to create a raw RecognitionResult + * + * @param sentence the recognized text. + */ + public static RecognitionResult newRawRecognitionResult(String sentence) { + return new RecognitionResult(RAW_RECOGNITION_RESULT, sentence, null, null); + } + + /** + * A factory method to create RecognitionResult for contacts. + * + * @param contact the contact name. + * @param phoneType the phone type. + */ + public static RecognitionResult newContactResult(String contact, int phoneType) { + return new RecognitionResult(CONTACT_RESULT, contact, phoneType); + } + + /** + * A factory method to create a RecognitionResult for Web Search Query. + * + * @param query the query string. + * @param html the html page of the search result. + * @param url the url that performs the search with the query. + */ + public static RecognitionResult newWebResult(String query, String html, String url) { + return new RecognitionResult(WEB_SEARCH_RESULT, query, html, url); + } + + public static final Parcelable.Creator<RecognitionResult> CREATOR + = new Parcelable.Creator<RecognitionResult>() { + + public RecognitionResult createFromParcel(Parcel in) { + return new RecognitionResult(in); + } + + public RecognitionResult[] newArray(int size) { + return new RecognitionResult[size]; + } + }; + + /** + * Result type. + */ + public final int mResultType; + + /** + * The recognized string when mResultType is WEB_SEARCH_RESULT. + * The name of the contact when mResultType is CONTACT_RESULT. + */ + public final String mText; + + /** + * The HTML result page for the query. If this is null, then the + * application must use the url field to get the HTML result page. + */ + public final String mHtml; + + /** + * The url to get the result page for the query string. The + * application must use this url instead of performing the search + * with the query. + */ + public final String mUrl; + + /** Phone number type. This is valid only when mResultType == CONTACT_RESULT */ + public final int mPhoneType; + + private RecognitionResult(int type, String query, String html, String url) { + mResultType = type; + mText = query; + mHtml = html; + mUrl = url; + mPhoneType = -1; + } + + private RecognitionResult(int type, String query, int at) { + mResultType = type; + mText = query; + mPhoneType = at; + mHtml = null; + mUrl = null; + } + + private RecognitionResult(Parcel in) { + mResultType = in.readInt(); + mText = in.readString(); + mHtml= in.readString(); + mUrl= in.readString(); + mPhoneType = in.readInt(); + } + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mResultType); + out.writeString(mText); + out.writeString(mHtml); + out.writeString(mUrl); + out.writeInt(mPhoneType); + } + + + @Override + public String toString() { + String resultType[] = { "RAW", "WEB", "CONTACT" }; + return "[type=" + resultType[mResultType] + + ", text=" + mText+ ", mUrl=" + mUrl + ", html=" + mHtml + "]"; + } + + public int describeContents() { + // no special description + return 0; + } +} diff --git a/core/java/android/speech/RecognitionServiceUtil.java b/core/java/android/speech/RecognitionServiceUtil.java index 650c0fd..a8c7868 100644 --- a/core/java/android/speech/RecognitionServiceUtil.java +++ b/core/java/android/speech/RecognitionServiceUtil.java @@ -21,6 +21,9 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteException; +import android.speech.RecognitionResult; +import android.util.Log; import java.util.List; @@ -56,6 +59,11 @@ public class RecognitionServiceUtil { public static final Intent sDefaultIntent = new Intent( RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + // Recognize request parameters + public static final String USE_LOCATION = "useLocation"; + public static final String CONTACT_AUTH_TOKEN = "contactAuthToken"; + + // Bundles public static final String NOISE_LEVEL = "NoiseLevel"; public static final String SIGNAL_NOISE_RATIO = "SignalNoiseRatio"; @@ -72,8 +80,8 @@ public class RecognitionServiceUtil { public void onRmsChanged(float rmsdB) {} public void onBufferReceived(byte[] buf) {} public void onEndOfSpeech() {} - public void onError(String error) {} - public void onResults(List<String> results) {} + public void onError(int error) {} + public void onResults(List<RecognitionResult> results, long key) {} } /** diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl new file mode 100755 index 0000000..c9a6180 --- /dev/null +++ b/core/java/android/speech/tts/ITts.aidl @@ -0,0 +1,63 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.speech.tts;
+
+import android.speech.tts.ITtsCallback;
+
+import android.content.Intent;
+
+/**
+ * AIDL for the TTS Service
+ * ITts.java is autogenerated from this.
+ *
+ * {@hide}
+ */
+interface ITts {
+ int setSpeechRate(in int speechRate);
+
+ int setPitch(in int pitch);
+
+ int speak(in String text, in int queueMode, in String[] params);
+
+ boolean isSpeaking();
+
+ int stop();
+
+ void addSpeech(in String text, in String packageName, in int resId);
+
+ void addSpeechFile(in String text, in String filename);
+
+ String[] getLanguage();
+
+ int isLanguageAvailable(in String language, in String country, in String variant);
+
+ int setLanguage(in String language, in String country, in String variant);
+
+ boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
+
+ int playEarcon(in String earcon, in int queueMode, in String[] params);
+
+ void addEarcon(in String earcon, in String packageName, in int resId);
+
+ void addEarconFile(in String earcon, in String filename);
+
+ void registerCallback(ITtsCallback cb);
+
+ void unregisterCallback(ITtsCallback cb);
+
+ int playSilence(in long duration, in int queueMode, in String[] params);
+}
diff --git a/core/java/android/speech/tts/ITtsCallback.aidl b/core/java/android/speech/tts/ITtsCallback.aidl new file mode 100755 index 0000000..48ed73e --- /dev/null +++ b/core/java/android/speech/tts/ITtsCallback.aidl @@ -0,0 +1,27 @@ +/* + * 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.speech.tts; + +/** + * AIDL for the callback from the TTS Service + * ITtsCallback.java is autogenerated from this. + * + * {@hide} + */ +oneway interface ITtsCallback { + void markReached(String mark); +} diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java new file mode 100644 index 0000000..616b3f1 --- /dev/null +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -0,0 +1,719 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package android.speech.tts; + +import android.speech.tts.ITts; +import android.speech.tts.ITtsCallback; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.HashMap; +import java.util.Locale; + +/** + * + * Synthesizes speech from text for immediate playback or to create a sound file. + * + */ +//TODO complete javadoc + add links to constants +public class TextToSpeech { + + /** + * Denotes a successful operation. + */ + public static final int TTS_SUCCESS = 0; + /** + * Denotes a generic operation failure. + */ + public static final int TTS_ERROR = -1; + + /** + * Queue mode where all entries in the playback queue (media to be played + * and text to be synthesized) are dropped and replaced by the new entry. + */ + public static final int TTS_QUEUE_FLUSH = 0; + /** + * Queue mode where the new entry is added at the end of the playback queue. + */ + public static final int TTS_QUEUE_ADD = 1; + + + /** + * Denotes the language is available exactly as specified by the locale + */ + public static final int TTS_LANG_COUNTRY_VAR_AVAILABLE = 2; + + + /** + * Denotes the language is available for the language and country specified + * by the locale, but not the variant. + */ + public static final int TTS_LANG_COUNTRY_AVAILABLE = 1; + + + /** + * Denotes the language is available for the language by the locale, + * but not the country and variant. + */ + public static final int TTS_LANG_AVAILABLE = 0; + + /** + * Denotes the language data is missing. + */ + public static final int TTS_LANG_MISSING_DATA = -1; + + /** + * Denotes the language is not supported by the current TTS engine. + */ + public static final int TTS_LANG_NOT_SUPPORTED = -2; + + + /** + * Called when the TTS has initialized. + * + * The InitListener must implement the onInit function. onInit is passed a + * status code indicating the result of the TTS initialization. + */ + public interface OnInitListener { + public void onInit(int status); + } + + /** + * Internal constants for the TTS functionality + * + * {@hide} + */ + public class Engine { + // default values for a TTS engine when settings are not found in the provider + public static final int FALLBACK_TTS_DEFAULT_RATE = 100; // 1x + public static final int FALLBACK_TTS_DEFAULT_PITCH = 100;// 1x + public static final int FALLBACK_TTS_USE_DEFAULTS = 0; // false + public static final String FALLBACK_TTS_DEFAULT_LANG = "eng"; + public static final String FALLBACK_TTS_DEFAULT_COUNTRY = ""; + public static final String FALLBACK_TTS_DEFAULT_VARIANT = ""; + + // return codes for a TTS engine's check data activity + public static final int CHECK_VOICE_DATA_PASS = 1; + public static final int CHECK_VOICE_DATA_FAIL = 0; + public static final int CHECK_VOICE_DATA_BAD_DATA = -1; + public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; + public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3; + + // return codes for a TTS engine's check data activity + public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; + public static final String VOICE_DATA_FILES = "dataFiles"; + public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo"; + + // keys for the parameters passed with speak commands + public static final String TTS_KEY_PARAM_RATE = "rate"; + public static final String TTS_KEY_PARAM_LANGUAGE = "language"; + public static final String TTS_KEY_PARAM_COUNTRY = "country"; + public static final String TTS_KEY_PARAM_VARIANT = "variant"; + public static final int TTS_PARAM_POSITION_RATE = 0; + public static final int TTS_PARAM_POSITION_LANGUAGE = 2; + public static final int TTS_PARAM_POSITION_COUNTRY = 4; + public static final int TTS_PARAM_POSITION_VARIANT = 6; + } + + /** + * Connection needed for the TTS. + */ + private ServiceConnection mServiceConnection; + + private ITts mITts = null; + private Context mContext = null; + private OnInitListener mInitListener = null; + private boolean mStarted = false; + private final Object mStartLock = new Object(); + /** + * Used to store the cached parameters sent along with each synthesis request to the + * TTS service. + */ + private String[] mCachedParams; + + /** + * The constructor for the TTS. + * + * @param context + * The context + * @param listener + * The InitListener that will be called when the TTS has + * initialized successfully. + */ + public TextToSpeech(Context context, OnInitListener listener) { + mContext = context; + mInitListener = listener; + + mCachedParams = new String[2*4]; // 4 parameters, store key and value + mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE; + mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE; + mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY; + mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT; + + mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = + String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE); + // initialize the language cached parameters with the current Locale + Locale defaultLoc = Locale.getDefault(); + mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language(); + mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country(); + mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant(); + + initTts(); + } + + + private void initTts() { + mStarted = false; + + // Initialize the TTS, run the callback after the binding is successful + mServiceConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized(mStartLock) { + mITts = ITts.Stub.asInterface(service); + mStarted = true; + if (mInitListener != null) { + // TODO manage failures and missing resources + mInitListener.onInit(TTS_SUCCESS); + } + } + } + + public void onServiceDisconnected(ComponentName name) { + synchronized(mStartLock) { + mITts = null; + mInitListener = null; + mStarted = false; + } + } + }; + + Intent intent = new Intent("android.intent.action.START_TTS_SERVICE"); + intent.addCategory("android.intent.category.TTS"); + mContext.bindService(intent, mServiceConnection, + Context.BIND_AUTO_CREATE); + // TODO handle case where the binding works (should always work) but + // the plugin fails + } + + + /** + * Shuts down the TTS. It is good practice to call this in the onDestroy + * method of the Activity that is using the TTS so that the TTS is stopped + * cleanly. + */ + public void shutdown() { + try { + mContext.unbindService(mServiceConnection); + } catch (IllegalArgumentException e) { + // Do nothing and fail silently since an error here indicates that + // binding never succeeded in the first place. + } + } + + + /** + * Adds a mapping between a string of text and a sound resource in a + * package. + * + * @see #TTS.speak(String text, int queueMode, String[] params) + * + * @param text + * Example: <b><code>"south_south_east"</code></b><br/> + * + * @param packagename + * Pass the packagename of the application that contains the + * resource. If the resource is in your own application (this is + * the most common case), then put the packagename of your + * application here.<br/> + * Example: <b>"com.google.marvin.compass"</b><br/> + * The packagename can be found in the AndroidManifest.xml of + * your application. + * <p> + * <code><manifest xmlns:android="..." + * package="<b>com.google.marvin.compass</b>"></code> + * </p> + * + * @param resourceId + * Example: <b><code>R.raw.south_south_east</code></b> + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int addSpeech(String text, String packagename, int resourceId) { + synchronized(mStartLock) { + if (!mStarted) { + return TTS_ERROR; + } + try { + mITts.addSpeech(text, packagename, resourceId); + return TTS_SUCCESS; + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } + return TTS_ERROR; + } + } + + + /** + * Adds a mapping between a string of text and a sound file. Using this, it + * is possible to add custom pronounciations for text. + * + * @param text + * The string of text + * @param filename + * The full path to the sound file (for example: + * "/sdcard/mysounds/hello.wav") + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int addSpeech(String text, String filename) { + synchronized (mStartLock) { + if (!mStarted) { + return TTS_ERROR; + } + try { + mITts.addSpeechFile(text, filename); + return TTS_SUCCESS; + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } + return TTS_ERROR; + } + } + + + /** + * Speaks the string using the specified queuing strategy and speech + * parameters. Note that the speech parameters are not universally supported + * by all engines and will be treated as a hint. The TTS library will try to + * fulfill these parameters as much as possible, but there is no guarantee + * that the voice used will have the properties specified. + * + * @param text + * The string of text to be spoken. + * @param queueMode + * The queuing strategy to use. + * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. + * @param params + * The hashmap of speech parameters to be used. + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int speak(String text, int queueMode, HashMap<String,String> params) + { + synchronized (mStartLock) { + int result = TTS_ERROR; + Log.i("TTS received: ", text); + if (!mStarted) { + return result; + } + try { + // TODO support extra parameters, passing cache of current parameters for the moment + result = mITts.speak(text, queueMode, mCachedParams); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Plays the earcon using the specified queueing mode and parameters. + * + * @param earcon + * The earcon that should be played + * @param queueMode + * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. + * @param params + * The hashmap of parameters to be used. + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int playEarcon(String earcon, int queueMode, + HashMap<String,String> params) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + // TODO support extra parameters, passing null for the moment + result = mITts.playEarcon(earcon, queueMode, null); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + /** + * Plays silence for the specified amount of time using the specified + * queue mode. + * + * @param durationInMs + * A long that indicates how long the silence should last. + * @param queueMode + * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int playSilence(long durationInMs, int queueMode) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + // TODO support extra parameters, passing cache of current parameters for the moment + result = mITts.playSilence(durationInMs, queueMode, mCachedParams); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Returns whether or not the TTS is busy speaking. + * + * @return Whether or not the TTS is busy speaking. + */ + public boolean isSpeaking() { + synchronized (mStartLock) { + if (!mStarted) { + return false; + } + try { + return mITts.isSpeaking(); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } + return false; + } + } + + + /** + * Stops speech from the TTS. + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int stop() { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + result = mITts.stop(); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Sets the speech rate for the TTS engine. + * + * Note that the speech rate is not universally supported by all engines and + * will be treated as a hint. The TTS library will try to use the specified + * speech rate, but there is no guarantee. + * This has no effect on any pre-recorded speech. + * + * @param speechRate + * The speech rate for the TTS engine. 1 is the normal speed, + * lower values slow down the speech (0.5 is half the normal speech rate), + * greater values accelerate it (2 is twice the normal speech rate). + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int setSpeechRate(float speechRate) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + if (speechRate > 0) { + int rate = (int)(speechRate*100); + mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(rate); + result = mITts.setSpeechRate(rate); + } + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * 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. + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int setPitch(float pitch) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + if (pitch > 0) { + result = mITts.setPitch((int)(pitch*100)); + } + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Sets the language for the TTS engine. + * + * Note that the language is not universally supported by all engines and + * will be treated as a hint. The TTS library will try to use the specified + * language as represented by the Locale, but there is no guarantee. + * + * @param loc + * The locale describing the language to be used. + * + * @return Code indicating the support status for the locale. See the TTS_LANG_ codes. + */ + public int setLanguage(Locale loc) { + synchronized (mStartLock) { + int result = TTS_LANG_NOT_SUPPORTED; + if (!mStarted) { + return result; + } + try { + mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language(); + mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country(); + mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant(); + result = mITts.setLanguage(mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1], + mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1], + mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] ); + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Returns a Locale instance describing the language currently being used by the TTS engine. + * @return language, country (if any) and variant (if any) used by the engine stored in a Locale + * instance, or null is the TTS engine has failed. + */ + public Locale getLanguage() { + synchronized (mStartLock) { + if (!mStarted) { + return null; + } + try { + String[] locStrings = mITts.getLanguage(); + if (locStrings.length == 3) { + return new Locale(locStrings[0], locStrings[1], locStrings[2]); + } else { + return null; + } + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } + return null; + } + } + + /** + * Checks if the specified language as represented by the Locale is available. + * + * @param loc + * The Locale describing the language to be used. + * + * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE, + * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE. + */ + public int isLanguageAvailable(Locale loc) { + synchronized (mStartLock) { + int result = TTS_LANG_NOT_SUPPORTED; + if (!mStarted) { + return result; + } + try { + result = mITts.isLanguageAvailable(loc.getISO3Language(), + loc.getISO3Country(), loc.getVariant()); + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + + + /** + * Synthesizes the given text to a file using the specified parameters. + * + * @param text + * The String of text that should be synthesized + * @param params + * A hashmap of parameters. + * @param filename + * The string that gives the full output filename; it should be + * something like "/sdcard/myappsounds/mysound.wav". + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int synthesizeToFile(String text, HashMap<String,String> params, + String filename) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + try { + // TODO support extra parameters, passing null for the moment + if (mITts.synthesizeToFile(text, null, filename)){ + result = TTS_SUCCESS; + } + } catch (RemoteException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + +} diff --git a/core/java/android/syncml/pim/PropertyNode.java b/core/java/android/syncml/pim/PropertyNode.java index cc52499..983ecb8 100644 --- a/core/java/android/syncml/pim/PropertyNode.java +++ b/core/java/android/syncml/pim/PropertyNode.java @@ -17,12 +17,16 @@ package android.syncml.pim; import android.content.ContentValues; -import android.util.Log; +import org.apache.commons.codec.binary.Base64; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.Map.Entry; +import java.util.regex.Pattern; public class PropertyNode { @@ -52,7 +56,9 @@ public class PropertyNode { public Set<String> propGroupSet; public PropertyNode() { + propName = ""; propValue = ""; + propValue_vector = new ArrayList<String>(); paramMap = new ContentValues(); paramMap_TYPE = new HashSet<String>(); propGroupSet = new HashSet<String>(); @@ -62,13 +68,21 @@ public class PropertyNode { String propName, String propValue, List<String> propValue_vector, byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE, Set<String> propGroupSet) { - this.propName = propName; + if (propName != null) { + this.propName = propName; + } else { + this.propName = ""; + } if (propValue != null) { this.propValue = propValue; } else { this.propValue = ""; } - this.propValue_vector = propValue_vector; + if (propValue_vector != null) { + this.propValue_vector = propValue_vector; + } else { + this.propValue_vector = new ArrayList<String>(); + } this.propValue_bytes = propValue_bytes; if (paramMap != null) { this.paramMap = paramMap; @@ -117,17 +131,9 @@ public class PropertyNode { // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector // is 1, the encoded value is stored in propValue, so we do not have to // check it. - if (propValue_vector != null) { - // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector); - return (propValue_vector.equals(node.propValue_vector) || - (propValue_vector.size() == 1)); - } else if (node.propValue_vector != null) { - // Log.d("@@@", "===" + propValue_vector + ", " + node.propValue_vector); - return (node.propValue_vector.equals(propValue_vector) || - (node.propValue_vector.size() == 1)); - } else { - return true; - } + return (propValue_vector.equals(node.propValue_vector) || + propValue_vector.size() == 1 || + node.propValue_vector.size() == 1); } } @@ -154,4 +160,164 @@ public class PropertyNode { builder.append(propValue); return builder.toString(); } + + /** + * Encode this object into a string which can be decoded. + */ + public String encode() { + // PropertyNode#toString() is for reading, not for parsing in the future. + // We construct appropriate String here. + StringBuilder builder = new StringBuilder(); + if (propName.length() > 0) { + builder.append("propName:["); + builder.append(propName); + builder.append("],"); + } + int size = propGroupSet.size(); + if (size > 0) { + Set<String> set = propGroupSet; + builder.append("propGroup:["); + int i = 0; + for (String group : set) { + // We do not need to double quote groups. + // group = 1*(ALPHA / DIGIT / "-") + builder.append(group); + if (i < size - 1) { + builder.append(","); + } + i++; + } + builder.append("],"); + } + + if (paramMap.size() > 0 || paramMap_TYPE.size() > 0) { + ContentValues values = paramMap; + builder.append("paramMap:["); + size = paramMap.size(); + int i = 0; + for (Entry<String, Object> entry : values.valueSet()) { + // Assuming param-key does not contain NON-ASCII nor symbols. + // + // According to vCard 3.0: + // param-name = iana-token / x-name + builder.append(entry.getKey()); + + // param-value may contain any value including NON-ASCIIs. + // We use the following replacing rule. + // \ -> \\ + // , -> \, + // In String#replaceAll(), "\\\\" means a single backslash. + builder.append("="); + builder.append(entry.getValue().toString() + .replaceAll("\\\\", "\\\\\\\\") + .replaceAll(",", "\\\\,")); + if (i < size -1) { + builder.append(","); + } + i++; + } + + Set<String> set = paramMap_TYPE; + size = paramMap_TYPE.size(); + if (i > 0 && size > 0) { + builder.append(","); + } + i = 0; + for (String type : set) { + builder.append("TYPE="); + builder.append(type + .replaceAll("\\\\", "\\\\\\\\") + .replaceAll(",", "\\\\,")); + if (i < size - 1) { + builder.append(","); + } + i++; + } + builder.append("],"); + } + + size = propValue_vector.size(); + if (size > 0) { + builder.append("propValue:["); + List<String> list = propValue_vector; + for (int i = 0; i < size; i++) { + builder.append(list.get(i) + .replaceAll("\\\\", "\\\\\\\\") + .replaceAll(",", "\\\\,")); + if (i < size -1) { + builder.append(","); + } + } + builder.append("],"); + } + + return builder.toString(); + } + + public static PropertyNode decode(String encodedString) { + PropertyNode propertyNode = new PropertyNode(); + String trimed = encodedString.trim(); + if (trimed.length() == 0) { + return propertyNode; + } + String[] elems = trimed.split("],"); + + for (String elem : elems) { + int index = elem.indexOf('['); + String name = elem.substring(0, index - 1); + Pattern pattern = Pattern.compile("(?<!\\\\),"); + String[] values = pattern.split(elem.substring(index + 1), -1); + if (name.equals("propName")) { + propertyNode.propName = values[0]; + } else if (name.equals("propGroupSet")) { + for (String value : values) { + propertyNode.propGroupSet.add(value); + } + } else if (name.equals("paramMap")) { + ContentValues paramMap = propertyNode.paramMap; + Set<String> paramMap_TYPE = propertyNode.paramMap_TYPE; + for (String value : values) { + String[] tmp = value.split("=", 2); + String mapKey = tmp[0]; + // \, -> , + // \\ -> \ + // In String#replaceAll(), "\\\\" means a single backslash. + String mapValue = + tmp[1].replaceAll("\\\\,", ",").replaceAll("\\\\\\\\", "\\\\"); + if (mapKey.equalsIgnoreCase("TYPE")) { + paramMap_TYPE.add(mapValue); + } else { + paramMap.put(mapKey, mapValue); + } + } + } else if (name.equals("propValue")) { + StringBuilder builder = new StringBuilder(); + List<String> list = propertyNode.propValue_vector; + int length = values.length; + for (int i = 0; i < length; i++) { + String normValue = values[i] + .replaceAll("\\\\,", ",") + .replaceAll("\\\\\\\\", "\\\\"); + list.add(normValue); + builder.append(normValue); + if (i < length - 1) { + builder.append(";"); + } + } + propertyNode.propValue = builder.toString(); + } + } + + // At this time, QUOTED-PRINTABLE is already decoded to Java String. + // We just need to decode BASE64 String to binary. + String encoding = propertyNode.paramMap.getAsString("ENCODING"); + if (encoding != null && + (encoding.equalsIgnoreCase("BASE64") || + encoding.equalsIgnoreCase("B"))) { + propertyNode.propValue_bytes = + Base64.decodeBase64(propertyNode.propValue_vector.get(0).getBytes()); + } + + return propertyNode; + } } diff --git a/core/java/android/syncml/pim/VBuilderCollection.java b/core/java/android/syncml/pim/VBuilderCollection.java new file mode 100644 index 0000000..f09c1c4 --- /dev/null +++ b/core/java/android/syncml/pim/VBuilderCollection.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.syncml.pim; + +import java.util.Collection; +import java.util.List; + +public class VBuilderCollection implements VBuilder { + + private final Collection<VBuilder> mVBuilderCollection; + + public VBuilderCollection(Collection<VBuilder> vBuilderCollection) { + mVBuilderCollection = vBuilderCollection; + } + + public Collection<VBuilder> getVBuilderCollection() { + return mVBuilderCollection; + } + + public void start() { + for (VBuilder builder : mVBuilderCollection) { + builder.start(); + } + } + + public void end() { + for (VBuilder builder : mVBuilderCollection) { + builder.end(); + } + } + + public void startRecord(String type) { + for (VBuilder builder : mVBuilderCollection) { + builder.startRecord(type); + } + } + + public void endRecord() { + for (VBuilder builder : mVBuilderCollection) { + builder.endRecord(); + } + } + + public void startProperty() { + for (VBuilder builder : mVBuilderCollection) { + builder.startProperty(); + } + } + + + public void endProperty() { + for (VBuilder builder : mVBuilderCollection) { + builder.endProperty(); + } + } + + public void propertyGroup(String group) { + for (VBuilder builder : mVBuilderCollection) { + builder.propertyGroup(group); + } + } + + public void propertyName(String name) { + for (VBuilder builder : mVBuilderCollection) { + builder.propertyName(name); + } + } + + public void propertyParamType(String type) { + for (VBuilder builder : mVBuilderCollection) { + builder.propertyParamType(type); + } + } + + public void propertyParamValue(String value) { + for (VBuilder builder : mVBuilderCollection) { + builder.propertyParamValue(value); + } + } + + public void propertyValues(List<String> values) { + for (VBuilder builder : mVBuilderCollection) { + builder.propertyValues(values); + } + } +} diff --git a/core/java/android/syncml/pim/VDataBuilder.java b/core/java/android/syncml/pim/VDataBuilder.java index 8c67cf5..f6e5b65 100644 --- a/core/java/android/syncml/pim/VDataBuilder.java +++ b/core/java/android/syncml/pim/VDataBuilder.java @@ -17,8 +17,10 @@ package android.syncml.pim; import android.content.ContentValues; +import android.util.CharsetUtils; import android.util.Log; +import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.net.QuotedPrintableCodec; @@ -26,9 +28,7 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Vector; /** * Store the parse result to custom datastruct: VNode, PropertyNode @@ -38,7 +38,13 @@ import java.util.Vector; */ public class VDataBuilder implements VBuilder { static private String LOG_TAG = "VDATABuilder"; - + + /** + * If there's no other information available, this class uses this charset for encoding + * byte arrays. + */ + static public String DEFAULT_CHARSET = "UTF-8"; + /** type=VNode */ public List<VNode> vNodeList = new ArrayList<VNode>(); private int mNodeListPos = 0; @@ -47,34 +53,74 @@ public class VDataBuilder implements VBuilder { private String mCurrentParamType; /** - * Assumes that each String can be encoded into byte array using this encoding. + * The charset using which VParser parses the text. + */ + private String mSourceCharset; + + /** + * The charset with which byte array is encoded to String. */ - private String mCharset; + private String mTargetCharset; private boolean mStrictLineBreakParsing; public VDataBuilder() { - mCharset = "ISO-8859-1"; - mStrictLineBreakParsing = false; + this(VParser.DEFAULT_CHARSET, DEFAULT_CHARSET, false); } - public VDataBuilder(String encoding, boolean strictLineBreakParsing) { - mCharset = encoding; - mStrictLineBreakParsing = strictLineBreakParsing; + public VDataBuilder(String charset, boolean strictLineBreakParsing) { + this(null, charset, strictLineBreakParsing); } + /** + * @hide sourceCharset is temporal. + */ + public VDataBuilder(String sourceCharset, String targetCharset, + boolean strictLineBreakParsing) { + if (sourceCharset != null) { + mSourceCharset = sourceCharset; + } else { + mSourceCharset = VParser.DEFAULT_CHARSET; + } + if (targetCharset != null) { + mTargetCharset = targetCharset; + } else { + mTargetCharset = DEFAULT_CHARSET; + } + mStrictLineBreakParsing = strictLineBreakParsing; + } + public void start() { } public void end() { } + // Note: I guess that this code assumes the Record may nest like this: + // START:VPOS + // ... + // START:VPOS2 + // ... + // END:VPOS2 + // ... + // END:VPOS + // + // However the following code has a bug. + // When error occurs after calling startRecord(), the entry which is probably + // the cause of the error remains to be in vNodeList, while endRecord() is not called. + // + // I leave this code as is since I'm not familiar with vcalendar specification. + // But I believe we should refactor this code in the future. + // Until this, the last entry has to be removed when some error occurs. public void startRecord(String type) { + VNode vnode = new VNode(); vnode.parseStatus = 1; vnode.VName = type; + // I feel this should be done in endRecord(), but it cannot be done because of + // the reason above. vNodeList.add(vnode); - mNodeListPos = vNodeList.size()-1; + mNodeListPos = vNodeList.size() - 1; mCurrentVNode = vNodeList.get(mNodeListPos); } @@ -90,15 +136,14 @@ public class VDataBuilder implements VBuilder { } public void startProperty() { - // System.out.println("+ startProperty. "); + mCurrentPropNode = new PropertyNode(); } public void endProperty() { - // System.out.println("- endProperty. "); + mCurrentVNode.propList.add(mCurrentPropNode); } public void propertyName(String name) { - mCurrentPropNode = new PropertyNode(); mCurrentPropNode.propName = name; } @@ -122,139 +167,145 @@ public class VDataBuilder implements VBuilder { mCurrentParamType = null; } - private String encodeString(String originalString, String targetEncoding) { - Charset charset = Charset.forName(mCharset); + private String encodeString(String originalString, String targetCharset) { + if (mSourceCharset.equalsIgnoreCase(targetCharset)) { + return originalString; + } + Charset charset = Charset.forName(mSourceCharset); ByteBuffer byteBuffer = charset.encode(originalString); // byteBuffer.array() "may" return byte array which is larger than // byteBuffer.remaining(). Here, we keep on the safe side. byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); try { - return new String(bytes, targetEncoding); + return new String(bytes, targetCharset); } catch (UnsupportedEncodingException e) { - return null; + Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); + return new String(bytes); } } - public void propertyValues(List<String> values) { - ContentValues paramMap = mCurrentPropNode.paramMap; - - String charsetString = paramMap.getAsString("CHARSET"); - - boolean setupParamValues = false; - //decode value string to propValue_bytes - if (paramMap.containsKey("ENCODING")) { - String encoding = paramMap.getAsString("ENCODING"); - if (encoding.equalsIgnoreCase("BASE64") || - encoding.equalsIgnoreCase("B")) { - if (values.size() > 1) { - Log.e(LOG_TAG, - ("BASE64 encoding is used while " + - "there are multiple values (" + values.size())); - } + private String handleOneValue(String value, String targetCharset, String encoding) { + if (encoding != null) { + if (encoding.equals("BASE64") || encoding.equals("B")) { + // Assume BASE64 is used only when the number of values is 1. mCurrentPropNode.propValue_bytes = - Base64.decodeBase64(values.get(0). - replaceAll(" ","").replaceAll("\t",""). - replaceAll("\r\n",""). - getBytes()); - } - - if(encoding.equalsIgnoreCase("QUOTED-PRINTABLE")){ - // if CHARSET is defined, we translate each String into the Charset. - List<String> tmpValues = new ArrayList<String>(); - Vector<byte[]> byteVector = new Vector<byte[]>(); - int size = 0; - try{ - for (String value : values) { - String quotedPrintable = value - .replaceAll("= ", " ").replaceAll("=\t", "\t"); - String[] lines; - if (mStrictLineBreakParsing) { - lines = quotedPrintable.split("\r\n"); - } else { - lines = quotedPrintable - .replace("\r\n", "\n").replace("\r", "\n").split("\n"); - } - StringBuilder builder = new StringBuilder(); - for (String line : lines) { - if (line.endsWith("=")) { - line = line.substring(0, line.length() - 1); - } - builder.append(line); - } - byte[] bytes = QuotedPrintableCodec.decodeQuotedPrintable( - builder.toString().getBytes()); - if (charsetString != null) { - try { - tmpValues.add(new String(bytes, charsetString)); - } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString); - tmpValues.add(new String(bytes)); + Base64.decodeBase64(value.getBytes()); + return value; + } else if (encoding.equals("QUOTED-PRINTABLE")) { + String quotedPrintable = value + .replaceAll("= ", " ").replaceAll("=\t", "\t"); + String[] lines; + if (mStrictLineBreakParsing) { + lines = quotedPrintable.split("\r\n"); + } else { + StringBuilder builder = new StringBuilder(); + int length = quotedPrintable.length(); + ArrayList<String> list = new ArrayList<String>(); + for (int i = 0; i < length; i++) { + char ch = quotedPrintable.charAt(i); + if (ch == '\n') { + list.add(builder.toString()); + builder = new StringBuilder(); + } else if (ch == '\r') { + list.add(builder.toString()); + builder = new StringBuilder(); + if (i < length - 1) { + char nextCh = quotedPrintable.charAt(i + 1); + if (nextCh == '\n') { + i++; + } } } else { - tmpValues.add(new String(bytes)); - } - byteVector.add(bytes); - size += bytes.length; - } // for (String value : values) { - mCurrentPropNode.propValue_vector = tmpValues; - mCurrentPropNode.propValue = listToString(tmpValues); - - mCurrentPropNode.propValue_bytes = new byte[size]; - - { - byte[] tmpBytes = mCurrentPropNode.propValue_bytes; - int index = 0; - for (byte[] bytes : byteVector) { - int length = bytes.length; - for (int i = 0; i < length; i++, index++) { - tmpBytes[index] = bytes[i]; - } + builder.append(ch); } } - setupParamValues = true; - } catch(Exception e) { - Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e); + String finalLine = builder.toString(); + if (finalLine.length() > 0) { + list.add(finalLine); + } + lines = list.toArray(new String[0]); } - } // QUOTED-PRINTABLE - } // ENCODING - - if (!setupParamValues) { - // if CHARSET is defined, we translate each String into the Charset. - if (charsetString != null) { - List<String> tmpValues = new ArrayList<String>(); - for (String value : values) { - String result = encodeString(value, charsetString); - if (result != null) { - tmpValues.add(result); - } else { - Log.e(LOG_TAG, "Failed to encode: charset=" + charsetString); - tmpValues.add(value); + StringBuilder builder = new StringBuilder(); + for (String line : lines) { + if (line.endsWith("=")) { + line = line.substring(0, line.length() - 1); } + builder.append(line); + } + byte[] bytes; + try { + bytes = builder.toString().getBytes(mSourceCharset); + } catch (UnsupportedEncodingException e1) { + Log.e(LOG_TAG, "Failed to encode: charset=" + mSourceCharset); + bytes = builder.toString().getBytes(); + } + + try { + bytes = QuotedPrintableCodec.decodeQuotedPrintable(bytes); + } catch (DecoderException e) { + Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e); + return ""; + } + + try { + return new String(bytes, targetCharset); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); + return new String(bytes); } - values = tmpValues; } - - mCurrentPropNode.propValue_vector = values; - mCurrentPropNode.propValue = listToString(values); + // Unknown encoding. Fall back to default. } - mCurrentVNode.propList.add(mCurrentPropNode); + return encodeString(value, targetCharset); } - - private String listToString(Collection<String> list){ - StringBuilder typeListB = new StringBuilder(); - for (String type : list) { - typeListB.append(type).append(";"); + + public void propertyValues(List<String> values) { + if (values == null || values.size() == 0) { + mCurrentPropNode.propValue_bytes = null; + mCurrentPropNode.propValue_vector.clear(); + mCurrentPropNode.propValue_vector.add(""); + mCurrentPropNode.propValue = ""; + return; + } + + ContentValues paramMap = mCurrentPropNode.paramMap; + + String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET")); + String encoding = paramMap.getAsString("ENCODING"); + + if (targetCharset == null || targetCharset.length() == 0) { + targetCharset = mTargetCharset; + } + + for (String value : values) { + mCurrentPropNode.propValue_vector.add( + handleOneValue(value, targetCharset, encoding)); } - int len = typeListB.length(); - if (len > 0 && typeListB.charAt(len - 1) == ';') { - return typeListB.substring(0, len - 1); + + mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector); + } + + private String listToString(List<String> list){ + int size = list.size(); + if (size > 1) { + StringBuilder typeListB = new StringBuilder(); + for (String type : list) { + typeListB.append(type).append(";"); + } + int len = typeListB.length(); + if (len > 0 && typeListB.charAt(len - 1) == ';') { + return typeListB.substring(0, len - 1); + } + return typeListB.toString(); + } else if (size == 1) { + return list.get(0); + } else { + return ""; } - return typeListB.toString(); } public String getResult(){ return null; } } - diff --git a/core/java/android/syncml/pim/VParser.java b/core/java/android/syncml/pim/VParser.java index df93f38..57c5f7a 100644 --- a/core/java/android/syncml/pim/VParser.java +++ b/core/java/android/syncml/pim/VParser.java @@ -26,6 +26,9 @@ import java.io.UnsupportedEncodingException; * */ abstract public class VParser { + // Assume that "iso-8859-1" is able to map "all" 8bit characters to some unicode and + // decode the unicode to the original charset. If not, this setting will cause some bug. + public static String DEFAULT_CHARSET = "iso-8859-1"; /** * The buffer used to store input stream @@ -96,6 +99,20 @@ abstract public class VParser { } /** + * Parse the given stream with the default encoding. + * + * @param is + * The source to parse. + * @param builder + * The v builder which used to construct data. + * @return Return true for success, otherwise false. + * @throws IOException + */ + public boolean parse(InputStream is, VBuilder builder) throws IOException { + return parse(is, DEFAULT_CHARSET, builder); + } + + /** * Copy the content of input stream and filter the "folding" */ protected void setInputStream(InputStream is, String encoding) diff --git a/core/java/android/syncml/pim/vcard/ContactStruct.java b/core/java/android/syncml/pim/vcard/ContactStruct.java index 8d9b7fa..ecd719d 100644 --- a/core/java/android/syncml/pim/vcard/ContactStruct.java +++ b/core/java/android/syncml/pim/vcard/ContactStruct.java @@ -16,45 +16,103 @@ package android.syncml.pim.vcard; -import java.util.List; +import android.content.AbstractSyncableContentProvider; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.net.Uri; +import android.provider.Contacts; +import android.provider.Contacts.ContactMethods; +import android.provider.Contacts.Extensions; +import android.provider.Contacts.GroupMembership; +import android.provider.Contacts.Organizations; +import android.provider.Contacts.People; +import android.provider.Contacts.Phones; +import android.provider.Contacts.Photos; +import android.syncml.pim.PropertyNode; +import android.syncml.pim.VNode; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; +import android.util.Log; + import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; /** - * The parameter class of VCardCreator. + * The parameter class of VCardComposer. * This class standy by the person-contact in * Android system, we must use this class instance as parameter to transmit to - * VCardCreator so that create vCard string. + * VCardComposer so that create vCard string. */ // TODO: rename the class name, next step public class ContactStruct { - public String company; + private static final String LOG_TAG = "ContactStruct"; + + // Note: phonetic name probably should be "LAST FIRST MIDDLE" for European languages, and + // space should be added between each element while it should not be in Japanese. + // But unfortunately, we currently do not have the data and are not sure whether we should + // support European version of name ordering. + // + // TODO: Implement the logic described above if we really need European version of + // phonetic name handling. Also, adding the appropriate test case of vCard would be + // highly appreciated. + public static final int NAME_ORDER_TYPE_ENGLISH = 0; + public static final int NAME_ORDER_TYPE_JAPANESE = 1; + /** MUST exist */ public String name; + public String phoneticName; /** maybe folding */ - public String notes; + public List<String> notes = new ArrayList<String>(); /** maybe folding */ public String title; /** binary bytes of pic. */ public byte[] photoBytes; - /** mime_type col of images table */ + /** The type of Photo (e.g. JPEG, BMP, etc.) */ public String photoType; /** Only for GET. Use addPhoneList() to PUT. */ public List<PhoneData> phoneList; /** Only for GET. Use addContactmethodList() to PUT. */ public List<ContactMethod> contactmethodList; + /** Only for GET. Use addOrgList() to PUT. */ + public List<OrganizationData> organizationList; + /** Only for GET. Use addExtension() to PUT */ + public Map<String, List<String>> extensionMap; - public static class PhoneData{ + // Use organizationList instead when handling ORG. + @Deprecated + public String company; + + public static class PhoneData { + public int type; /** maybe folding */ public String data; - public String type; public String label; + public boolean isPrimary; } - public static class ContactMethod{ - public String kind; - public String type; + public static class ContactMethod { + // Contacts.KIND_EMAIL, Contacts.KIND_POSTAL + public int kind; + // e.g. Contacts.ContactMethods.TYPE_HOME, Contacts.PhoneColumns.TYPE_HOME + // If type == Contacts.PhoneColumns.TYPE_CUSTOM, label is used. + public int type; public String data; + // Used only when TYPE is TYPE_CUSTOM. public String label; + public boolean isPrimary; + } + + public static class OrganizationData { + public int type; + public String companyName; + public String positionName; + public boolean isPrimary; } /** @@ -63,29 +121,858 @@ public class ContactStruct { * @param type type col of content://contacts/phones * @param label lable col of content://contacts/phones */ - public void addPhone(String data, String type, String label){ - if(phoneList == null) + public void addPhone(int type, String data, String label, boolean isPrimary){ + if (phoneList == null) { phoneList = new ArrayList<PhoneData>(); - PhoneData st = new PhoneData(); - st.data = data; - st.type = type; - st.label = label; - phoneList.add(st); + } + PhoneData phoneData = new PhoneData(); + phoneData.type = type; + + StringBuilder builder = new StringBuilder(); + String trimed = data.trim(); + int length = trimed.length(); + for (int i = 0; i < length; i++) { + char ch = trimed.charAt(i); + if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) { + builder.append(ch); + } + } + phoneData.data = PhoneNumberUtils.formatNumber(builder.toString()); + phoneData.label = label; + phoneData.isPrimary = isPrimary; + phoneList.add(phoneData); } + /** * Add a contactmethod info to contactmethodList. - * @param data contact data + * @param kind integer value defined in Contacts.java + * (e.g. Contacts.KIND_EMAIL) * @param type type col of content://contacts/contact_methods + * @param data contact data + * @param label extra string used only when kind is Contacts.KIND_CUSTOM. */ - public void addContactmethod(String kind, String data, String type, - String label){ - if(contactmethodList == null) + public void addContactmethod(int kind, int type, String data, + String label, boolean isPrimary){ + if (contactmethodList == null) { contactmethodList = new ArrayList<ContactMethod>(); - ContactMethod st = new ContactMethod(); - st.kind = kind; - st.data = data; - st.type = type; - st.label = label; - contactmethodList.add(st); + } + ContactMethod contactMethod = new ContactMethod(); + contactMethod.kind = kind; + contactMethod.type = type; + contactMethod.data = data; + contactMethod.label = label; + contactMethod.isPrimary = isPrimary; + contactmethodList.add(contactMethod); + } + + /** + * Add a Organization info to organizationList. + */ + public void addOrganization(int type, String companyName, String positionName, + boolean isPrimary) { + if (organizationList == null) { + organizationList = new ArrayList<OrganizationData>(); + } + OrganizationData organizationData = new OrganizationData(); + organizationData.type = type; + organizationData.companyName = companyName; + organizationData.positionName = positionName; + organizationData.isPrimary = isPrimary; + organizationList.add(organizationData); + } + + /** + * 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; + } + // Now store the string into extensionMap. + List<String> list; + String name = propertyNode.propName; + if (extensionMap == null) { + extensionMap = new HashMap<String, List<String>>(); + } + if (!extensionMap.containsKey(name)){ + list = new ArrayList<String>(); + extensionMap.put(name, list); + } else { + list = extensionMap.get(name); + } + + list.add(propertyNode.encode()); + } + + private static String getNameFromNProperty(List<String> elems, int nameOrderType) { + // Family, Given, Middle, Prefix, Suffix. (1 - 5) + int size = elems.size(); + if (size > 1) { + StringBuilder builder = new StringBuilder(); + boolean builderIsEmpty = true; + // Prefix + if (size > 3 && elems.get(3).length() > 0) { + builder.append(elems.get(3)); + builderIsEmpty = false; + } + String first, second; + if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) { + first = elems.get(0); + second = elems.get(1); + } else { + first = elems.get(1); + second = elems.get(0); + } + if (first.length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(first); + builderIsEmpty = false; + } + // Middle name + if (size > 2 && elems.get(2).length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(elems.get(2)); + builderIsEmpty = false; + } + if (second.length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(second); + builderIsEmpty = false; + } + // Suffix + if (size > 4 && elems.get(4).length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(elems.get(4)); + builderIsEmpty = false; + } + return builder.toString(); + } else if (size == 1) { + return elems.get(0); + } else { + return ""; + } + } + + public static ContactStruct constructContactFromVNode(VNode node, + int nameOrderType) { + if (!node.VName.equals("VCARD")) { + // Impossible in current implementation. Just for safety. + Log.e(LOG_TAG, "Non VCARD data is inserted."); + return null; + } + + // For name, there are three fields in vCard: FN, N, NAME. + // We prefer FN, which is a required field in vCard 3.0 , but not in vCard 2.1. + // Next, we prefer NAME, which is defined only in vCard 3.0. + // Finally, we use N, which is a little difficult to parse. + String fullName = null; + String nameFromNProperty = null; + + // Some vCard has "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", and + // "X-PHONETIC-LAST-NAME" + String xPhoneticFirstName = null; + String xPhoneticMiddleName = null; + String xPhoneticLastName = null; + + ContactStruct contact = new ContactStruct(); + + // Each Column of four properties has ISPRIMARY field + // (See android.provider.Contacts) + // If false even after the following loop, we choose the first + // entry as a "primary" entry. + boolean prefIsSetAddress = false; + boolean prefIsSetPhone = false; + boolean prefIsSetEmail = false; + boolean prefIsSetOrganization = false; + + for (PropertyNode propertyNode: node.propList) { + String name = propertyNode.propName; + + if (TextUtils.isEmpty(propertyNode.propValue)) { + continue; + } + + if (name.equals("VERSION")) { + // vCard version. Ignore this. + } else if (name.equals("FN")) { + fullName = propertyNode.propValue; + } else if (name.equals("NAME") && fullName == null) { + // Only in vCard 3.0. Use this if FN does not exist. + // Though, note that vCard 3.0 requires FN. + fullName = propertyNode.propValue; + } else if (name.equals("N")) { + nameFromNProperty = getNameFromNProperty(propertyNode.propValue_vector, + nameOrderType); + } else if (name.equals("SORT-STRING")) { + contact.phoneticName = propertyNode.propValue; + } else if (name.equals("SOUND")) { + if (propertyNode.paramMap_TYPE.contains("X-IRMC-N") && + contact.phoneticName == null) { + // Some Japanese mobile phones use this field for phonetic name, + // since vCard 2.1 does not have "SORT-STRING" type. + // Also, in some cases, the field has some ';' in it. + // We remove them. + StringBuilder builder = new StringBuilder(); + String value = propertyNode.propValue; + int length = value.length(); + for (int i = 0; i < length; i++) { + char ch = value.charAt(i); + if (ch != ';') { + builder.append(ch); + } + } + contact.phoneticName = builder.toString(); + } else { + contact.addExtension(propertyNode); + } + } else if (name.equals("ADR")) { + List<String> values = propertyNode.propValue_vector; + boolean valuesAreAllEmpty = true; + for (String value : values) { + if (value.length() > 0) { + valuesAreAllEmpty = false; + break; + } + } + if (valuesAreAllEmpty) { + continue; + } + + int kind = Contacts.KIND_POSTAL; + int type = -1; + String label = ""; + boolean isPrimary = false; + for (String typeString : propertyNode.paramMap_TYPE) { + if (typeString.equals("PREF") && !prefIsSetAddress) { + // Only first "PREF" is considered. + prefIsSetAddress = true; + isPrimary = true; + } else if (typeString.equalsIgnoreCase("HOME")) { + type = Contacts.ContactMethodsColumns.TYPE_HOME; + label = ""; + } else if (typeString.equalsIgnoreCase("WORK") || + typeString.equalsIgnoreCase("COMPANY")) { + // "COMPANY" seems emitted by Windows Mobile, which is not + // specifically supported by vCard 2.1. We assume this is same + // as "WORK". + type = Contacts.ContactMethodsColumns.TYPE_WORK; + label = ""; + } else if (typeString.equalsIgnoreCase("POSTAL")) { + kind = Contacts.KIND_POSTAL; + } else if (typeString.equalsIgnoreCase("PARCEL") || + typeString.equalsIgnoreCase("DOM") || + typeString.equalsIgnoreCase("INTL")) { + // We do not have a kind or type matching these. + // TODO: fix this. We may need to split entries into two. + // (e.g. entries for KIND_POSTAL and KIND_PERCEL) + } else if (typeString.toUpperCase().startsWith("X-") && + type < 0) { + type = Contacts.ContactMethodsColumns.TYPE_CUSTOM; + label = typeString.substring(2); + } else if (type < 0) { + // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters + // emit non-standard types. We do not handle their values now. + type = Contacts.ContactMethodsColumns.TYPE_CUSTOM; + label = typeString; + } + } + // We use "HOME" as default + if (type < 0) { + type = Contacts.ContactMethodsColumns.TYPE_HOME; + } + + // adr-value = 0*6(text-value ";") text-value + // ; PO Box, Extended Address, Street, Locality, Region, Postal + // ; Code, Country Name + String address; + List<String> list = propertyNode.propValue_vector; + int size = list.size(); + if (size > 1) { + StringBuilder builder = new StringBuilder(); + boolean builderIsEmpty = true; + if (Locale.getDefault().getCountry().equals(Locale.JAPAN.getCountry())) { + // In Japan, the order is reversed. + for (int i = size - 1; i >= 0; i--) { + String addressPart = list.get(i); + if (addressPart.length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(addressPart); + builderIsEmpty = false; + } + } + } else { + for (int i = 0; i < size; i++) { + String addressPart = list.get(i); + if (addressPart.length() > 0) { + if (!builderIsEmpty) { + builder.append(' '); + } + builder.append(addressPart); + builderIsEmpty = false; + } + } + } + address = builder.toString().trim(); + } else { + address = propertyNode.propValue; + } + contact.addContactmethod(kind, type, address, label, isPrimary); + } else if (name.equals("ORG")) { + // vCard specification does not specify other types. + int type = Contacts.OrganizationColumns.TYPE_WORK; + boolean isPrimary = false; + + for (String typeString : propertyNode.paramMap_TYPE) { + if (typeString.equals("PREF") && !prefIsSetOrganization) { + // vCard specification officially does not have PREF in ORG. + // This is just for safety. + prefIsSetOrganization = true; + isPrimary = true; + } + // XXX: Should we cope with X- words? + } + + List<String> list = propertyNode.propValue_vector; + int size = list.size(); + StringBuilder builder = new StringBuilder(); + for (Iterator<String> iter = list.iterator(); iter.hasNext();) { + builder.append(iter.next()); + if (iter.hasNext()) { + builder.append(' '); + } + } + + contact.addOrganization(type, builder.toString(), "", isPrimary); + } else if (name.equals("TITLE")) { + contact.setPosition(propertyNode.propValue); + } else if (name.equals("ROLE")) { + contact.setPosition(propertyNode.propValue); + } else if (name.equals("PHOTO")) { + // We prefer PHOTO to LOGO. + String valueType = propertyNode.paramMap.getAsString("VALUE"); + if (valueType != null && valueType.equals("URL")) { + // TODO: do something. + } else { + // Assume PHOTO is stored in BASE64. In that case, + // data is already stored in propValue_bytes in binary form. + // It should be automatically done by VBuilder (VDataBuilder/VCardDatabuilder) + contact.photoBytes = propertyNode.propValue_bytes; + String type = propertyNode.paramMap.getAsString("TYPE"); + if (type != null) { + contact.photoType = type; + } + } + } else if (name.equals("LOGO")) { + // When PHOTO is not available this is not URL, + // we use this instead of PHOTO. + String valueType = propertyNode.paramMap.getAsString("VALUE"); + if (valueType != null && valueType.equals("URL")) { + // TODO: do something. + } else if (contact.photoBytes == null) { + contact.photoBytes = propertyNode.propValue_bytes; + String type = propertyNode.paramMap.getAsString("TYPE"); + if (type != null) { + contact.photoType = type; + } + } + } else if (name.equals("EMAIL")) { + int type = -1; + String label = null; + boolean isPrimary = false; + for (String typeString : propertyNode.paramMap_TYPE) { + if (typeString.equals("PREF") && !prefIsSetEmail) { + // Only first "PREF" is considered. + prefIsSetEmail = true; + isPrimary = true; + } else if (typeString.equalsIgnoreCase("HOME")) { + type = Contacts.ContactMethodsColumns.TYPE_HOME; + } else if (typeString.equalsIgnoreCase("WORK")) { + type = Contacts.ContactMethodsColumns.TYPE_WORK; + } else if (typeString.equalsIgnoreCase("CELL")) { + // We do not have Contacts.ContactMethodsColumns.TYPE_MOBILE yet. + type = Contacts.ContactMethodsColumns.TYPE_CUSTOM; + label = Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME; + } else if (typeString.toUpperCase().startsWith("X-") && + type < 0) { + type = Contacts.ContactMethodsColumns.TYPE_CUSTOM; + label = typeString.substring(2); + } else if (type < 0) { + // vCard 3.0 allows iana-token. + // We may have INTERNET (specified in vCard spec), + // SCHOOL, etc. + type = Contacts.ContactMethodsColumns.TYPE_CUSTOM; + label = typeString; + } + } + // We use "OTHER" as default. + if (type < 0) { + type = Contacts.ContactMethodsColumns.TYPE_OTHER; + } + contact.addContactmethod(Contacts.KIND_EMAIL, + type, propertyNode.propValue,label, isPrimary); + } else if (name.equals("TEL")) { + int type = -1; + String label = null; + boolean isPrimary = false; + boolean isFax = false; + for (String typeString : propertyNode.paramMap_TYPE) { + if (typeString.equals("PREF") && !prefIsSetPhone) { + // Only first "PREF" is considered. + prefIsSetPhone = true; + isPrimary = true; + } else if (typeString.equalsIgnoreCase("HOME")) { + type = Contacts.PhonesColumns.TYPE_HOME; + } else if (typeString.equalsIgnoreCase("WORK")) { + type = Contacts.PhonesColumns.TYPE_WORK; + } else if (typeString.equalsIgnoreCase("CELL")) { + type = Contacts.PhonesColumns.TYPE_MOBILE; + } else if (typeString.equalsIgnoreCase("PAGER")) { + type = Contacts.PhonesColumns.TYPE_PAGER; + } else if (typeString.equalsIgnoreCase("FAX")) { + isFax = true; + } else if (typeString.equalsIgnoreCase("VOICE") || + typeString.equalsIgnoreCase("MSG")) { + // Defined in vCard 3.0. Ignore these because they + // conflict with "HOME", "WORK", etc. + // XXX: do something? + } else if (typeString.toUpperCase().startsWith("X-") && + type < 0) { + type = Contacts.PhonesColumns.TYPE_CUSTOM; + label = typeString.substring(2); + } else if (type < 0){ + // We may have MODEM, CAR, ISDN, etc... + type = Contacts.PhonesColumns.TYPE_CUSTOM; + label = typeString; + } + } + // We use "HOME" as default + if (type < 0) { + type = Contacts.PhonesColumns.TYPE_HOME; + } + if (isFax) { + if (type == Contacts.PhonesColumns.TYPE_HOME) { + type = Contacts.PhonesColumns.TYPE_FAX_HOME; + } else if (type == Contacts.PhonesColumns.TYPE_WORK) { + type = Contacts.PhonesColumns.TYPE_FAX_WORK; + } + } + + contact.addPhone(type, propertyNode.propValue, label, isPrimary); + } else if (name.equals("NOTE")) { + contact.notes.add(propertyNode.propValue); + } else if (name.equals("BDAY")) { + contact.addExtension(propertyNode); + } else if (name.equals("URL")) { + contact.addExtension(propertyNode); + } else if (name.equals("REV")) { + // Revision of this VCard entry. I think we can ignore this. + contact.addExtension(propertyNode); + } else if (name.equals("UID")) { + contact.addExtension(propertyNode); + } else if (name.equals("KEY")) { + // Type is X509 or PGP? I don't know how to handle this... + contact.addExtension(propertyNode); + } else if (name.equals("MAILER")) { + contact.addExtension(propertyNode); + } else if (name.equals("TZ")) { + contact.addExtension(propertyNode); + } else if (name.equals("GEO")) { + contact.addExtension(propertyNode); + } else if (name.equals("NICKNAME")) { + // vCard 3.0 only. + contact.addExtension(propertyNode); + } else if (name.equals("CLASS")) { + // vCard 3.0 only. + // e.g. CLASS:CONFIDENTIAL + contact.addExtension(propertyNode); + } else if (name.equals("PROFILE")) { + // VCard 3.0 only. Must be "VCARD". I think we can ignore this. + contact.addExtension(propertyNode); + } else if (name.equals("CATEGORIES")) { + // VCard 3.0 only. + // e.g. CATEGORIES:INTERNET,IETF,INDUSTRY,INFORMATION TECHNOLOGY + contact.addExtension(propertyNode); + } else if (name.equals("SOURCE")) { + // VCard 3.0 only. + contact.addExtension(propertyNode); + } else if (name.equals("PRODID")) { + // VCard 3.0 only. + // To specify the identifier for the product that created + // the vCard object. + contact.addExtension(propertyNode); + } else if (name.equals("X-PHONETIC-FIRST-NAME")) { + xPhoneticFirstName = propertyNode.propValue; + } else if (name.equals("X-PHONETIC-MIDDLE-NAME")) { + xPhoneticMiddleName = propertyNode.propValue; + } else if (name.equals("X-PHONETIC-LAST-NAME")) { + xPhoneticLastName = propertyNode.propValue; + } else { + // Unknown X- words and IANA token. + contact.addExtension(propertyNode); + } + } + + if (fullName != null) { + contact.name = fullName; + } else if(nameFromNProperty != null) { + contact.name = nameFromNProperty; + } else { + contact.name = ""; + } + + if (contact.phoneticName == null && + (xPhoneticFirstName != null || xPhoneticMiddleName != null || + xPhoneticLastName != null)) { + // Note: In Europe, this order should be "LAST FIRST MIDDLE". See the comment around + // NAME_ORDER_TYPE_* for more detail. + String first; + String second; + if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) { + first = xPhoneticLastName; + second = xPhoneticFirstName; + } else { + first = xPhoneticFirstName; + second = xPhoneticLastName; + } + StringBuilder builder = new StringBuilder(); + if (first != null) { + builder.append(first); + } + if (xPhoneticMiddleName != null) { + builder.append(xPhoneticMiddleName); + } + if (second != null) { + builder.append(second); + } + contact.phoneticName = builder.toString(); + } + + // Remove unnecessary white spaces. + // It is found that some mobile phone emits phonetic name with just one white space + // when a user does not specify one. + // This logic is effective toward such kind of weird data. + if (contact.phoneticName != null) { + contact.phoneticName = contact.phoneticName.trim(); + } + + // If there is no "PREF", we choose the first entries as primary. + if (!prefIsSetPhone && + contact.phoneList != null && + contact.phoneList.size() > 0) { + contact.phoneList.get(0).isPrimary = true; + } + + if (!prefIsSetAddress && contact.contactmethodList != null) { + for (ContactMethod contactMethod : contact.contactmethodList) { + if (contactMethod.kind == Contacts.KIND_POSTAL) { + contactMethod.isPrimary = true; + break; + } + } + } + if (!prefIsSetEmail && contact.contactmethodList != null) { + for (ContactMethod contactMethod : contact.contactmethodList) { + if (contactMethod.kind == Contacts.KIND_EMAIL) { + contactMethod.isPrimary = true; + break; + } + } + } + if (!prefIsSetOrganization && + contact.organizationList != null && + contact.organizationList.size() > 0) { + contact.organizationList.get(0).isPrimary = true; + } + + return contact; + } + + public String displayString() { + if (name.length() > 0) { + return name; + } + if (contactmethodList != null && contactmethodList.size() > 0) { + for (ContactMethod contactMethod : contactmethodList) { + if (contactMethod.kind == Contacts.KIND_EMAIL && contactMethod.isPrimary) { + return contactMethod.data; + } + } + } + if (phoneList != null && phoneList.size() > 0) { + for (PhoneData phoneData : phoneList) { + if (phoneData.isPrimary) { + return phoneData.data; + } + } + } + return ""; + } + + private void pushIntoContentProviderOrResolver(Object contentSomething, + long myContactsGroupId) { + ContentResolver resolver = null; + AbstractSyncableContentProvider provider = null; + if (contentSomething instanceof ContentResolver) { + resolver = (ContentResolver)contentSomething; + } else if (contentSomething instanceof AbstractSyncableContentProvider) { + provider = (AbstractSyncableContentProvider)contentSomething; + } else { + Log.e(LOG_TAG, "Unsupported object came."); + return; + } + + ContentValues contentValues = new ContentValues(); + contentValues.put(People.NAME, name); + contentValues.put(People.PHONETIC_NAME, phoneticName); + + if (notes.size() > 1) { + StringBuilder builder = new StringBuilder(); + for (String note : notes) { + builder.append(note); + builder.append("\n"); + } + contentValues.put(People.NOTES, builder.toString()); + } else if (notes.size() == 1){ + contentValues.put(People.NOTES, notes.get(0)); + } + + Uri personUri; + long personId = 0; + if (resolver != null) { + personUri = Contacts.People.createPersonInMyContactsGroup( + resolver, contentValues); + if (personUri != null) { + personId = ContentUris.parseId(personUri); + } + } else { + personUri = provider.nonTransactionalInsert(People.CONTENT_URI, contentValues); + if (personUri != null) { + personId = ContentUris.parseId(personUri); + ContentValues values = new ContentValues(); + values.put(GroupMembership.PERSON_ID, personId); + values.put(GroupMembership.GROUP_ID, myContactsGroupId); + Uri resultUri = provider.nonTransactionalInsert( + GroupMembership.CONTENT_URI, values); + if (resultUri == null) { + Log.e(LOG_TAG, "Faild to insert the person to MyContact."); + provider.nonTransactionalDelete(personUri, null, null); + personUri = null; + } + } + } + + if (personUri == null) { + Log.e(LOG_TAG, "Failed to create the contact."); + return; + } + + if (photoBytes != null) { + if (resolver != null) { + People.setPhotoData(resolver, personUri, photoBytes); + } else { + Uri photoUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY); + ContentValues values = new ContentValues(); + values.put(Photos.DATA, photoBytes); + provider.update(photoUri, values, null, null); + } + } + + long primaryPhoneId = -1; + if (phoneList != null && phoneList.size() > 0) { + for (PhoneData phoneData : phoneList) { + ContentValues values = new ContentValues(); + values.put(Contacts.PhonesColumns.TYPE, phoneData.type); + if (phoneData.type == Contacts.PhonesColumns.TYPE_CUSTOM) { + values.put(Contacts.PhonesColumns.LABEL, phoneData.label); + } + // Already formatted. + values.put(Contacts.PhonesColumns.NUMBER, phoneData.data); + + // Not sure about Contacts.PhonesColumns.NUMBER_KEY ... + values.put(Contacts.PhonesColumns.ISPRIMARY, 1); + values.put(Contacts.Phones.PERSON_ID, personId); + Uri phoneUri; + if (resolver != null) { + phoneUri = resolver.insert(Phones.CONTENT_URI, values); + } else { + phoneUri = provider.nonTransactionalInsert(Phones.CONTENT_URI, values); + } + if (phoneData.isPrimary) { + primaryPhoneId = Long.parseLong(phoneUri.getLastPathSegment()); + } + } + } + + long primaryOrganizationId = -1; + if (organizationList != null && organizationList.size() > 0) { + for (OrganizationData organizationData : organizationList) { + ContentValues values = new ContentValues(); + // Currently, we do not use TYPE_CUSTOM. + values.put(Contacts.OrganizationColumns.TYPE, + organizationData.type); + values.put(Contacts.OrganizationColumns.COMPANY, + organizationData.companyName); + values.put(Contacts.OrganizationColumns.TITLE, + organizationData.positionName); + values.put(Contacts.OrganizationColumns.ISPRIMARY, 1); + values.put(Contacts.OrganizationColumns.PERSON_ID, personId); + + Uri organizationUri; + if (resolver != null) { + organizationUri = resolver.insert(Organizations.CONTENT_URI, values); + } else { + organizationUri = provider.nonTransactionalInsert( + Organizations.CONTENT_URI, values); + } + if (organizationData.isPrimary) { + primaryOrganizationId = Long.parseLong(organizationUri.getLastPathSegment()); + } + } + } + + long primaryEmailId = -1; + if (contactmethodList != null && contactmethodList.size() > 0) { + for (ContactMethod contactMethod : contactmethodList) { + ContentValues values = new ContentValues(); + values.put(Contacts.ContactMethodsColumns.KIND, contactMethod.kind); + values.put(Contacts.ContactMethodsColumns.TYPE, contactMethod.type); + if (contactMethod.type == Contacts.ContactMethodsColumns.TYPE_CUSTOM) { + values.put(Contacts.ContactMethodsColumns.LABEL, contactMethod.label); + } + values.put(Contacts.ContactMethodsColumns.DATA, contactMethod.data); + values.put(Contacts.ContactMethodsColumns.ISPRIMARY, 1); + values.put(Contacts.ContactMethods.PERSON_ID, personId); + + if (contactMethod.kind == Contacts.KIND_EMAIL) { + Uri emailUri; + if (resolver != null) { + emailUri = resolver.insert(ContactMethods.CONTENT_URI, values); + } else { + emailUri = provider.nonTransactionalInsert( + ContactMethods.CONTENT_URI, values); + } + if (contactMethod.isPrimary) { + primaryEmailId = Long.parseLong(emailUri.getLastPathSegment()); + } + } else { // probably KIND_POSTAL + if (resolver != null) { + resolver.insert(ContactMethods.CONTENT_URI, values); + } else { + provider.nonTransactionalInsert( + ContactMethods.CONTENT_URI, values); + } + } + } + } + + if (extensionMap != null && extensionMap.size() > 0) { + ArrayList<ContentValues> contentValuesArray; + if (resolver != null) { + contentValuesArray = new ArrayList<ContentValues>(); + } else { + contentValuesArray = null; + } + for (Entry<String, List<String>> entry : extensionMap.entrySet()) { + String key = entry.getKey(); + List<String> list = entry.getValue(); + for (String value : list) { + ContentValues values = new ContentValues(); + values.put(Extensions.NAME, key); + values.put(Extensions.VALUE, value); + values.put(Extensions.PERSON_ID, personId); + if (resolver != null) { + contentValuesArray.add(values); + } else { + provider.nonTransactionalInsert(Extensions.CONTENT_URI, values); + } + } + } + if (resolver != null) { + resolver.bulkInsert(Extensions.CONTENT_URI, + contentValuesArray.toArray(new ContentValues[0])); + } + } + + if (primaryPhoneId >= 0 || primaryOrganizationId >= 0 || primaryEmailId >= 0) { + ContentValues values = new ContentValues(); + if (primaryPhoneId >= 0) { + values.put(People.PRIMARY_PHONE_ID, primaryPhoneId); + } + if (primaryOrganizationId >= 0) { + values.put(People.PRIMARY_ORGANIZATION_ID, primaryOrganizationId); + } + if (primaryEmailId >= 0) { + values.put(People.PRIMARY_EMAIL_ID, primaryEmailId); + } + if (resolver != null) { + resolver.update(personUri, values, null, null); + } else { + provider.nonTransactionalUpdate(personUri, values, null, null); + } + } + } + + /** + * Push this object into database in the resolver. + */ + public void pushIntoContentResolver(ContentResolver resolver) { + pushIntoContentProviderOrResolver(resolver, 0); + } + + /** + * Push this object into AbstractSyncableContentProvider object. + */ + public void pushIntoAbstractSyncableContentProvider( + AbstractSyncableContentProvider provider, long myContactsGroupId) { + boolean successful = false; + provider.beginTransaction(); + try { + pushIntoContentProviderOrResolver(provider, myContactsGroupId); + successful = true; + } finally { + provider.endTransaction(successful); + } + } + + public boolean isIgnorable() { + return TextUtils.isEmpty(name) && + TextUtils.isEmpty(phoneticName) && + (phoneList == null || phoneList.size() == 0) && + (contactmethodList == null || contactmethodList.size() == 0); } } diff --git a/core/java/android/syncml/pim/vcard/VCardComposer.java b/core/java/android/syncml/pim/vcard/VCardComposer.java index 05e8f40..192736a 100644 --- a/core/java/android/syncml/pim/vcard/VCardComposer.java +++ b/core/java/android/syncml/pim/vcard/VCardComposer.java @@ -124,9 +124,9 @@ public class VCardComposer { mResult.append("ORG:").append(struct.company).append(mNewline); } - if (!isNull(struct.notes)) { + if (struct.notes.size() > 0 && !isNull(struct.notes.get(0))) { mResult.append("NOTE:").append( - foldingString(struct.notes, vcardversion)).append(mNewline); + foldingString(struct.notes.get(0), vcardversion)).append(mNewline); } if (!isNull(struct.title)) { @@ -190,7 +190,7 @@ public class VCardComposer { */ private void appendPhotoStr(byte[] bytes, String type, int version) throws VCardException { - String value, apptype, encodingStr; + String value, encodingStr; try { value = foldingString(new String(Base64.encodeBase64(bytes, true)), version); @@ -198,20 +198,23 @@ public class VCardComposer { throw new VCardException(e.getMessage()); } - if (isNull(type)) { - type = "image/jpeg"; - } - if (type.indexOf("jpeg") > 0) { - apptype = "JPEG"; - } else if (type.indexOf("gif") > 0) { - apptype = "GIF"; - } else if (type.indexOf("bmp") > 0) { - apptype = "BMP"; + if (isNull(type) || type.toUpperCase().indexOf("JPEG") >= 0) { + type = "JPEG"; + } else if (type.toUpperCase().indexOf("GIF") >= 0) { + type = "GIF"; + } else if (type.toUpperCase().indexOf("BMP") >= 0) { + type = "BMP"; } else { - apptype = type.substring(type.indexOf("/")).toUpperCase(); + // Handle the string like "image/tiff". + int indexOfSlash = type.indexOf("/"); + if (indexOfSlash >= 0) { + type = type.substring(indexOfSlash + 1).toUpperCase(); + } else { + type = type.toUpperCase(); + } } - mResult.append("LOGO;TYPE=").append(apptype); + mResult.append("LOGO;TYPE=").append(type); if (version == VERSION_VCARD21_INT) { encodingStr = ";ENCODING=BASE64:"; value = value + mNewline; @@ -281,7 +284,7 @@ public class VCardComposer { private String getPhoneTypeStr(PhoneData phone) { - int phoneType = Integer.parseInt(phone.type); + int phoneType = phone.type; String typeStr, label; if (phoneTypeMap.containsKey(phoneType)) { @@ -308,7 +311,7 @@ public class VCardComposer { String joinMark = version == VERSION_VCARD21_INT ? ";" : ","; for (ContactStruct.ContactMethod contactMethod : contactMList) { // same with v2.1 and v3.0 - switch (Integer.parseInt(contactMethod.kind)) { + switch (contactMethod.kind) { case Contacts.KIND_EMAIL: String mailType = "INTERNET"; if (!isNull(contactMethod.data)) { diff --git a/core/java/android/syncml/pim/vcard/VCardDataBuilder.java b/core/java/android/syncml/pim/vcard/VCardDataBuilder.java new file mode 100644 index 0000000..a0513f1 --- /dev/null +++ b/core/java/android/syncml/pim/vcard/VCardDataBuilder.java @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.syncml.pim.vcard; + +import android.app.ProgressDialog; +import android.content.AbstractSyncableContentProvider; +import android.content.ContentProvider; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.IContentProvider; +import android.os.Handler; +import android.provider.Contacts; +import android.syncml.pim.PropertyNode; +import android.syncml.pim.VBuilder; +import android.syncml.pim.VNode; +import android.syncml.pim.VParser; +import android.util.CharsetUtils; +import android.util.Log; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.net.QuotedPrintableCodec; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +/** + * VBuilder for VCard. VCard may contain big photo images encoded by BASE64, + * If we store all VNode entries in memory like VDataBuilder.java, + * OutOfMemoryError may be thrown. Thus, this class push each VCard entry into + * ContentResolver immediately. + */ +public class VCardDataBuilder implements VBuilder { + static private String LOG_TAG = "VCardDataBuilder"; + + /** + * If there's no other information available, this class uses this charset for encoding + * byte arrays. + */ + static public String DEFAULT_CHARSET = "UTF-8"; + + private class ProgressShower implements Runnable { + private ContactStruct mContact; + + public ProgressShower(ContactStruct contact) { + mContact = contact; + } + + public void run () { + mProgressDialog.setMessage(mProgressMessage + "\n" + + mContact.displayString()); + } + } + + /** type=VNode */ + private VNode mCurrentVNode; + private PropertyNode mCurrentPropNode; + private String mCurrentParamType; + + /** + * The charset using which VParser parses the text. + */ + private String mSourceCharset; + + /** + * The charset with which byte array is encoded to String. + */ + private String mTargetCharset; + private boolean mStrictLineBreakParsing; + private ContentResolver mContentResolver; + + // For letting VCardDataBuilder show the display name of VCard while handling it. + private Handler mHandler; + private ProgressDialog mProgressDialog; + private String mProgressMessage; + private Runnable mOnProgressRunnable; + private boolean mLastNameComesBeforeFirstName; + + // Just for testing. + private long mTimeCreateContactStruct; + private long mTimePushIntoContentResolver; + + // Ideally, this should be ContactsProvider but it seems Class loader cannot find it, + // even when it is subclass of ContactsProvider... + private AbstractSyncableContentProvider mProvider; + private long mMyContactsGroupId; + + public VCardDataBuilder(ContentResolver resolver) { + mTargetCharset = DEFAULT_CHARSET; + mContentResolver = resolver; + } + + /** + * Constructor which requires minimum requiredvariables. + * + * @param resolver insert each data into this ContentResolver + * @param progressDialog + * @param progressMessage + * @param handler if this importer works on the different thread than main one, + * set appropriate handler object. If not, it is ok to set this null. + */ + public VCardDataBuilder(ContentResolver resolver, + ProgressDialog progressDialog, + String progressMessage, + Handler handler) { + this(resolver, progressDialog, progressMessage, handler, + null, null, false, false); + } + + public VCardDataBuilder(ContentResolver resolver, + ProgressDialog progressDialog, + String progressMessage, + Handler handler, + String charset, + boolean strictLineBreakParsing, + boolean lastNameComesBeforeFirstName) { + this(resolver, progressDialog, progressMessage, handler, + null, charset, strictLineBreakParsing, + lastNameComesBeforeFirstName); + } + + /** + * @hide + */ + public VCardDataBuilder(ContentResolver resolver, + ProgressDialog progressDialog, + String progressMessage, + Handler handler, + String sourceCharset, + String targetCharset, + boolean strictLineBreakParsing, + boolean lastNameComesBeforeFirstName) { + if (sourceCharset != null) { + mSourceCharset = sourceCharset; + } else { + mSourceCharset = VParser.DEFAULT_CHARSET; + } + if (targetCharset != null) { + mTargetCharset = targetCharset; + } else { + mTargetCharset = DEFAULT_CHARSET; + } + mContentResolver = resolver; + mStrictLineBreakParsing = strictLineBreakParsing; + mHandler = handler; + mProgressDialog = progressDialog; + mProgressMessage = progressMessage; + mLastNameComesBeforeFirstName = lastNameComesBeforeFirstName; + + tryGetOriginalProvider(); + } + + private void tryGetOriginalProvider() { + final ContentResolver resolver = mContentResolver; + + if ((mMyContactsGroupId = Contacts.People.tryGetMyContactsGroupId(resolver)) == 0) { + Log.e(LOG_TAG, "Could not get group id of MyContact"); + return; + } + + IContentProvider iProviderForName = resolver.acquireProvider(Contacts.CONTENT_URI); + ContentProvider contentProvider = + ContentProvider.coerceToLocalContentProvider(iProviderForName); + if (contentProvider == null) { + Log.e(LOG_TAG, "Fail to get ContentProvider object."); + return; + } + + if (!(contentProvider instanceof AbstractSyncableContentProvider)) { + Log.e(LOG_TAG, + "Acquired ContentProvider object is not AbstractSyncableContentProvider."); + return; + } + + mProvider = (AbstractSyncableContentProvider)contentProvider; + } + + public void setOnProgressRunnable(Runnable runnable) { + mOnProgressRunnable = runnable; + } + + public void start() { + } + + public void end() { + } + + /** + * Assume that VCard is not nested. In other words, this code does not accept + */ + public void startRecord(String type) { + if (mCurrentVNode != null) { + // This means startRecord() is called inside startRecord() - endRecord() block. + // TODO: should throw some Exception + Log.e(LOG_TAG, "Nested VCard code is not supported now."); + } + mCurrentVNode = new VNode(); + mCurrentVNode.parseStatus = 1; + mCurrentVNode.VName = type; + } + + public void endRecord() { + mCurrentVNode.parseStatus = 0; + long start = System.currentTimeMillis(); + ContactStruct contact = ContactStruct.constructContactFromVNode(mCurrentVNode, + mLastNameComesBeforeFirstName ? ContactStruct.NAME_ORDER_TYPE_JAPANESE : + ContactStruct.NAME_ORDER_TYPE_ENGLISH); + mTimeCreateContactStruct += System.currentTimeMillis() - start; + if (!contact.isIgnorable()) { + if (mProgressDialog != null && mProgressMessage != null) { + if (mHandler != null) { + mHandler.post(new ProgressShower(contact)); + } else { + mProgressDialog.setMessage(mProgressMessage + "\n" + + contact.displayString()); + } + } + start = System.currentTimeMillis(); + if (mProvider != null) { + contact.pushIntoAbstractSyncableContentProvider( + mProvider, mMyContactsGroupId); + } else { + contact.pushIntoContentResolver(mContentResolver); + } + mTimePushIntoContentResolver += System.currentTimeMillis() - start; + } + if (mOnProgressRunnable != null) { + mOnProgressRunnable.run(); + } + mCurrentVNode = null; + } + + public void startProperty() { + mCurrentPropNode = new PropertyNode(); + } + + public void endProperty() { + mCurrentVNode.propList.add(mCurrentPropNode); + mCurrentPropNode = null; + } + + public void propertyName(String name) { + mCurrentPropNode.propName = name; + } + + public void propertyGroup(String group) { + mCurrentPropNode.propGroupSet.add(group); + } + + public void propertyParamType(String type) { + mCurrentParamType = type; + } + + public void propertyParamValue(String value) { + if (mCurrentParamType == null || + mCurrentParamType.equalsIgnoreCase("TYPE")) { + mCurrentPropNode.paramMap_TYPE.add(value); + } else { + mCurrentPropNode.paramMap.put(mCurrentParamType, value); + } + + mCurrentParamType = null; + } + + private String encodeString(String originalString, String targetCharset) { + if (mSourceCharset.equalsIgnoreCase(targetCharset)) { + return originalString; + } + Charset charset = Charset.forName(mSourceCharset); + ByteBuffer byteBuffer = charset.encode(originalString); + // byteBuffer.array() "may" return byte array which is larger than + // byteBuffer.remaining(). Here, we keep on the safe side. + byte[] bytes = new byte[byteBuffer.remaining()]; + byteBuffer.get(bytes); + try { + return new String(bytes, targetCharset); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); + return new String(bytes); + } + } + + private String handleOneValue(String value, String targetCharset, String encoding) { + if (encoding != null) { + if (encoding.equals("BASE64") || encoding.equals("B")) { + mCurrentPropNode.propValue_bytes = + Base64.decodeBase64(value.getBytes()); + return value; + } else if (encoding.equals("QUOTED-PRINTABLE")) { + // "= " -> " ", "=\t" -> "\t". + // Previous code had done this replacement. Keep on the safe side. + StringBuilder builder = new StringBuilder(); + int length = value.length(); + for (int i = 0; i < length; i++) { + char ch = value.charAt(i); + if (ch == '=' && i < length - 1) { + char nextCh = value.charAt(i + 1); + if (nextCh == ' ' || nextCh == '\t') { + + builder.append(nextCh); + i++; + continue; + } + } + builder.append(ch); + } + String quotedPrintable = builder.toString(); + + String[] lines; + if (mStrictLineBreakParsing) { + lines = quotedPrintable.split("\r\n"); + } else { + builder = new StringBuilder(); + length = quotedPrintable.length(); + ArrayList<String> list = new ArrayList<String>(); + for (int i = 0; i < length; i++) { + char ch = quotedPrintable.charAt(i); + if (ch == '\n') { + list.add(builder.toString()); + builder = new StringBuilder(); + } else if (ch == '\r') { + list.add(builder.toString()); + builder = new StringBuilder(); + if (i < length - 1) { + char nextCh = quotedPrintable.charAt(i + 1); + if (nextCh == '\n') { + i++; + } + } + } else { + builder.append(ch); + } + } + String finalLine = builder.toString(); + if (finalLine.length() > 0) { + list.add(finalLine); + } + lines = list.toArray(new String[0]); + } + + builder = new StringBuilder(); + for (String line : lines) { + if (line.endsWith("=")) { + line = line.substring(0, line.length() - 1); + } + builder.append(line); + } + byte[] bytes; + try { + bytes = builder.toString().getBytes(mSourceCharset); + } catch (UnsupportedEncodingException e1) { + Log.e(LOG_TAG, "Failed to encode: charset=" + mSourceCharset); + bytes = builder.toString().getBytes(); + } + + try { + bytes = QuotedPrintableCodec.decodeQuotedPrintable(bytes); + } catch (DecoderException e) { + Log.e(LOG_TAG, "Failed to decode quoted-printable: " + e); + return ""; + } + + try { + return new String(bytes, targetCharset); + } catch (UnsupportedEncodingException e) { + Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset); + return new String(bytes); + } + } + // Unknown encoding. Fall back to default. + } + return encodeString(value, targetCharset); + } + + public void propertyValues(List<String> values) { + if (values == null || values.size() == 0) { + mCurrentPropNode.propValue_bytes = null; + mCurrentPropNode.propValue_vector.clear(); + mCurrentPropNode.propValue_vector.add(""); + mCurrentPropNode.propValue = ""; + return; + } + + ContentValues paramMap = mCurrentPropNode.paramMap; + + String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET")); + String encoding = paramMap.getAsString("ENCODING"); + + if (targetCharset == null || targetCharset.length() == 0) { + targetCharset = mTargetCharset; + } + + for (String value : values) { + mCurrentPropNode.propValue_vector.add( + handleOneValue(value, targetCharset, encoding)); + } + + mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector); + } + + public void showDebugInfo() { + Log.d(LOG_TAG, "time for creating ContactStruct: " + mTimeCreateContactStruct + " ms"); + Log.d(LOG_TAG, "time for insert ContactStruct to database: " + + mTimePushIntoContentResolver + " ms"); + } + + private String listToString(List<String> list){ + int size = list.size(); + if (size > 1) { + StringBuilder builder = new StringBuilder(); + int i = 0; + for (String type : list) { + builder.append(type); + if (i < size - 1) { + builder.append(";"); + } + } + return builder.toString(); + } else if (size == 1) { + return list.get(0); + } else { + return ""; + } + } +} diff --git a/core/java/android/syncml/pim/vcard/VCardEntryCounter.java b/core/java/android/syncml/pim/vcard/VCardEntryCounter.java new file mode 100644 index 0000000..03cd1d9 --- /dev/null +++ b/core/java/android/syncml/pim/vcard/VCardEntryCounter.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.syncml.pim.vcard; + +import java.util.List; + +import android.syncml.pim.VBuilder; + +public class VCardEntryCounter implements VBuilder { + private int mCount; + + public int getCount() { + return mCount; + } + + public void start() { + } + + public void end() { + } + + public void startRecord(String type) { + } + + public void endRecord() { + mCount++; + } + + public void startProperty() { + } + + public void endProperty() { + } + + public void propertyGroup(String group) { + } + + public void propertyName(String name) { + } + + public void propertyParamType(String type) { + } + + public void propertyParamValue(String value) { + } + + public void propertyValues(List<String> values) { + } +}
\ No newline at end of file diff --git a/core/java/android/syncml/pim/vcard/VCardNestedException.java b/core/java/android/syncml/pim/vcard/VCardNestedException.java new file mode 100644 index 0000000..def6f3b --- /dev/null +++ b/core/java/android/syncml/pim/vcard/VCardNestedException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.syncml.pim.vcard; + +/** + * VCardException thrown when VCard is nested without VCardParser's being notified. + */ +public class VCardNestedException extends VCardException { + public VCardNestedException() {} + public VCardNestedException(String message) { + super(message); + } +} diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V21.java b/core/java/android/syncml/pim/vcard/VCardParser_V21.java index f853c5e..d865668 100644 --- a/core/java/android/syncml/pim/vcard/VCardParser_V21.java +++ b/core/java/android/syncml/pim/vcard/VCardParser_V21.java @@ -17,21 +17,26 @@ package android.syncml.pim.vcard; import android.syncml.pim.VBuilder; +import android.syncml.pim.VParser; +import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.regex.Pattern; /** - * This class is used to parse vcard. Please refer to vCard Specification 2.1 + * This class is used to parse vcard. Please refer to vCard Specification 2.1. */ public class VCardParser_V21 { - + private static final String LOG_TAG = "VCardParser_V21"; + + public static final String DEFAULT_CHARSET = VParser.DEFAULT_CHARSET; + /** Store the known-type */ private static final HashSet<String> sKnownTypeSet = new HashSet<String>( Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK", @@ -42,19 +47,17 @@ public class VCardParser_V21 { "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF", "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI", "WAVE", "AIFF", "PCM", "X509", "PGP")); - + /** Store the known-value */ private static final HashSet<String> sKnownValueSet = new HashSet<String>( Arrays.asList("INLINE", "URL", "CONTENT-ID", "CID")); - /** Store the property name available in vCard 2.1 */ - // NICKNAME is not supported in vCard 2.1, but some vCard may contain. + /** Store the property names available in vCard 2.1 */ private static final HashSet<String> sAvailablePropertyNameV21 = new HashSet<String>(Arrays.asList( - "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", + "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", - "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", - "NICKNAME")); + "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER")); // Though vCard 2.1 specification does not allow "B" encoding, some data may have it. // We allow it for safety... @@ -76,6 +79,30 @@ public class VCardParser_V21 { // Should not directly read a line from this. Use getLine() instead. protected BufferedReader mReader; + private boolean mCanceled; + + // In some cases, vCard is nested. Currently, we only consider the most interior vCard data. + // See v21_foma_1.vcf in test directory for more information. + private int mNestCount; + + // In order to reduce warning message as much as possible, we hold the value which made Logger + // emit a warning message. + protected HashSet<String> mWarningValueMap = new HashSet<String>(); + + // Just for debugging + private long mTimeTotal; + private long mTimeStartRecord; + private long mTimeEndRecord; + private long mTimeStartProperty; + private long mTimeEndProperty; + private long mTimeParseItems; + private long mTimeParseItem1; + private long mTimeParseItem2; + private long mTimeParseItem3; + private long mTimeHandlePropertyValue1; + private long mTimeHandlePropertyValue2; + private long mTimeHandlePropertyValue3; + /** * Create a new VCard parser. */ @@ -83,12 +110,35 @@ public class VCardParser_V21 { super(); } + public VCardParser_V21(VCardSourceDetector detector) { + super(); + if (detector != null && detector.getType() == VCardSourceDetector.TYPE_FOMA) { + mNestCount = 1; + } + } + /** * Parse the file at the given position * vcard_file = [wsls] vcard [wsls] */ protected void parseVCardFile() throws IOException, VCardException { - while (parseOneVCard()) { + boolean firstReading = true; + while (true) { + if (mCanceled) { + break; + } + if (!parseOneVCard(firstReading)) { + break; + } + firstReading = false; + } + + if (mNestCount > 0) { + boolean useCache = true; + for (int i = 0; i < mNestCount; i++) { + readEndVCard(useCache, true); + useCache = false; + } } } @@ -100,7 +150,13 @@ public class VCardParser_V21 { * @return true when the propertyName is a valid property name. */ protected boolean isValidPropertyName(String propertyName) { - return sAvailablePropertyNameV21.contains(propertyName.toUpperCase()); + if (!(sAvailablePropertyNameV21.contains(propertyName.toUpperCase()) || + propertyName.startsWith("X-")) && + !mWarningValueMap.contains(propertyName)) { + mWarningValueMap.add(propertyName); + Log.w(LOG_TAG, "Property name unsupported by vCard 2.1: " + propertyName); + } + return true; } /** @@ -129,7 +185,7 @@ public class VCardParser_V21 { line = getLine(); if (line == null) { throw new VCardException("Reached end of buffer."); - } else if (line.trim().length() > 0) { + } else if (line.trim().length() > 0) { return line; } } @@ -140,12 +196,37 @@ public class VCardParser_V21 { * items *CRLF * "END" [ws] ":" [ws] "VCARD" */ - private boolean parseOneVCard() throws IOException, VCardException { - if (!readBeginVCard()) { + private boolean parseOneVCard(boolean firstReading) throws IOException, VCardException { + boolean allowGarbage = false; + if (firstReading) { + if (mNestCount > 0) { + for (int i = 0; i < mNestCount; i++) { + if (!readBeginVCard(allowGarbage)) { + return false; + } + allowGarbage = true; + } + } + } + + if (!readBeginVCard(allowGarbage)) { return false; } + long start; + if (mBuilder != null) { + start = System.currentTimeMillis(); + mBuilder.startRecord("VCARD"); + mTimeStartRecord += System.currentTimeMillis() - start; + } + start = System.currentTimeMillis(); parseItems(); - readEndVCard(); + mTimeParseItems += System.currentTimeMillis() - start; + readEndVCard(true, false); + if (mBuilder != null) { + start = System.currentTimeMillis(); + mBuilder.endRecord(); + mTimeEndRecord += System.currentTimeMillis() - start; + } return true; } @@ -154,46 +235,102 @@ public class VCardParser_V21 { * @throws IOException * @throws VCardException */ - protected boolean readBeginVCard() throws IOException, VCardException { + protected boolean readBeginVCard(boolean allowGarbage) + throws IOException, VCardException { String line; - while (true) { - line = getLine(); - if (line == null) { - return false; - } else if (line.trim().length() > 0) { - break; + do { + while (true) { + line = getLine(); + if (line == null) { + return false; + } else if (line.trim().length() > 0) { + break; + } } - } - String[] strArray = line.split(":", 2); - - // Though vCard specification does not allow lower cases, - // some data may have them, so we allow it. - if (!(strArray.length == 2 && - strArray[0].trim().equalsIgnoreCase("BEGIN") && - strArray[1].trim().equalsIgnoreCase("VCARD"))) { - throw new VCardException("BEGIN:VCARD != \"" + line + "\""); - } - - if (mBuilder != null) { - mBuilder.startRecord("VCARD"); - } + String[] strArray = line.split(":", 2); + int length = strArray.length; - return true; + // Though vCard 2.1/3.0 specification does not allow lower cases, + // some data may have them, so we allow it (Actually, previous code + // had explicitly allowed "BEGIN:vCard" though there's no example). + // + // TODO: ignore non vCard entry (e.g. vcalendar). + // XXX: Not sure, but according to VDataBuilder.java, vcalendar + // entry + // may be nested. Just seeking "END:SOMETHING" may not be enough. + // e.g. + // BEGIN:VCARD + // ... (Valid. Must parse this) + // END:VCARD + // BEGIN:VSOMETHING + // ... (Must ignore this) + // BEGIN:VSOMETHING2 + // ... (Must ignore this) + // END:VSOMETHING2 + // ... (Must ignore this!) + // END:VSOMETHING + // BEGIN:VCARD + // ... (Valid. Must parse this) + // END:VCARD + // INVALID_STRING (VCardException should be thrown) + if (length == 2 && + strArray[0].trim().equalsIgnoreCase("BEGIN") && + strArray[1].trim().equalsIgnoreCase("VCARD")) { + return true; + } else if (!allowGarbage) { + if (mNestCount > 0) { + mPreviousLine = line; + return false; + } else { + throw new VCardException( + "Expected String \"BEGIN:VCARD\" did not come " + + "(Instead, \"" + line + "\" came)"); + } + } + } while(allowGarbage); + + throw new VCardException("Reached where must not be reached."); } - - protected void readEndVCard() throws VCardException { - // Though vCard specification does not allow lower cases, - // some data may have them, so we allow it. - String[] strArray = mPreviousLine.split(":", 2); - if (!(strArray.length == 2 && - strArray[0].trim().equalsIgnoreCase("END") && - strArray[1].trim().equalsIgnoreCase("VCARD"))) { - throw new VCardException("END:VCARD != \"" + mPreviousLine + "\""); - } - - if (mBuilder != null) { - mBuilder.endRecord(); - } + + /** + * The arguments useCache and allowGarbase are usually true and false accordingly when + * this function is called outside this function itself. + * + * @param useCache When true, line is obtained from mPreviousline. Otherwise, getLine() + * is used. + * @param allowGarbage When true, ignore non "END:VCARD" line. + * @throws IOException + * @throws VCardException + */ + protected void readEndVCard(boolean useCache, boolean allowGarbage) + throws IOException, VCardException { + String line; + do { + if (useCache) { + // Though vCard specification does not allow lower cases, + // some data may have them, so we allow it. + line = mPreviousLine; + } else { + while (true) { + line = getLine(); + if (line == null) { + throw new VCardException("Expected END:VCARD was not found."); + } else if (line.trim().length() > 0) { + break; + } + } + } + + String[] strArray = line.split(":", 2); + if (strArray.length == 2 && + strArray[0].trim().equalsIgnoreCase("END") && + strArray[1].trim().equalsIgnoreCase("VCARD")) { + return; + } else if (!allowGarbage) { + throw new VCardException("END:VCARD != \"" + mPreviousLine + "\""); + } + useCache = false; + } while (allowGarbage); } /** @@ -205,32 +342,33 @@ public class VCardParser_V21 { boolean ended = false; if (mBuilder != null) { + long start = System.currentTimeMillis(); mBuilder.startProperty(); + mTimeStartProperty += System.currentTimeMillis() - start; } - - try { - ended = parseItem(); - } finally { - if (mBuilder != null) { - mBuilder.endProperty(); - } + ended = parseItem(); + if (mBuilder != null && !ended) { + long start = System.currentTimeMillis(); + mBuilder.endProperty(); + mTimeEndProperty += System.currentTimeMillis() - start; } while (!ended) { // follow VCARD ,it wont reach endProperty if (mBuilder != null) { + long start = System.currentTimeMillis(); mBuilder.startProperty(); + mTimeStartProperty += System.currentTimeMillis() - start; } - try { - ended = parseItem(); - } finally { - if (mBuilder != null) { - mBuilder.endProperty(); - } + ended = parseItem(); + if (mBuilder != null && !ended) { + long start = System.currentTimeMillis(); + mBuilder.endProperty(); + mTimeEndProperty += System.currentTimeMillis() - start; } } } - + /** * item = [groups "."] name [params] ":" value CRLF * / [groups "."] "ADR" [params] ":" addressparts CRLF @@ -241,57 +379,134 @@ public class VCardParser_V21 { protected boolean parseItem() throws IOException, VCardException { mEncoding = sDefaultEncoding; - // params = ";" [ws] paramlist String line = getNonEmptyLine(); - String[] strArray = line.split(":", 2); - if (strArray.length < 2) { - throw new VCardException("Invalid line(\":\" does not exist): " + line); - } - String propertyValue = strArray[1]; - String[] groupNameParamsArray = strArray[0].split(";"); - String groupAndName = groupNameParamsArray[0].trim(); - String[] groupNameArray = groupAndName.split("\\."); - int length = groupNameArray.length; - String propertyName = groupNameArray[length - 1]; - if (mBuilder != null) { - mBuilder.propertyName(propertyName); - for (int i = 0; i < length - 1; i++) { - mBuilder.propertyGroup(groupNameArray[i]); - } - } - if (propertyName.equalsIgnoreCase("END")) { - mPreviousLine = line; + long start = System.currentTimeMillis(); + + String[] propertyNameAndValue = separateLineAndHandleGroup(line); + if (propertyNameAndValue == null) { return true; } - - length = groupNameParamsArray.length; - for (int i = 1; i < length; i++) { - handleParams(groupNameParamsArray[i]); + if (propertyNameAndValue.length != 2) { + throw new VCardException("Invalid line \"" + line + "\""); } - - if (isValidPropertyName(propertyName) || - propertyName.startsWith("X-")) { - if (propertyName.equals("VERSION") && - !propertyValue.equals(getVersion())) { - throw new VCardVersionException("Incompatible version: " + - propertyValue + " != " + getVersion()); - } - handlePropertyValue(propertyName, propertyValue); - return false; - } else if (propertyName.equals("ADR") || + String propertyName = propertyNameAndValue[0].toUpperCase(); + String propertyValue = propertyNameAndValue[1]; + + mTimeParseItem1 += System.currentTimeMillis() - start; + + if (propertyName.equals("ADR") || propertyName.equals("ORG") || propertyName.equals("N")) { + start = System.currentTimeMillis(); handleMultiplePropertyValue(propertyName, propertyValue); + mTimeParseItem3 += System.currentTimeMillis() - start; return false; } else if (propertyName.equals("AGENT")) { handleAgent(propertyValue); return false; + } else if (isValidPropertyName(propertyName)) { + if (propertyName.equals("BEGIN")) { + if (propertyValue.equals("VCARD")) { + throw new VCardNestedException("This vCard has nested vCard data in it."); + } else { + throw new VCardException("Unknown BEGIN type: " + propertyValue); + } + } else if (propertyName.equals("VERSION") && + !propertyValue.equals(getVersion())) { + throw new VCardVersionException("Incompatible version: " + + propertyValue + " != " + getVersion()); + } + start = System.currentTimeMillis(); + handlePropertyValue(propertyName, propertyValue); + mTimeParseItem2 += System.currentTimeMillis() - start; + return false; } throw new VCardException("Unknown property name: \"" + propertyName + "\""); } + static private final int STATE_GROUP_OR_PROPNAME = 0; + static private final int STATE_PARAMS = 1; + // vCard 3.1 specification allows double-quoted param-value, while vCard 2.1 does not. + // This is just for safety. + static private final int STATE_PARAMS_IN_DQUOTE = 2; + + protected String[] separateLineAndHandleGroup(String line) throws VCardException { + int length = line.length(); + int state = STATE_GROUP_OR_PROPNAME; + int nameIndex = 0; + + String[] propertyNameAndValue = new String[2]; + + for (int i = 0; i < length; i++) { + char ch = line.charAt(i); + switch (state) { + case STATE_GROUP_OR_PROPNAME: + if (ch == ':') { + String propertyName = line.substring(nameIndex, i); + if (propertyName.equalsIgnoreCase("END")) { + mPreviousLine = line; + return null; + } + if (mBuilder != null) { + mBuilder.propertyName(propertyName); + } + propertyNameAndValue[0] = propertyName; + if (i < length - 1) { + propertyNameAndValue[1] = line.substring(i + 1); + } else { + propertyNameAndValue[1] = ""; + } + return propertyNameAndValue; + } else if (ch == '.') { + String groupName = line.substring(nameIndex, i); + if (mBuilder != null) { + mBuilder.propertyGroup(groupName); + } + nameIndex = i + 1; + } else if (ch == ';') { + String propertyName = line.substring(nameIndex, i); + if (propertyName.equalsIgnoreCase("END")) { + mPreviousLine = line; + return null; + } + if (mBuilder != null) { + mBuilder.propertyName(propertyName); + } + propertyNameAndValue[0] = propertyName; + nameIndex = i + 1; + state = STATE_PARAMS; + } + break; + case STATE_PARAMS: + if (ch == '"') { + state = STATE_PARAMS_IN_DQUOTE; + } else if (ch == ';') { + handleParams(line.substring(nameIndex, i)); + nameIndex = i + 1; + } else if (ch == ':') { + handleParams(line.substring(nameIndex, i)); + if (i < length - 1) { + propertyNameAndValue[1] = line.substring(i + 1); + } else { + propertyNameAndValue[1] = ""; + } + return propertyNameAndValue; + } + break; + case STATE_PARAMS_IN_DQUOTE: + if (ch == '"') { + state = STATE_PARAMS; + } + break; + } + } + + throw new VCardException("Invalid line: \"" + line + "\""); + } + + /** * params = ";" [ws] paramlist * paramlist = paramlist [ws] ";" [ws] param @@ -330,18 +545,19 @@ public class VCardParser_V21 { } /** - * typeval = knowntype / "X-" word + * ptypeval = knowntype / "X-" word */ - protected void handleType(String ptypeval) throws VCardException { - if (sKnownTypeSet.contains(ptypeval.toUpperCase()) || - ptypeval.startsWith("X-")) { - if (mBuilder != null) { - mBuilder.propertyParamType("TYPE"); - mBuilder.propertyParamValue(ptypeval.toUpperCase()); - } - } else { - throw new VCardException("Unknown type: \"" + ptypeval + "\""); - } + protected void handleType(String ptypeval) { + String upperTypeValue = ptypeval; + if (!(sKnownTypeSet.contains(upperTypeValue) || upperTypeValue.startsWith("X-")) && + !mWarningValueMap.contains(ptypeval)) { + mWarningValueMap.add(ptypeval); + Log.w(LOG_TAG, "Type unsupported by vCard 2.1: " + ptypeval); + } + if (mBuilder != null) { + mBuilder.propertyParamType("TYPE"); + mBuilder.propertyParamValue(upperTypeValue); + } } /** @@ -427,31 +643,48 @@ public class VCardParser_V21 { protected void handlePropertyValue( String propertyName, String propertyValue) throws IOException, VCardException { - if (mEncoding == null || mEncoding.equalsIgnoreCase("7BIT") - || mEncoding.equalsIgnoreCase("8BIT") - || mEncoding.toUpperCase().startsWith("X-")) { - if (mBuilder != null) { - ArrayList<String> v = new ArrayList<String>(); - v.add(maybeUnescapeText(propertyValue)); - mBuilder.propertyValues(v); - } - } else if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { + if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { + long start = System.currentTimeMillis(); String result = getQuotedPrintable(propertyValue); if (mBuilder != null) { ArrayList<String> v = new ArrayList<String>(); v.add(result); mBuilder.propertyValues(v); } + mTimeHandlePropertyValue2 += System.currentTimeMillis() - start; } else if (mEncoding.equalsIgnoreCase("BASE64") || mEncoding.equalsIgnoreCase("B")) { - String result = getBase64(propertyValue); + long start = System.currentTimeMillis(); + // It is very rare, but some BASE64 data may be so big that + // OutOfMemoryError occurs. To ignore such cases, use try-catch. + try { + String result = getBase64(propertyValue); + if (mBuilder != null) { + ArrayList<String> v = new ArrayList<String>(); + v.add(result); + mBuilder.propertyValues(v); + } + } catch (OutOfMemoryError error) { + Log.e(LOG_TAG, "OutOfMemoryError happened during parsing BASE64 data!"); + if (mBuilder != null) { + mBuilder.propertyValues(null); + } + } + mTimeHandlePropertyValue3 += System.currentTimeMillis() - start; + } else { + if (!(mEncoding == null || mEncoding.equalsIgnoreCase("7BIT") + || mEncoding.equalsIgnoreCase("8BIT") + || mEncoding.toUpperCase().startsWith("X-"))) { + Log.w(LOG_TAG, "The encoding unsupported by vCard spec: \"" + mEncoding + "\"."); + } + + long start = System.currentTimeMillis(); if (mBuilder != null) { ArrayList<String> v = new ArrayList<String>(); - v.add(result); + v.add(maybeUnescapeText(propertyValue)); mBuilder.propertyValues(v); - } - } else { - throw new VCardException("Unknown encoding: \"" + mEncoding + "\""); + } + mTimeHandlePropertyValue1 += System.currentTimeMillis() - start; } } @@ -546,57 +779,51 @@ public class VCardParser_V21 { if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) { propertyValue = getQuotedPrintable(propertyValue); } - - if (propertyValue.endsWith("\\")) { + + if (mBuilder != null) { + // TODO: limit should be set in accordance with propertyName? StringBuilder builder = new StringBuilder(); - // builder.append(propertyValue); - builder.append(propertyValue.substring(0, propertyValue.length() - 1)); - try { - String line; - while (true) { - line = getNonEmptyLine(); - // builder.append("\r\n"); - // builder.append(line); - if (!line.endsWith("\\")) { - builder.append(line); - break; + ArrayList<String> list = new ArrayList<String>(); + int length = propertyValue.length(); + for (int i = 0; i < length; i++) { + char ch = propertyValue.charAt(i); + if (ch == '\\' && i < length - 1) { + char nextCh = propertyValue.charAt(i + 1); + String unescapedString = maybeUnescape(nextCh); + if (unescapedString != null) { + builder.append(unescapedString); + i++; } else { - builder.append(line.substring(0, line.length() - 1)); + builder.append(ch); } + } else if (ch == ';') { + list.add(builder.toString()); + builder = new StringBuilder(); + } else { + builder.append(ch); } - } catch (IOException e) { - throw new VCardException( - "IOException is throw during reading propertyValue" + e); } - // Now, propertyValue may contain "\r\n" - propertyValue = builder.toString(); - } - - if (mBuilder != null) { - // In String#replaceAll() and Pattern class, "\\\\" means single slash. - - final String IMPOSSIBLE_STRING = "\0"; - // First replace two backslashes with impossible strings. - propertyValue = propertyValue.replaceAll("\\\\\\\\", IMPOSSIBLE_STRING); - - // Now, split propertyValue with ; whose previous char is not back slash. - Pattern pattern = Pattern.compile("(?<!\\\\);"); - // TODO: limit should be set in accordance with propertyName? - String[] strArray = pattern.split(propertyValue, -1); - ArrayList<String> arrayList = new ArrayList<String>(); - for (String str : strArray) { - // Replace impossible strings with original two backslashes - arrayList.add( - unescapeText(str.replaceAll(IMPOSSIBLE_STRING, "\\\\\\\\"))); - } - mBuilder.propertyValues(arrayList); + list.add(builder.toString()); + mBuilder.propertyValues(list); } } /** * vCard 2.1 specifies AGENT allows one vcard entry. It is not encoded at all. + * + * item = ... + * / [groups "."] "AGENT" + * [params] ":" vcard CRLF + * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF + * items *CRLF "END" [ws] ":" [ws] "VCARD" + * */ - protected void handleAgent(String propertyValue) throws IOException, VCardException { + protected void handleAgent(String propertyValue) throws VCardException { + throw new VCardException("AGENT Property is not supported."); + /* This is insufficient support. Also, AGENT Property is very rare. + Ignore it for now. + TODO: fix this. + String[] strArray = propertyValue.split(":", 2); if (!(strArray.length == 2 || strArray[0].trim().equalsIgnoreCase("BEGIN") && @@ -605,6 +832,7 @@ public class VCardParser_V21 { } parseItems(); readEndVCard(); + */ } /** @@ -615,17 +843,18 @@ public class VCardParser_V21 { } /** - * Convert escaped text into unescaped text. + * Returns unescaped String if the character should be unescaped. Return null otherwise. + * e.g. In vCard 2.1, "\;" should be unescaped into ";" while "\x" should not be. */ - protected String unescapeText(String text) { + protected String maybeUnescape(char ch) { // Original vCard 2.1 specification does not allow transformation // "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous implementation of // this class allowed them, so keep it as is. - // In String#replaceAll(), "\\\\" means single slash. - return text.replaceAll("\\\\;", ";") - .replaceAll("\\\\:", ":") - .replaceAll("\\\\,", ",") - .replaceAll("\\\\\\\\", "\\\\"); + if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') { + return String.valueOf(ch); + } else { + return null; + } } /** @@ -656,12 +885,15 @@ public class VCardParser_V21 { */ public boolean parse(InputStream is, String charset, VBuilder builder) throws IOException, VCardException { + // TODO: make this count error entries instead of just throwing VCardException. + // TODO: If we really need to allow only CRLF as line break, // we will have to develop our own BufferedReader(). - mReader = new BufferedReader(new InputStreamReader(is, charset)); + mReader = new CustomBufferedReader(new InputStreamReader(is, charset)); mBuilder = builder; + long start = System.currentTimeMillis(); if (mBuilder != null) { mBuilder.start(); } @@ -669,9 +901,50 @@ public class VCardParser_V21 { if (mBuilder != null) { mBuilder.end(); } + mTimeTotal += System.currentTimeMillis() - start; + return true; } + public boolean parse(InputStream is, VBuilder builder) throws IOException, VCardException { + return parse(is, DEFAULT_CHARSET, builder); + } + + /** + * Cancel parsing. + * Actual cancel is done after the end of the current one vcard entry parsing. + */ + public void cancel() { + mCanceled = true; + } + + /** + * It is very, very rare case, but there is a case where + * canceled may be already true outside this object. + * @hide + */ + public void parse(InputStream is, String charset, VBuilder builder, boolean canceled) + throws IOException, VCardException { + mCanceled = canceled; + parse(is, charset, builder); + } + + public void showDebugInfo() { + Log.d(LOG_TAG, "total parsing time: " + mTimeTotal + " ms"); + if (mReader instanceof CustomBufferedReader) { + Log.d(LOG_TAG, "total readLine time: " + + ((CustomBufferedReader)mReader).getTotalmillisecond() + " ms"); + } + Log.d(LOG_TAG, "mTimeStartRecord: " + mTimeStartRecord + " ms"); + Log.d(LOG_TAG, "mTimeEndRecord: " + mTimeEndRecord + " ms"); + Log.d(LOG_TAG, "mTimeParseItem1: " + mTimeParseItem1 + " ms"); + Log.d(LOG_TAG, "mTimeParseItem2: " + mTimeParseItem2 + " ms"); + Log.d(LOG_TAG, "mTimeParseItem3: " + mTimeParseItem3 + " ms"); + Log.d(LOG_TAG, "mTimeHandlePropertyValue1: " + mTimeHandlePropertyValue1 + " ms"); + Log.d(LOG_TAG, "mTimeHandlePropertyValue2: " + mTimeHandlePropertyValue2 + " ms"); + Log.d(LOG_TAG, "mTimeHandlePropertyValue3: " + mTimeHandlePropertyValue3 + " ms"); + } + private boolean isLetter(char ch) { if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { return true; @@ -679,3 +952,24 @@ public class VCardParser_V21 { return false; } } + +class CustomBufferedReader extends BufferedReader { + private long mTime; + + public CustomBufferedReader(Reader in) { + super(in); + } + + @Override + public String readLine() throws IOException { + long start = System.currentTimeMillis(); + String ret = super.readLine(); + long end = System.currentTimeMillis(); + mTime += end - start; + return ret; + } + + public long getTotalmillisecond() { + return mTime; + } +} diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V30.java b/core/java/android/syncml/pim/vcard/VCardParser_V30.java index 901bd49..e67525e 100644 --- a/core/java/android/syncml/pim/vcard/VCardParser_V30.java +++ b/core/java/android/syncml/pim/vcard/VCardParser_V30.java @@ -16,8 +16,9 @@ package android.syncml.pim.vcard; +import android.util.Log; + import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -26,9 +27,11 @@ import java.util.HashSet; * Please refer to vCard Specification 3.0 (http://tools.ietf.org/html/rfc2426) */ public class VCardParser_V30 extends VCardParser_V21 { + private static final String LOG_TAG = "VCardParser_V30"; + private static final HashSet<String> acceptablePropsWithParam = new HashSet<String>( Arrays.asList( - "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", + "BEGIN", "LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND", "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL", "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER", // 2.1 "NAME", "PROFILE", "SOURCE", "NICKNAME", "CLASS", @@ -51,8 +54,14 @@ public class VCardParser_V30 extends VCardParser_V21 { @Override protected boolean isValidPropertyName(String propertyName) { - return acceptablePropsWithParam.contains(propertyName) || - acceptablePropsWithoutParam.contains(propertyName); + if (!(acceptablePropsWithParam.contains(propertyName) || + acceptablePropsWithoutParam.contains(propertyName) || + propertyName.startsWith("X-")) && + !mWarningValueMap.contains(propertyName)) { + mWarningValueMap.add(propertyName); + Log.w(LOG_TAG, "Property name unsupported by vCard 3.0: " + propertyName); + } + return true; } @Override @@ -100,7 +109,21 @@ public class VCardParser_V30 extends VCardParser_V21 { } } else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') { if (builder != null) { - // TODO: Check whether MIME requires only one whitespace. + // See Section 5.8.1 of RFC 2425 (MIME-DIR document). + // Following is the excerpts from it. + // + // DESCRIPTION:This is a long description that exists on a long line. + // + // Can be represented as: + // + // DESCRIPTION:This is a long description + // that exists on a long line. + // + // It could also be represented as: + // + // DESCRIPTION:This is a long descrip + // tion that exists o + // n a long line. builder.append(line.substring(1)); } else if (mPreviousLine != null) { builder = new StringBuilder(); @@ -113,10 +136,13 @@ public class VCardParser_V30 extends VCardParser_V21 { } else { if (mPreviousLine == null) { mPreviousLine = line; + if (builder != null) { + return builder.toString(); + } } else { String ret = mPreviousLine; mPreviousLine = line; - return ret; + return ret; } } } @@ -130,15 +156,16 @@ public class VCardParser_V30 extends VCardParser_V21 { * [group "."] "END" ":" "VCARD" 1*CRLF */ @Override - protected boolean readBeginVCard() throws IOException, VCardException { + protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException { // TODO: vCard 3.0 supports group. - return super.readBeginVCard(); + return super.readBeginVCard(allowGarbage); } @Override - protected void readEndVCard() throws VCardException { + protected void readEndVCard(boolean useCache, boolean allowGarbage) + throws IOException, VCardException { // TODO: vCard 3.0 supports group. - super.readEndVCard(); + super.readEndVCard(useCache, allowGarbage); } /** @@ -214,23 +241,6 @@ public class VCardParser_V30 extends VCardParser_V21 { throw new VCardException("AGENT in vCard 3.0 is not supported yet."); } - // vCard 3.0 supports "B" as BASE64 encoding. - @Override - protected void handlePropertyValue( - String propertyName, String propertyValue) throws - IOException, VCardException { - if (mEncoding != null && mEncoding.equalsIgnoreCase("B")) { - String result = getBase64(propertyValue); - if (mBuilder != null) { - ArrayList<String> v = new ArrayList<String>(); - v.add(result); - mBuilder.propertyValues(v); - } - } - - super.handlePropertyValue(propertyName, propertyValue); - } - /** * vCard 3.0 does not require two CRLF at the last of BASE64 data. * It only requires that data should be MIME-encoded. @@ -259,27 +269,38 @@ public class VCardParser_V30 extends VCardParser_V21 { } /** - * Return unescapeText(text). - * In vCard 3.0, 8bit text is always encoded. - */ - @Override - protected String maybeUnescapeText(String text) { - return unescapeText(text); - } - - /** * ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N") * ; \\ encodes \, \n or \N encodes newline * ; \; encodes ;, \, encodes , - */ + * + * Note: Apple escape ':' into '\:' while does not escape '\' + */ @Override - protected String unescapeText(String text) { - // In String#replaceAll(), "\\\\" means single slash. - return text.replaceAll("\\\\;", ";") - .replaceAll("\\\\:", ":") - .replaceAll("\\\\,", ",") - .replaceAll("\\\\n", "\r\n") - .replaceAll("\\\\N", "\r\n") - .replaceAll("\\\\\\\\", "\\\\"); + protected String maybeUnescapeText(String text) { + StringBuilder builder = new StringBuilder(); + int length = text.length(); + for (int i = 0; i < length; i++) { + char ch = text.charAt(i); + if (ch == '\\' && i < length - 1) { + char next_ch = text.charAt(++i); + if (next_ch == 'n' || next_ch == 'N') { + builder.append("\r\n"); + } else { + builder.append(next_ch); + } + } else { + builder.append(ch); + } + } + return builder.toString(); + } + + @Override + protected String maybeUnescape(char ch) { + if (ch == 'n' || ch == 'N') { + return "\r\n"; + } else { + return String.valueOf(ch); + } } } diff --git a/core/java/android/syncml/pim/vcard/VCardSourceDetector.java b/core/java/android/syncml/pim/vcard/VCardSourceDetector.java new file mode 100644 index 0000000..8c48391 --- /dev/null +++ b/core/java/android/syncml/pim/vcard/VCardSourceDetector.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.syncml.pim.vcard; + +import android.syncml.pim.VBuilder; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Class which tries to detects the source of the vCard from its properties. + * Currently this implementation is very premature. + * @hide + */ +public class VCardSourceDetector implements VBuilder { + // Should only be used in package. + static final int TYPE_UNKNOWN = 0; + static final int TYPE_APPLE = 1; + static final int TYPE_JAPANESE_MOBILE_PHONE = 2; // Used in Japanese mobile phones. + static final int TYPE_FOMA = 3; // Used in some Japanese FOMA mobile phones. + static final int TYPE_WINDOWS_MOBILE_JP = 4; + // TODO: Excel, etc. + + private static Set<String> APPLE_SIGNS = new HashSet<String>(Arrays.asList( + "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", "X-PHONETIC-LAST-NAME", + "X-ABADR", "X-ABUID")); + + private static Set<String> JAPANESE_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList( + "X-GNO", "X-GN", "X-REDUCTION")); + + private static Set<String> WINDOWS_MOBILE_PHONE_SIGNS = new HashSet<String>(Arrays.asList( + "X-MICROSOFT-ASST_TEL", "X-MICROSOFT-ASSISTANT", "X-MICROSOFT-OFFICELOC")); + + // Note: these signes appears before the signs of the other type (e.g. "X-GN"). + // In other words, Japanese FOMA mobile phones are detected as FOMA, not JAPANESE_MOBILE_PHONES. + private static Set<String> FOMA_SIGNS = new HashSet<String>(Arrays.asList( + "X-SD-VERN", "X-SD-FORMAT_VER", "X-SD-CATEGORIES", "X-SD-CLASS", "X-SD-DCREATED", + "X-SD-DESCRIPTION")); + private static String TYPE_FOMA_CHARSET_SIGN = "X-SD-CHAR_CODE"; + + private int mType = TYPE_UNKNOWN; + // Some mobile phones (like FOMA) tells us the charset of the data. + private boolean mNeedParseSpecifiedCharset; + private String mSpecifiedCharset; + + public void start() { + } + + public void end() { + } + + public void startRecord(String type) { + } + + public void startProperty() { + mNeedParseSpecifiedCharset = false; + } + + public void endProperty() { + } + + public void endRecord() { + } + + public void propertyGroup(String group) { + } + + public void propertyName(String name) { + if (name.equalsIgnoreCase(TYPE_FOMA_CHARSET_SIGN)) { + mType = TYPE_FOMA; + mNeedParseSpecifiedCharset = true; + return; + } + if (mType != TYPE_UNKNOWN) { + return; + } + if (WINDOWS_MOBILE_PHONE_SIGNS.contains(name)) { + mType = TYPE_WINDOWS_MOBILE_JP; + } else if (FOMA_SIGNS.contains(name)) { + mType = TYPE_FOMA; + } else if (JAPANESE_MOBILE_PHONE_SIGNS.contains(name)) { + mType = TYPE_JAPANESE_MOBILE_PHONE; + } else if (APPLE_SIGNS.contains(name)) { + mType = TYPE_APPLE; + } + } + + public void propertyParamType(String type) { + } + + public void propertyParamValue(String value) { + } + + public void propertyValues(List<String> values) { + if (mNeedParseSpecifiedCharset && values.size() > 0) { + mSpecifiedCharset = values.get(0); + } + } + + int getType() { + return mType; + } + + /** + * Return charset String guessed from the source's properties. + * This method must be called after parsing target file(s). + * @return Charset String. Null is returned if guessing the source fails. + */ + public String getEstimatedCharset() { + if (mSpecifiedCharset != null) { + return mSpecifiedCharset; + } + switch (mType) { + case TYPE_WINDOWS_MOBILE_JP: + case TYPE_FOMA: + case TYPE_JAPANESE_MOBILE_PHONE: + return "SHIFT_JIS"; + case TYPE_APPLE: + return "UTF-8"; + default: + return null; + } + } +} diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java index 9bafa32..de0587a 100644 --- a/core/java/android/test/AndroidTestCase.java +++ b/core/java/android/test/AndroidTestCase.java @@ -16,12 +16,14 @@ package android.test; +import android.content.ContentValues; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import junit.framework.TestCase; import java.lang.reflect.Field; -import junit.framework.TestCase; - /** * Extend this if you need to access Resources or other things that depend on Activity Context. */ @@ -53,6 +55,72 @@ public class AndroidTestCase extends TestCase { } /** + * Asserts that launching a given activity is protected by a particular permission by + * attempting to start the activity and validating that a {@link SecurityException} + * is thrown that mentions the permission in its error message. + * + * Note that an instrumentation isn't needed because all we are looking for is a security error + * and we don't need to wait for the activity to launch and get a handle to the activity. + * + * @param packageName The package name of the activity to launch. + * @param className The class of the activity to launch. + * @param permission The name of the permission. + */ + public void assertActivityRequiresPermission( + String packageName, String className, String permission) { + final Intent intent = new Intent(); + intent.setClassName(packageName, className); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + try { + getContext().startActivity(intent); + fail("expected security exception for " + permission); + } catch (SecurityException expected) { + assertNotNull("security exception's error message.", expected.getMessage()); + assertTrue("error message should contain " + permission + ".", + expected.getMessage().contains(permission)); + } + } + + + /** + * Asserts that reading from the content uri requires a particular permission by querying the + * uri and ensuring a {@link SecurityException} is thrown mentioning the particular permission. + * + * @param uri The uri that requires a permission to query. + * @param permission The permission that should be required. + */ + public void assertReadingContentUriRequiresPermission(Uri uri, String permission) { + try { + getContext().getContentResolver().query(uri, null, null, null, null); + fail("expected SecurityException requiring " + permission); + } catch (SecurityException expected) { + assertNotNull("security exception's error message.", expected.getMessage()); + assertTrue("error message should contain " + permission + ".", + expected.getMessage().contains(permission)); + } + } + + /** + * Asserts that writing to the content uri requires a particular permission by inserting into + * the uri and ensuring a {@link SecurityException} is thrown mentioning the particular + * permission. + * + * @param uri The uri that requires a permission to query. + * @param permission The permission that should be required. + */ + public void assertWritingContentUriRequiresPermission(Uri uri, String permission) { + try { + getContext().getContentResolver().insert(uri, new ContentValues()); + fail("expected SecurityException requiring " + permission); + } catch (SecurityException expected) { + assertNotNull("security exception's error message.", expected.getMessage()); + assertTrue("error message should contain " + permission + ".", + expected.getMessage().contains(permission)); + } + } + + /** * This function is called by various TestCase implementations, at tearDown() time, in order * to scrub out any class variables. This protects against memory leaks in the case where a * test case creates a non-static inner class (thus referencing the test case) and gives it to diff --git a/core/java/android/test/InstrumentationTestCase.java b/core/java/android/test/InstrumentationTestCase.java index 470ab0d..2145d7c 100644 --- a/core/java/android/test/InstrumentationTestCase.java +++ b/core/java/android/test/InstrumentationTestCase.java @@ -241,7 +241,13 @@ public class InstrumentationTestCase extends TestCase { try { final Field keyCodeField = KeyEvent.class.getField("KEYCODE_" + key); final int keyCode = keyCodeField.getInt(null); - instrumentation.sendKeyDownUpSync(keyCode); + try { + instrumentation.sendKeyDownUpSync(keyCode); + } catch (SecurityException e) { + // Ignore security exceptions that are now thrown + // when trying to send to another app, to retain + // compatibility with existing tests. + } } catch (NoSuchFieldException e) { Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key); break; @@ -266,7 +272,13 @@ public class InstrumentationTestCase extends TestCase { final Instrumentation instrumentation = getInstrumentation(); for (int i = 0; i < count; i++) { - instrumentation.sendKeyDownUpSync(keys[i]); + try { + instrumentation.sendKeyDownUpSync(keys[i]); + } catch (SecurityException e) { + // Ignore security exceptions that are now thrown + // when trying to send to another app, to retain + // compatibility with existing tests. + } } instrumentation.waitForIdleSync(); @@ -292,7 +304,13 @@ public class InstrumentationTestCase extends TestCase { final int keyCount = keys[i]; final int keyCode = keys[i + 1]; for (int j = 0; j < keyCount; j++) { - instrumentation.sendKeyDownUpSync(keyCode); + try { + instrumentation.sendKeyDownUpSync(keyCode); + } catch (SecurityException e) { + // Ignore security exceptions that are now thrown + // when trying to send to another app, to retain + // compatibility with existing tests. + } } } diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java index 27c703f..9045c09 100644 --- a/core/java/android/text/LoginFilter.java +++ b/core/java/android/text/LoginFilter.java @@ -49,10 +49,6 @@ public abstract class LoginFilter implements InputFilter { */ public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { - char[] out = new char[end - start]; // reserve enough space for whole string - int outidx = 0; - boolean changed = false; - onStart(); // Scan through beginning characters in dest, calling onInvalidCharacter() @@ -63,14 +59,26 @@ public abstract class LoginFilter implements InputFilter { } // Scan through changed characters rejecting disallowed chars + SpannableStringBuilder modification = null; + int modoff = 0; + for (int i = start; i < end; i++) { char c = source.charAt(i); if (isAllowed(c)) { - // Character allowed. Add it to the sequence. - out[outidx++] = c; + // Character allowed. + modoff++; } else { - if (mAppendInvalid) out[outidx++] = c; - else changed = true; // we changed the original string + if (mAppendInvalid) { + modoff++; + } else { + if (modification == null) { + modification = new SpannableStringBuilder(source, start, end); + modoff = i - start; + } + + modification.delete(modoff, modoff + 1); + } + onInvalidCharacter(c); } } @@ -84,20 +92,9 @@ public abstract class LoginFilter implements InputFilter { onStop(); - if (!changed) { - return null; - } - - String s = new String(out, 0, outidx); - - if (source instanceof Spanned) { - SpannableString sp = new SpannableString(s); - TextUtils.copySpansFrom((Spanned) source, - start, end, null, sp, 0); - return sp; - } else { - return s; - } + // Either returns null if we made no changes, + // or what we wanted to change it to if there were changes. + return modification; } /** diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 5b4c380..53096dd 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -916,6 +916,17 @@ public class TextUtils { sp.setSpan(o, p.readInt(), p.readInt(), p.readInt()); } + /** + * Copies the spans from the region <code>start...end</code> in + * <code>source</code> to the region + * <code>destoff...destoff+end-start</code> in <code>dest</code>. + * Spans in <code>source</code> that begin before <code>start</code> + * or end after <code>end</code> but overlap this range are trimmed + * as if they began at <code>start</code> or ended at <code>end</code>. + * + * @throws IndexOutOfBoundsException if any of the copied spans + * are out of range in <code>dest</code>. + */ public static void copySpansFrom(Spanned source, int start, int end, Class kind, Spannable dest, int destoff) { diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 0dc96c3..3d10f17 100644 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -242,7 +242,7 @@ public class DateFormat { /** * Returns a {@link java.text.DateFormat} object that can format the time according - * to the current user preference. + * to the current locale and the user's 12-/24-hour clock preference. * @param context the application context * @return the {@link java.text.DateFormat} object that properly formats the time. */ @@ -260,46 +260,88 @@ public class DateFormat { } /** - * Returns a {@link java.text.DateFormat} object that can format the date according - * to the current user preference. + * Returns a {@link java.text.DateFormat} object that can format the date + * in short form (such as 12/31/1999) according + * to the current locale and the user's date-order preference. * @param context the application context * @return the {@link java.text.DateFormat} object that properly formats the date. */ public static final java.text.DateFormat getDateFormat(Context context) { - String value = getDateFormatString(context); + String value = Settings.System.getString(context.getContentResolver(), + Settings.System.DATE_FORMAT); + + return getDateFormatForSetting(context, value); + } + + /** + * Returns a {@link java.text.DateFormat} object to format the date + * as if the date format setting were set to <code>value</code>, + * including null to use the locale's default format. + * @param context the application context + * @param value the date format setting string to interpret for + * the current locale + * @hide + */ + public static java.text.DateFormat getDateFormatForSetting(Context context, + String value) { + if (value != null) { + int month = value.indexOf('M'); + int day = value.indexOf('d'); + int year = value.indexOf('y'); + + if (month >= 0 && day >= 0 && year >= 0) { + String template = context.getString(R.string.numeric_date_template); + if (year < month) { + if (month < day) { + value = String.format(template, "yyyy", "MM", "dd"); + } else { + value = String.format(template, "yyyy", "dd", "MM"); + } + } else if (month < day) { + if (day < year) { + value = String.format(template, "MM", "dd", "yyyy"); + } else { // unlikely + value = String.format(template, "MM", "yyyy", "dd"); + } + } else { // day < month + if (month < year) { + value = String.format(template, "dd", "MM", "yyyy"); + } else { // unlikely + value = String.format(template, "dd", "yyyy", "MM"); + } + } + + return new java.text.SimpleDateFormat(value); + } + } + + /* + * The setting is not set; use the default. + * We use a resource string here instead of just DateFormat.SHORT + * so that we get a four-digit year instead a two-digit year. + */ + value = context.getString(R.string.numeric_date_format); return new java.text.SimpleDateFormat(value); } /** * Returns a {@link java.text.DateFormat} object that can format the date - * in long form (such as December 31, 1999) based on user preference. + * in long form (such as December 31, 1999) for the current locale. * @param context the application context * @return the {@link java.text.DateFormat} object that formats the date in long form. */ public static final java.text.DateFormat getLongDateFormat(Context context) { - String value = getDateFormatString(context); - if (value.indexOf('M') < value.indexOf('d')) { - value = context.getString(R.string.full_date_month_first); - } else { - value = context.getString(R.string.full_date_day_first); - } - return new java.text.SimpleDateFormat(value); + return java.text.DateFormat.getDateInstance(java.text.DateFormat.LONG); } /** * Returns a {@link java.text.DateFormat} object that can format the date - * in medium form (such as Dec. 31, 1999) based on user preference. + * in medium form (such as Dec. 31, 1999) for the current locale. * @param context the application context * @return the {@link java.text.DateFormat} object that formats the date in long form. */ public static final java.text.DateFormat getMediumDateFormat(Context context) { - String value = getDateFormatString(context); - if (value.indexOf('M') < value.indexOf('d')) { - value = context.getString(R.string.medium_date_month_first); - } else { - value = context.getString(R.string.medium_date_day_first); - } - return new java.text.SimpleDateFormat(value); + return java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM); } /** @@ -338,6 +380,12 @@ public class DateFormat { } private static String getDateFormatString(Context context) { + java.text.DateFormat df; + df = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT); + if (df instanceof SimpleDateFormat) { + return ((SimpleDateFormat) df).toPattern(); + } + String value = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT); if (value == null || value.length() < 6) { diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java index 8a7cdd9..1a4eb69 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -62,15 +62,6 @@ public class DateUtils com.android.internal.R.string.day_of_week_short_friday, com.android.internal.R.string.day_of_week_short_saturday, }; - private static final int[] sDaysShorter = new int[] { - com.android.internal.R.string.day_of_week_shorter_sunday, - com.android.internal.R.string.day_of_week_shorter_monday, - com.android.internal.R.string.day_of_week_shorter_tuesday, - com.android.internal.R.string.day_of_week_shorter_wednesday, - com.android.internal.R.string.day_of_week_shorter_thursday, - com.android.internal.R.string.day_of_week_shorter_friday, - com.android.internal.R.string.day_of_week_shorter_saturday, - }; private static final int[] sDaysShortest = new int[] { com.android.internal.R.string.day_of_week_shortest_sunday, com.android.internal.R.string.day_of_week_shortest_monday, @@ -80,6 +71,20 @@ public class DateUtils com.android.internal.R.string.day_of_week_shortest_friday, com.android.internal.R.string.day_of_week_shortest_saturday, }; + private static final int[] sMonthsStandaloneLong = new int [] { + com.android.internal.R.string.month_long_standalone_january, + com.android.internal.R.string.month_long_standalone_february, + com.android.internal.R.string.month_long_standalone_march, + com.android.internal.R.string.month_long_standalone_april, + com.android.internal.R.string.month_long_standalone_may, + com.android.internal.R.string.month_long_standalone_june, + com.android.internal.R.string.month_long_standalone_july, + com.android.internal.R.string.month_long_standalone_august, + com.android.internal.R.string.month_long_standalone_september, + com.android.internal.R.string.month_long_standalone_october, + com.android.internal.R.string.month_long_standalone_november, + com.android.internal.R.string.month_long_standalone_december, + }; private static final int[] sMonthsLong = new int [] { com.android.internal.R.string.month_long_january, com.android.internal.R.string.month_long_february, @@ -127,7 +132,7 @@ public class DateUtils com.android.internal.R.string.pm, }; private static Configuration sLastConfig; - private static String sStatusTimeFormat; + private static java.text.DateFormat sStatusTimeFormat; private static String sElapsedFormatMMSS; private static String sElapsedFormatHMMSS; @@ -142,6 +147,9 @@ public class DateUtils public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60; public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24; public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7; + /** + * This constant is actually the length of 364 days, not of a year! + */ public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52; // The following FORMAT_* symbols are used for specifying the format of @@ -171,8 +179,14 @@ public class DateUtils // Date and time format strings that are constant and don't need to be // translated. + /** + * This is not actually the preferred 24-hour date format in all locales. + */ public static final String HOUR_MINUTE_24 = "%H:%M"; public static final String MONTH_FORMAT = "%B"; + /** + * This is not actually a useful month name in all locales. + */ public static final String ABBREV_MONTH_FORMAT = "%b"; public static final String NUMERIC_MONTH_FORMAT = "%m"; public static final String MONTH_DAY_FORMAT = "%-d"; @@ -255,18 +269,15 @@ public class DateUtils * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}. * @more * <p>e.g. "Su" or "Jan" - * <p>In some languages, the results returned for LENGTH_SHORT may be the same as - * return for {@link #LENGTH_MEDIUM}. + * <p>In most languages, the results returned for LENGTH_SHORT will be the same as + * the results returned for {@link #LENGTH_MEDIUM}. */ public static final int LENGTH_SHORT = 30; /** * Request an even shorter abbreviated version of the name. - * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}. - * @more - * <p>e.g. "M", "Tu", "Th" or "J" - * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as - * return for {@link #LENGTH_SHORTER}. + * Do not use this. Currently this will always return the same result + * as {@link #LENGTH_SHORT}. */ public static final int LENGTH_SHORTER = 40; @@ -275,8 +286,8 @@ public class DateUtils * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}. * @more * <p>e.g. "S", "T", "T" or "J" - * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as - * return for {@link #LENGTH_SHORTER}. + * <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as + * the results returned for {@link #LENGTH_SHORT}. */ public static final int LENGTH_SHORTEST = 50; @@ -284,9 +295,12 @@ public class DateUtils * Return a string for the day of the week. * @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY}, * {@link Calendar#MONDAY Calendar.MONDAY}, etc. - * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER} - * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else - * will return the same as {#LENGTH_MEDIUM}. + * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, + * {@link #LENGTH_MEDIUM}, or {@link #LENGTH_SHORTEST}. + * Note that in most languages, {@link #LENGTH_SHORT} + * will return the same as {@link #LENGTH_MEDIUM}. + * Undefined lengths will return {@link #LENGTH_MEDIUM} + * but may return something different in the future. * @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds. */ public static String getDayOfWeekString(int dayOfWeek, int abbrev) { @@ -295,7 +309,7 @@ public class DateUtils case LENGTH_LONG: list = sDaysLong; break; case LENGTH_MEDIUM: list = sDaysMedium; break; case LENGTH_SHORT: list = sDaysShort; break; - case LENGTH_SHORTER: list = sDaysShorter; break; + case LENGTH_SHORTER: list = sDaysShort; break; case LENGTH_SHORTEST: list = sDaysShortest; break; default: list = sDaysMedium; break; } @@ -316,13 +330,14 @@ public class DateUtils } /** - * Return a localized string for the day of the week. + * Return a localized string for the month of the year. * @param month One of {@link Calendar#JANUARY Calendar.JANUARY}, * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc. - * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER} - * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else - * will return the same as {#LENGTH_MEDIUM}. - * @return Localized day of the week. + * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM}, + * or {@link #LENGTH_SHORTEST}. + * Undefined lengths will return {@link #LENGTH_MEDIUM} + * but may return something different in the future. + * @return Localized month of the year. */ public static String getMonthString(int month, int abbrev) { // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER. @@ -344,6 +359,40 @@ public class DateUtils } /** + * Return a localized string for the month of the year, for + * contexts where the month is not formatted together with + * a day of the month. + * + * @param month One of {@link Calendar#JANUARY Calendar.JANUARY}, + * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc. + * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM}, + * or {@link #LENGTH_SHORTEST}. + * Undefined lengths will return {@link #LENGTH_MEDIUM} + * but may return something different in the future. + * @return Localized month of the year. + * @hide Pending API council approval + */ + public static String getStandaloneMonthString(int month, int abbrev) { + // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER. + // This is a shortcut to not spam the translators with too many variations + // of the same string. If we find that in a language the distinction + // is necessary, we can can add more without changing this API. + int[] list; + switch (abbrev) { + case LENGTH_LONG: list = sMonthsStandaloneLong; + break; + case LENGTH_MEDIUM: list = sMonthsMedium; break; + case LENGTH_SHORT: list = sMonthsMedium; break; + case LENGTH_SHORTER: list = sMonthsMedium; break; + case LENGTH_SHORTEST: list = sMonthsShortest; break; + default: list = sMonthsMedium; break; + } + + Resources r = Resources.getSystem(); + return r.getString(list[month - Calendar.JANUARY]); + } + + /** * Returns a string describing the elapsed time since startTime. * @param startTime some time in the past. * @return a String object containing the elapsed time. @@ -572,7 +621,7 @@ public class DateUtils Configuration cfg = r.getConfiguration(); if (sLastConfig == null || !sLastConfig.equals(cfg)) { sLastConfig = cfg; - sStatusTimeFormat = r.getString(com.android.internal.R.string.status_bar_time_format); + sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT); sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss); sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss); } @@ -586,7 +635,7 @@ public class DateUtils */ public static final CharSequence timeString(long millis) { initFormatStrings(); - return DateFormat.format(sStatusTimeFormat, millis); + return sStatusTimeFormat.format(millis); } /** @@ -1066,7 +1115,9 @@ public class DateUtils * * <p> * If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM" - * and "PM" are capitalized. + * and "PM" are capitalized. You should not use this flag + * because in some locales these terms cannot be capitalized, and in + * many others it doesn't make sense to do so even though it is possible. * * <p> * If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is @@ -1074,15 +1125,19 @@ public class DateUtils * * <p> * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is - * shown instead of "noon". + * shown instead of "noon". You should probably not use this flag + * because in many locales it will not make sense to capitalize + * the term. * * <p> * If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is * shown instead of "midnight". * * <p> - * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Midnight" is - * shown instead of "midnight". + * If FORMAT_CAP_MIDNIGHT is set and 12-hour time is used, then "Midnight" + * is shown instead of "midnight". You should probably not use this + * flag because in many locales it will not make sense to capitalize + * the term. * * <p> * If FORMAT_12HOUR is set and the time is shown, then the time is @@ -1224,8 +1279,8 @@ public class DateUtils use24Hour = DateFormat.is24HourFormat(context); } if (use24Hour) { - startTimeFormat = HOUR_MINUTE_24; - endTimeFormat = HOUR_MINUTE_24; + startTimeFormat = endTimeFormat = + res.getString(com.android.internal.R.string.hour_minute_24); } else { boolean abbrevTime = (flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0; boolean capAMPM = (flags & FORMAT_CAP_AMPM) != 0; @@ -1392,7 +1447,8 @@ public class DateUtils if (numericDate) { monthFormat = NUMERIC_MONTH_FORMAT; } else if (abbrevMonth) { - monthFormat = ABBREV_MONTH_FORMAT; + monthFormat = + res.getString(com.android.internal.R.string.short_format_month); } else { monthFormat = MONTH_FORMAT; } diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java index 1b30aa0..367b26c 100644 --- a/core/java/android/text/format/Formatter.java +++ b/core/java/android/text/format/Formatter.java @@ -59,9 +59,15 @@ public final class Formatter { result = result / 1024; } if (result < 100) { - return String.format("%.2f%s", result, context.getText(suffix).toString()); + String value = String.format("%.2f", result); + return context.getResources(). + getString(com.android.internal.R.string.fileSizeSuffix, + value, context.getString(suffix)); } - return String.format("%.0f%s", result, context.getText(suffix).toString()); + String value = String.format("%.0f", result); + return context.getResources(). + getString(com.android.internal.R.string.fileSizeSuffix, + value, context.getString(suffix)); } /** diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index daa99c2..8eae111 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -135,6 +135,7 @@ public class Time { private static Locale sLocale; private static String[] sShortMonths; private static String[] sLongMonths; + private static String[] sLongStandaloneMonths; private static String[] sShortWeekdays; private static String[] sLongWeekdays; private static String sTimeOnlyFormat; @@ -321,6 +322,20 @@ public class Time { r.getString(com.android.internal.R.string.month_long_november), r.getString(com.android.internal.R.string.month_long_december), }; + sLongStandaloneMonths = new String[] { + r.getString(com.android.internal.R.string.month_long_standalone_january), + r.getString(com.android.internal.R.string.month_long_standalone_february), + r.getString(com.android.internal.R.string.month_long_standalone_march), + r.getString(com.android.internal.R.string.month_long_standalone_april), + r.getString(com.android.internal.R.string.month_long_standalone_may), + r.getString(com.android.internal.R.string.month_long_standalone_june), + r.getString(com.android.internal.R.string.month_long_standalone_july), + r.getString(com.android.internal.R.string.month_long_standalone_august), + r.getString(com.android.internal.R.string.month_long_standalone_september), + r.getString(com.android.internal.R.string.month_long_standalone_october), + r.getString(com.android.internal.R.string.month_long_standalone_november), + r.getString(com.android.internal.R.string.month_long_standalone_december), + }; sShortWeekdays = new String[] { r.getString(com.android.internal.R.string.day_of_week_medium_sunday), r.getString(com.android.internal.R.string.day_of_week_medium_monday), @@ -438,6 +453,7 @@ public class Time { * * @param s the string to parse * @return true if the resulting time value is in UTC time + * @throws android.util.TimeFormatException if s cannot be parsed. */ public boolean parse3339(String s) { if (nativeParse3339(s)) { diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java index b121e60..584e83f 100644 --- a/core/java/android/text/method/DialerKeyListener.java +++ b/core/java/android/text/method/DialerKeyListener.java @@ -106,7 +106,7 @@ public class DialerKeyListener extends NumberKeyListener */ public static final char[] CHARACTERS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*', - '+', '-', '(', ')', ',', '/', 'N', '.', ' ' + '+', '-', '(', ')', ',', '/', 'N', '.', ' ', ';' }; private static DialerKeyListener sInstance; diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java index f2fb9cb..dfc16f5 100644 --- a/core/java/android/text/method/Touch.java +++ b/core/java/android/text/method/Touch.java @@ -81,6 +81,12 @@ public class Touch { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: + ds = buffer.getSpans(0, buffer.length(), DragState.class); + + for (int i = 0; i < ds.length; i++) { + buffer.removeSpan(ds[i]); + } + buffer.setSpan(new DragState(event.getX(), event.getY(), widget.getScrollX(), widget.getScrollY()), 0, 0, Spannable.SPAN_MARK_MARK); diff --git a/core/java/android/util/CharsetUtils.java b/core/java/android/util/CharsetUtils.java index 7553029..9d91aca 100644 --- a/core/java/android/util/CharsetUtils.java +++ b/core/java/android/util/CharsetUtils.java @@ -142,20 +142,25 @@ public final class CharsetUtils { /** * Returns whether the given character set name indicates the Shift-JIS - * encoding. + * encoding. Returns false if the name is null. * * @param charsetName the character set name * @return {@code true} if the name corresponds to Shift-JIS or * {@code false} if not */ private static boolean isShiftJis(String charsetName) { - if (charsetName.length() != 9) { - // Bail quickly if the length doesn't match. + // Bail quickly if the length doesn't match. + if (charsetName == null) { + return false; + } + int length = charsetName.length(); + if (length != 4 && length != 9) { return false; } return charsetName.equalsIgnoreCase("shift_jis") - || charsetName.equalsIgnoreCase("shift-jis"); + || charsetName.equalsIgnoreCase("shift-jis") + || charsetName.equalsIgnoreCase("sjis"); } /** diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index e4dd020..4179edb 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -16,6 +16,8 @@ package android.util; +import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; import android.os.*; @@ -35,8 +37,7 @@ public class DisplayMetrics { * The device's density. * @hide */ - public static final int DEVICE_DENSITY = SystemProperties.getInt("ro.sf.lcd_density", - DEFAULT_DENSITY); + public static final int DEVICE_DENSITY = getDeviceDensity(); /** * The absolute width of the display in pixels. @@ -101,22 +102,83 @@ public class DisplayMetrics { } /** - * Set the display metrics' density and update parameters depend on it. - * @hide + * Update the display metrics based on the compatibility info and orientation + * NOTE: DO NOT EXPOSE THIS API! It is introducing a circular dependency + * with the higher-level android.res package. + * {@hide} */ - public void updateDensity(float newDensity) { - float ratio = newDensity / density; - density = newDensity; - scaledDensity = density; - widthPixels *= ratio; - heightPixels *= ratio; - xdpi *= ratio; - ydpi *= ratio; + public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation, + int screenLayout) { + int xOffset = 0; + if (!compatibilityInfo.isConfiguredExpandable()) { + // Note: this assume that configuration is updated before calling + // updateMetrics method. + if (screenLayout == Configuration.SCREENLAYOUT_LARGE) { + // This is a large screen device and the app is not + // compatible with large screens, to diddle it. + + compatibilityInfo.setExpandable(false); + // Figure out the compatibility width and height of the screen. + int defaultWidth; + int defaultHeight; + switch (orientation) { + case Configuration.ORIENTATION_LANDSCAPE: { + defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); + defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); + break; + } + case Configuration.ORIENTATION_PORTRAIT: + case Configuration.ORIENTATION_SQUARE: + default: { + defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); + defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); + break; + } + case Configuration.ORIENTATION_UNDEFINED: { + // don't change + return; + } + } + + if (defaultWidth < widthPixels) { + // content/window's x offset in original pixels + xOffset = ((widthPixels - defaultWidth) / 2); + widthPixels = defaultWidth; + } + if (defaultHeight < heightPixels) { + heightPixels = defaultHeight; + } + + } else { + // the screen size is same as expected size. make it expandable + compatibilityInfo.setExpandable(true); + } + } + 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 + ", xdpi=" + xdpi + ", ydpi=" + ydpi + "}"; } + + private static int getDeviceDensity() { + // qemu.sf.lcd_density can be used to override ro.sf.lcd_density + // when running in the emulator, allowing for dynamic configurations. + // The reason for this is that ro.sf.lcd_density is write-once and is + // set by the init process when it parses build.prop before anything else. + return SystemProperties.getInt("qemu.sf.lcd_density", + SystemProperties.getInt("ro.sf.lcd_density", DEFAULT_DENSITY)); + } } diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java new file mode 100644 index 0000000..d90045f --- /dev/null +++ b/core/java/android/util/LongSparseArray.java @@ -0,0 +1,342 @@ +/* + * 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.util; + +import com.android.internal.util.ArrayUtils; + +/** + * SparseArrays map longs to Objects. Unlike a normal array of Objects, + * there can be gaps in the indices. It is intended to be more efficient + * than using a HashMap to map Longs to Objects. + * + * @hide + */ +public class LongSparseArray<E> { + private static final Object DELETED = new Object(); + private boolean mGarbage = false; + + /** + * Creates a new SparseArray containing no mappings. + */ + public LongSparseArray() { + this(10); + } + + /** + * Creates a new SparseArray containing no mappings that will not + * require any additional memory allocation to store the specified + * number of mappings. + */ + public LongSparseArray(int initialCapacity) { + initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity); + + mKeys = new long[initialCapacity]; + mValues = new Object[initialCapacity]; + mSize = 0; + } + + /** + * Gets the Object mapped from the specified key, or <code>null</code> + * if no such mapping has been made. + */ + public E get(long key) { + return get(key, null); + } + + /** + * Gets the Object mapped from the specified key, or the specified Object + * if no such mapping has been made. + */ + public E get(long key, E valueIfKeyNotFound) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i < 0 || mValues[i] == DELETED) { + return valueIfKeyNotFound; + } else { + return (E) mValues[i]; + } + } + + /** + * Removes the mapping from the specified key, if there was any. + */ + public void delete(long key) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + if (mValues[i] != DELETED) { + mValues[i] = DELETED; + mGarbage = true; + } + } + } + + /** + * Alias for {@link #delete(long)}. + */ + public void remove(long key) { + delete(key); + } + + private void gc() { + // Log.e("SparseArray", "gc start with " + mSize); + + int n = mSize; + int o = 0; + long[] keys = mKeys; + Object[] values = mValues; + + for (int i = 0; i < n; i++) { + Object val = values[i]; + + if (val != DELETED) { + if (i != o) { + keys[o] = keys[i]; + values[o] = val; + } + + o++; + } + } + + mGarbage = false; + mSize = o; + + // Log.e("SparseArray", "gc end with " + mSize); + } + + /** + * Adds a mapping from the specified key to the specified value, + * replacing the previous mapping from the specified key if there + * was one. + */ + public void put(long key, E value) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + mValues[i] = value; + } else { + i = ~i; + + if (i < mSize && mValues[i] == DELETED) { + mKeys[i] = key; + mValues[i] = value; + return; + } + + if (mGarbage && mSize >= mKeys.length) { + gc(); + + // Search again because indices may have changed. + i = ~binarySearch(mKeys, 0, mSize, key); + } + + if (mSize >= mKeys.length) { + int n = ArrayUtils.idealIntArraySize(mSize + 1); + + long[] nkeys = new long[n]; + Object[] nvalues = new Object[n]; + + // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + if (mSize - i != 0) { + // Log.e("SparseArray", "move " + (mSize - i)); + System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); + System.arraycopy(mValues, i, mValues, i + 1, mSize - i); + } + + mKeys[i] = key; + mValues[i] = value; + mSize++; + } + } + + /** + * Returns the number of key-value mappings that this SparseArray + * currently stores. + */ + public int size() { + if (mGarbage) { + gc(); + } + + return mSize; + } + + /** + * Given an index in the range <code>0...size()-1</code>, returns + * the key from the <code>index</code>th key-value mapping that this + * SparseArray stores. + */ + public long keyAt(int index) { + if (mGarbage) { + gc(); + } + + return mKeys[index]; + } + + /** + * Given an index in the range <code>0...size()-1</code>, returns + * the value from the <code>index</code>th key-value mapping that this + * SparseArray stores. + */ + public E valueAt(int index) { + if (mGarbage) { + gc(); + } + + return (E) mValues[index]; + } + + /** + * Given an index in the range <code>0...size()-1</code>, sets a new + * value for the <code>index</code>th key-value mapping that this + * SparseArray stores. + */ + public void setValueAt(int index, E value) { + if (mGarbage) { + gc(); + } + + mValues[index] = value; + } + + /** + * Returns the index for which {@link #keyAt} would return the + * specified key, or a negative number if the specified + * key is not mapped. + */ + public int indexOfKey(long key) { + if (mGarbage) { + gc(); + } + + return binarySearch(mKeys, 0, mSize, key); + } + + /** + * Returns an index for which {@link #valueAt} would return the + * specified key, or a negative number if no keys map to the + * specified value. + * Beware that this is a linear search, unlike lookups by key, + * and that multiple keys can map to the same value and this will + * find only one of them. + */ + public int indexOfValue(E value) { + if (mGarbage) { + gc(); + } + + for (int i = 0; i < mSize; i++) + if (mValues[i] == value) + return i; + + return -1; + } + + /** + * Removes all key-value mappings from this SparseArray. + */ + public void clear() { + int n = mSize; + Object[] values = mValues; + + for (int i = 0; i < n; i++) { + values[i] = null; + } + + mSize = 0; + mGarbage = false; + } + + /** + * Puts a key/value pair into the array, optimizing for the case where + * the key is greater than all existing keys in the array. + */ + public void append(long key, E value) { + if (mSize != 0 && key <= mKeys[mSize - 1]) { + put(key, value); + return; + } + + if (mGarbage && mSize >= mKeys.length) { + gc(); + } + + int pos = mSize; + if (pos >= mKeys.length) { + int n = ArrayUtils.idealIntArraySize(pos + 1); + + long[] nkeys = new long[n]; + Object[] nvalues = new Object[n]; + + // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + mKeys[pos] = key; + mValues[pos] = value; + mSize = pos + 1; + } + + private static int binarySearch(long[] a, int start, int len, long key) { + int high = start + len, low = start - 1, guess; + + while (high - low > 1) { + guess = (high + low) / 2; + + if (a[guess] < key) + low = guess; + else + high = guess; + } + + if (high == start + len) + return ~(start + len); + else if (a[high] == key) + return high; + else + return ~high; + } + + private void checkIntegrity() { + for (int i = 1; i < mSize; i++) { + if (mKeys[i] <= mKeys[i - 1]) { + for (int j = 0; j < mSize; j++) { + Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); + } + + throw new RuntimeException(); + } + } + } + + private long[] mKeys; + private Object[] mValues; + private int mSize; +}
\ No newline at end of file diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index 23f3e3c..1e558be 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -198,6 +198,7 @@ public class GestureDetector { private int mTouchSlopSquare; private int mDoubleTapSlopSquare; private int mMinimumFlingVelocity; + private int mMaximumFlingVelocity; private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); @@ -361,11 +362,13 @@ public class GestureDetector { doubleTapSlop = ViewConfiguration.getDoubleTapSlop(); //noinspection deprecation mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); + mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); } else { final ViewConfiguration configuration = ViewConfiguration.get(context); touchSlop = configuration.getScaledTouchSlop(); doubleTapSlop = configuration.getScaledDoubleTapSlop(); mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity(); } mTouchSlopSquare = touchSlop * touchSlop; mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop; @@ -505,7 +508,7 @@ public class GestureDetector { // A fling must travel the minimum tap distance final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); + velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); final float velocityY = velocityTracker.getYVelocity(); final float velocityX = velocityTracker.getXVelocity(); diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 86261c4..a224ed3 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -59,32 +59,32 @@ public final class MotionEvent implements Parcelable { public static final int ACTION_OUTSIDE = 4; private static final boolean TRACK_RECYCLED_LOCATION = false; - + /** * Flag indicating the motion event intersected the top edge of the screen. */ public static final int EDGE_TOP = 0x00000001; - + /** * Flag indicating the motion event intersected the bottom edge of the screen. */ public static final int EDGE_BOTTOM = 0x00000002; - + /** * Flag indicating the motion event intersected the left edge of the screen. */ public static final int EDGE_LEFT = 0x00000004; - + /** * Flag indicating the motion event intersected the right edge of the screen. */ public static final int EDGE_RIGHT = 0x00000008; - + static private final int MAX_RECYCLED = 10; static private Object gRecyclerLock = new Object(); static private int gRecyclerUsed = 0; static private MotionEvent gRecyclerTop = null; - + private long mDownTime; private long mEventTime; private int mAction; @@ -109,7 +109,7 @@ public final class MotionEvent implements Parcelable { private MotionEvent() { } - + static private MotionEvent obtain() { synchronized (gRecyclerLock) { if (gRecyclerTop == null) { @@ -123,26 +123,26 @@ public final class MotionEvent implements Parcelable { return ev; } } - + /** * Create a new MotionEvent, filling in all of the basic values that * define the motion. - * - * @param downTime The time (in ms) when the user originally pressed down to start + * + * @param downTime The time (in ms) when the user originally pressed down to start * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. - * @param eventTime The the time (in ms) when this specific event was generated. This + * @param eventTime The the time (in ms) when this specific event was generated. This * must be obtained from {@link SystemClock#uptimeMillis()}. * @param action The kind of action being performed -- one of either * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or * {@link #ACTION_CANCEL}. * @param x The X coordinate of this event. * @param y The Y coordinate of this event. - * @param pressure The current pressure of this event. The pressure generally - * ranges from 0 (no pressure at all) to 1 (normal pressure), however - * values higher than 1 may be generated depending on the calibration of + * @param pressure The current pressure of this event. The pressure generally + * ranges from 0 (no pressure at all) to 1 (normal pressure), however + * values higher than 1 may be generated depending on the calibration of * the input device. * @param size A scaled value of the approximate size of the area being pressed when - * touched with the finger. The actual value in pixels corresponding to the finger + * touched with the finger. The actual value in pixels corresponding to the finger * touch is normalized with a device specific range of values * and scaled to a value between 0 and 1. * @param metaState The state of any meta / modifier keys that were in effect when @@ -174,15 +174,15 @@ public final class MotionEvent implements Parcelable { return ev; } - + /** * Create a new MotionEvent, filling in a subset of the basic motion * values. Those not specified here are: device id (always 0), pressure * and size (always 1), x and y precision (always 1), and edgeFlags (always 0). - * - * @param downTime The time (in ms) when the user originally pressed down to start + * + * @param downTime The time (in ms) when the user originally pressed down to start * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. - * @param eventTime The the time (in ms) when this specific event was generated. This + * @param eventTime The the time (in ms) when this specific event was generated. This * must be obtained from {@link SystemClock#uptimeMillis()}. * @param action The kind of action being performed -- one of either * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or @@ -212,27 +212,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; - history[i + 2] *= scale; - history[i + 3] *= scale; - } + 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) } } } @@ -265,7 +285,7 @@ public final class MotionEvent implements Parcelable { } return ev; } - + /** * Recycle the MotionEvent, to be re-used by a later caller. After calling * this function you must not ever touch the event again. @@ -291,7 +311,7 @@ public final class MotionEvent implements Parcelable { } } } - + /** * Return the kind of action being performed -- one of either * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or @@ -302,8 +322,8 @@ public final class MotionEvent implements Parcelable { } /** - * Returns the time (in ms) when the user originally pressed down to start - * a stream of position events. + * Returns the time (in ms) when the user originally pressed down to start + * a stream of position events. */ public final long getDownTime() { return mDownTime; @@ -317,25 +337,25 @@ public final class MotionEvent implements Parcelable { } /** - * Returns the X coordinate of this event. Whole numbers are pixels; the - * value may have a fraction for input devices that are sub-pixel precise. + * Returns the X coordinate of this event. Whole numbers are pixels; the + * value may have a fraction for input devices that are sub-pixel precise. */ public final float getX() { return mX; } /** - * Returns the Y coordinate of this event. Whole numbers are pixels; the - * value may have a fraction for input devices that are sub-pixel precise. + * Returns the Y coordinate of this event. Whole numbers are pixels; the + * value may have a fraction for input devices that are sub-pixel precise. */ public final float getY() { return mY; } /** - * Returns the current pressure of this event. The pressure generally - * ranges from 0 (no pressure at all) to 1 (normal pressure), however - * values higher than 1 may be generated depending on the calibration of + * Returns the current pressure of this event. The pressure generally + * ranges from 0 (no pressure at all) to 1 (normal pressure), however + * values higher than 1 may be generated depending on the calibration of * the input device. */ public final float getPressure() { @@ -344,9 +364,9 @@ public final class MotionEvent implements Parcelable { /** * Returns a scaled value of the approximate size, of the area being pressed when - * touched with the finger. The actual value in pixels corresponding to the finger + * touched with the finger. The actual value in pixels corresponding to the finger * touch is normalized with the device specific range of values - * and scaled to a value between 0 and 1. The value of size can be used to + * and scaled to a value between 0 and 1. The value of size can be used to * determine fat touch events. */ public final float getSize() { @@ -396,7 +416,7 @@ public final class MotionEvent implements Parcelable { public final float getXPrecision() { return mXPrecision; } - + /** * Return the precision of the Y coordinates being reported. You can * multiple this number with {@link #getY} to find the actual hardware @@ -406,89 +426,89 @@ public final class MotionEvent implements Parcelable { public final float getYPrecision() { return mYPrecision; } - + /** * Returns the number of historical points in this event. These are * movements that have occurred between this event and the previous event. * This only applies to ACTION_MOVE events -- all other actions will have * a size of 0. - * + * * @return Returns the number of historical points in the event. */ public final int getHistorySize() { return mNumHistory; } - + /** * Returns the time that a historical movement occurred between this event * and the previous event. Only applies to ACTION_MOVE events. - * + * * @param pos Which historical value to return; must be less than * {@link #getHistorySize} - * + * * @see #getHistorySize * @see #getEventTime */ public final long getHistoricalEventTime(int pos) { return mHistoryTimes[pos]; } - + /** * Returns a historical X coordinate that occurred between this event * and the previous event. Only applies to ACTION_MOVE events. - * + * * @param pos Which historical value to return; must be less than * {@link #getHistorySize} - * + * * @see #getHistorySize * @see #getX */ public final float getHistoricalX(int pos) { return mHistory[pos*4]; } - + /** * Returns a historical Y coordinate that occurred between this event * and the previous event. Only applies to ACTION_MOVE events. - * + * * @param pos Which historical value to return; must be less than * {@link #getHistorySize} - * + * * @see #getHistorySize * @see #getY */ public final float getHistoricalY(int pos) { return mHistory[pos*4 + 1]; } - + /** * Returns a historical pressure coordinate that occurred between this event * and the previous event. Only applies to ACTION_MOVE events. - * + * * @param pos Which historical value to return; must be less than * {@link #getHistorySize} - * + * * @see #getHistorySize * @see #getPressure */ public final float getHistoricalPressure(int pos) { return mHistory[pos*4 + 2]; } - + /** * Returns a historical size coordinate that occurred between this event * and the previous event. Only applies to ACTION_MOVE events. - * + * * @param pos Which historical value to return; must be less than * {@link #getHistorySize} - * + * * @see #getHistorySize * @see #getSize */ public final float getHistoricalSize(int pos) { return mHistory[pos*4 + 3]; } - + /** * Return the id for the device that this event came from. An id of * zero indicates that the event didn't come from a physical device; other @@ -497,12 +517,12 @@ public final class MotionEvent implements Parcelable { public final int getDeviceId() { return mDeviceId; } - + /** * Returns a bitfield indicating which edges, if any, where touched by this - * MotionEvent. For touch events, clients can use this to determine if the - * user's finger was touching the edge of the display. - * + * MotionEvent. For touch events, clients can use this to determine if the + * user's finger was touching the edge of the display. + * * @see #EDGE_LEFT * @see #EDGE_TOP * @see #EDGE_RIGHT @@ -511,12 +531,12 @@ public final class MotionEvent implements Parcelable { public final int getEdgeFlags() { return mEdgeFlags; } - + /** * Sets the bitfield indicating which edges, if any, where touched by this - * MotionEvent. - * + * MotionEvent. + * * @see #getEdgeFlags() */ public final void setEdgeFlags(int flags) { @@ -548,11 +568,11 @@ public final class MotionEvent implements Parcelable { pos[i+1] += deltaY; } } - + /** * Set this event's location. Applies {@link #offsetLocation} with a * delta from the current location to the given new location. - * + * * @param x New absolute X location. * @param y New absolute Y location. */ @@ -563,13 +583,13 @@ public final class MotionEvent implements Parcelable { offsetLocation(deltaX, deltaY); } } - + /** * Add a new movement to the batch of movements in this event. The event's * current location, position and size is updated to the new values. In * the future, the current values in the event will be added to a list of * historic values. - * + * * @param x The new X position. * @param y The new Y position. * @param pressure The new pressure. @@ -599,16 +619,16 @@ public final class MotionEvent implements Parcelable { mHistoryTimes = historyTimes = newHistoryTimes; } } - + historyTimes[N] = mEventTime; - + final int pos = N*4; history[pos] = mX; history[pos+1] = mY; history[pos+2] = mPressure; history[pos+3] = mSize; mNumHistory = N+1; - + mEventTime = eventTime; mX = mRawX = x; mY = mRawY = y; @@ -616,7 +636,7 @@ public final class MotionEvent implements Parcelable { mSize = size; mMetaState |= metaState; } - + @Override public String toString() { return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this)) diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 3d023f7..45b0f0a 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -17,6 +17,8 @@ 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; @@ -100,6 +102,8 @@ public class SurfaceView extends View { static final int KEEP_SCREEN_ON_MSG = 1; static final int GET_NEW_SURFACE_MSG = 2; + int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; + boolean mIsCreating = false; final Handler mHandler = new Handler() { @@ -135,28 +139,21 @@ public class SurfaceView extends View { int mFormat = -1; int mType = -1; final Rect mSurfaceFrame = new Rect(); - private final float mAppScale; - private final float mAppScaleInverted; + private Translator mTranslator; public SurfaceView(Context context) { super(context); setWillNotDraw(true); - mAppScale = context.getApplicationScale(); - mAppScaleInverted = 1.0f / mAppScale; } public SurfaceView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(true); - mAppScale = context.getApplicationScale(); - mAppScaleInverted = 1.0f / mAppScale; } public SurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setWillNotDraw(true); - mAppScale = context.getApplicationScale(); - mAppScaleInverted = 1.0f / mAppScale; } /** @@ -259,9 +256,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 && mAppScale != 1.0f) { + if (mRequestedWidth < 0 && mTranslator != null) { MotionEvent scaledBack = MotionEvent.obtain(event); - scaledBack.scale(mAppScale); + scaledBack.scale(mTranslator.applicationScale); try { return super.dispatchTouchEvent(scaledBack); } finally { @@ -285,20 +282,33 @@ public class SurfaceView extends View { super.dispatchDraw(canvas); } + /** + * Hack to allow special layering of windows. The type is one of the + * types in WindowManager.LayoutParams. This is a hack so: + * @hide + */ + public void setWindowType(int type) { + mWindowType = type; + } + private void updateWindow(boolean force) { if (!mHaveFrame) { return; } + 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) { - myWidth *= mAppScale; - myHeight *= mAppScale; + // 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; } getLocationInWindow(mLocation); @@ -316,7 +326,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]; @@ -326,23 +336,30 @@ public class SurfaceView extends View { mFormat = mRequestedFormat; mType = mRequestedType; - // Scaling window's layout here beause mLayout is not used elsewhere. - mLayout.x = (int) (mLeft * mAppScale); - mLayout.y = (int) (mTop * mAppScale); - mLayout.width = (int) (getWidth() * mAppScale); - mLayout.height = (int) (getHeight() * mAppScale); + // 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; if (mWindow == null) { mWindow = new MyWindow(this); - mLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; + mLayout.type = mWindowType; mLayout.gravity = Gravity.LEFT|Gravity.TOP; mSession.add(mWindow, mLayout, mVisible ? VISIBLE : GONE, mContentInsets); @@ -356,15 +373,12 @@ public class SurfaceView extends View { mSurfaceLock.lock(); mDrawingStopped = !visible; + final int relayoutResult = mSession.relayout( mWindow, mLayout, mWidth, mHeight, visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets, mVisibleInsets, mSurface); - mContentInsets.scale(mAppScaleInverted); - mVisibleInsets.scale(mAppScaleInverted); - mWinFrame.scale(mAppScaleInverted); - if (localLOGV) Log.i(TAG, "New surface: " + mSurface + ", vis=" + visible + ", frame=" + mWinFrame); mSurfaceFrame.left = 0; @@ -433,24 +447,14 @@ public class SurfaceView extends View { private static class MyWindow extends IWindow.Stub { private final WeakReference<SurfaceView> mSurfaceView; - private final float mAppScale; - private final float mAppScaleInverted; public MyWindow(SurfaceView surfaceView) { mSurfaceView = new WeakReference<SurfaceView>(surfaceView); - mAppScale = surfaceView.getContext().getApplicationScale(); - mAppScaleInverted = 1.0f / mAppScale; } public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw) { SurfaceView surfaceView = mSurfaceView.get(); - float scale = mAppScaleInverted; - w *= scale; - h *= scale; - coveredInsets.scale(scale); - visibleInsets.scale(scale); - if (surfaceView != null) { if (localLOGV) Log.v( "SurfaceView", surfaceView + " got resized: w=" + @@ -613,7 +617,6 @@ public class SurfaceView extends View { Canvas c = null; if (!mDrawingStopped && mWindow != null) { Rect frame = dirty != null ? dirty : mSurfaceFrame; - frame.scale(mAppScale); try { c = mSurface.lockCanvas(frame); } catch (Exception e) { diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index c708f54..5d89c46 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -165,7 +165,17 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { pastTime[i] = 0; } } - + + /** + * Equivalent to invoking {@link #computeCurrentVelocity(int, float)} with a maximum + * velocity of Float.MAX_VALUE. + * + * @see #computeCurrentVelocity(int, float) + */ + public void computeCurrentVelocity(int units) { + computeCurrentVelocity(units, Float.MAX_VALUE); + } + /** * Compute the current velocity based on the points that have been * collected. Only call this when you actually want to retrieve velocity @@ -175,8 +185,11 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * * @param units The units you would like the velocity in. A value of 1 * provides pixels per millisecond, 1000 provides pixels per second, etc. + * @param maxVelocity The maximum velocity that can be computed by this method. + * This value must be declared in the same unit as the units parameter. This value + * must be positive. */ - public void computeCurrentVelocity(int units) { + public void computeCurrentVelocity(int units, float maxVelocity) { final float[] pastX = mPastX; final float[] pastY = mPastY; final long[] pastTime = mPastTime; @@ -210,8 +223,8 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { if (accumY == 0) accumY = vel; else accumY = (accumY + vel) * .5f; } - mXVelocity = accumX; - mYVelocity = accumY; + mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity) : Math.min(accumX, maxVelocity); + mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity) : Math.min(accumY, maxVelocity); if (localLOGV) Log.v(TAG, "Y velocity=" + mYVelocity +" X velocity=" + mXVelocity + " N=" + N); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9e709cf..ff8868b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,6 +16,9 @@ package android.view; +import com.android.internal.R; +import com.android.internal.view.menu.MenuBuilder; + import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -25,12 +28,12 @@ import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; +import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; -import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; @@ -42,47 +45,47 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.util.AttributeSet; +import android.util.Config; import android.util.EventLog; import android.util.Log; -import android.util.SparseArray; -import android.util.Poolable; import android.util.Pool; -import android.util.Pools; +import android.util.Poolable; import android.util.PoolableManager; -import android.util.Config; +import android.util.Pools; +import android.util.SparseArray; import android.view.ContextMenu.ContextMenuInfo; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityEventSource; +import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.EditorInfo; import android.widget.ScrollBarDrawable; -import com.android.internal.R; -import com.android.internal.view.menu.MenuBuilder; - +import java.lang.ref.SoftReference; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.WeakHashMap; -import java.lang.ref.SoftReference; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; /** * <p> * This class represents the basic building block for user interface components. A View * occupies a rectangular area on the screen and is responsible for drawing and * event handling. View is the base class for <em>widgets</em>, which are - * used to create interactive UI components (buttons, text fields, etc.). The + * used to create interactive UI components (buttons, text fields, etc.). The * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which * are invisible containers that hold other Views (or other ViewGroups) and define * their layout properties. * </p> * * <div class="special"> - * <p>For an introduction to using this class to develop your - * application's user interface, read the Developer Guide documentation on + * <p>For an introduction to using this class to develop your + * application's user interface, read the Developer Guide documentation on * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics - * include: + * include: * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a> @@ -93,7 +96,7 @@ import java.lang.reflect.InvocationTargetException; * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>. * </p> * </div> - * + * * <a name="Using"></a> * <h3>Using Views</h3> * <p> @@ -419,7 +422,7 @@ import java.lang.reflect.InvocationTargetException; * </p> * * <p> - * Note that the framework will not draw views that are not in the invalid region. + * Note that the framework will not draw views that are not in the invalid region. * </p> * * <p> @@ -535,25 +538,52 @@ import java.lang.reflect.InvocationTargetException; * take care of redrawing the appropriate views until the animation completes. * </p> * + * @attr ref android.R.styleable#View_background + * @attr ref android.R.styleable#View_clickable + * @attr ref android.R.styleable#View_contentDescription + * @attr ref android.R.styleable#View_drawingCacheQuality + * @attr ref android.R.styleable#View_duplicateParentState + * @attr ref android.R.styleable#View_id + * @attr ref android.R.styleable#View_fadingEdge + * @attr ref android.R.styleable#View_fadingEdgeLength * @attr ref android.R.styleable#View_fitsSystemWindows + * @attr ref android.R.styleable#View_isScrollContainer + * @attr ref android.R.styleable#View_focusable + * @attr ref android.R.styleable#View_focusableInTouchMode + * @attr ref android.R.styleable#View_hapticFeedbackEnabled + * @attr ref android.R.styleable#View_keepScreenOn + * @attr ref android.R.styleable#View_longClickable + * @attr ref android.R.styleable#View_minHeight + * @attr ref android.R.styleable#View_minWidth * @attr ref android.R.styleable#View_nextFocusDown * @attr ref android.R.styleable#View_nextFocusLeft * @attr ref android.R.styleable#View_nextFocusRight * @attr ref android.R.styleable#View_nextFocusUp + * @attr ref android.R.styleable#View_onClick + * @attr ref android.R.styleable#View_padding + * @attr ref android.R.styleable#View_paddingBottom + * @attr ref android.R.styleable#View_paddingLeft + * @attr ref android.R.styleable#View_paddingRight + * @attr ref android.R.styleable#View_paddingTop + * @attr ref android.R.styleable#View_saveEnabled * @attr ref android.R.styleable#View_scrollX * @attr ref android.R.styleable#View_scrollY - * @attr ref android.R.styleable#View_scrollbarTrackHorizontal - * @attr ref android.R.styleable#View_scrollbarThumbHorizontal * @attr ref android.R.styleable#View_scrollbarSize + * @attr ref android.R.styleable#View_scrollbarStyle * @attr ref android.R.styleable#View_scrollbars + * @attr ref android.R.styleable#View_scrollbarTrackHorizontal + * @attr ref android.R.styleable#View_scrollbarThumbHorizontal * @attr ref android.R.styleable#View_scrollbarThumbVertical * @attr ref android.R.styleable#View_scrollbarTrackVertical * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack + * @attr ref android.R.styleable#View_soundEffectsEnabled + * @attr ref android.R.styleable#View_tag + * @attr ref android.R.styleable#View_visibility * * @see android.view.ViewGroup */ -public class View implements Drawable.Callback, KeyEvent.Callback { +public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { private static final boolean DBG = false; /** @@ -851,6 +881,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; /** + * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} + * should add all focusable Views regardless if they are focusable in touch mode. + */ + public static final int FOCUSABLES_ALL = 0x00000000; + + /** + * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} + * should add only Views focusable in touch mode. + */ + public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; + + /** * Use with {@link #focusSearch}. Move focus to the previous selectable * item. */ @@ -1428,6 +1470,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback { static final int DIRTY_MASK = 0x00600000; /** + * Indicates whether the background is opaque. + * + * @hide + */ + static final int OPAQUE_BACKGROUND = 0x00800000; + + /** + * Indicates whether the scrollbars are opaque. + * + * @hide + */ + static final int OPAQUE_SCROLLBARS = 0x01000000; + + /** + * Indicates whether the view is opaque. + * + * @hide + */ + static final int OPAQUE_MASK = 0x01800000; + + /** * The parent this view is attached to. * {@hide} * @@ -1449,7 +1512,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED, name = "LAYOUT_REQUIRED"), @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID, - name = "DRAWING_CACHE_VALID", outputIf = false), + name = "DRAWING_CACHE_INVALID", outputIf = false), @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true), @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false), @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), @@ -1551,6 +1614,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback { protected int mPaddingBottom; /** + * Briefly describes the view and is primarily used for accessibility support. + */ + private CharSequence mContentDescription; + + /** * Cache the paddingRight set by the user to append to the scrollbar's size. */ @ViewDebug.ExportedProperty @@ -1622,6 +1690,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { private int[] mDrawableState = null; private SoftReference<Bitmap> mDrawingCache; + private SoftReference<Bitmap> mUnscaledDrawingCache; /** * When this view has focus and the next focus is {@link #FOCUS_LEFT}, @@ -1701,7 +1770,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public View(Context context) { mContext = context; mResources = context != null ? context.getResources() : null; - mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED; + mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; ++sInstanceCount; } @@ -1762,7 +1831,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { int viewFlagMasks = 0; boolean setScrollContainer = false; - + int x = 0; int y = 0; @@ -1858,16 +1927,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback { viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; } break; + case com.android.internal.R.styleable.View_contentDescription: + mContentDescription = a.getString(attr); + break; case com.android.internal.R.styleable.View_soundEffectsEnabled: if (!a.getBoolean(attr, true)) { 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) { @@ -1922,6 +1996,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback { mMinHeight = a.getDimensionPixelSize(attr, 0); break; case R.styleable.View_onClick: + if (context.isRestricted()) { + throw new IllegalStateException("The android:onClick attribute cannot " + + "be used within a restricted context"); + } + final String handlerName = a.getString(attr); if (handlerName != null) { setOnClickListener(new OnClickListener() { @@ -1990,7 +2069,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback { if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { setScrollContainer(true); } - + + computeOpaqueFlags(); + a.recycle(); } @@ -2255,6 +2336,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * otherwise is returned. */ public boolean performClick() { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); + if (mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); mOnClickListener.onClick(this); @@ -2272,6 +2355,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * otherwise is returned. */ public boolean performLongClick() { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); + boolean handled = false; if (mOnLongClickListener != null) { handled = mOnLongClickListener.onLongClick(View.this); @@ -2387,7 +2472,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { if (!(parent instanceof View)) { break; } - + child = (View) parent; parent = child.getParent(); } @@ -2479,7 +2564,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * and previouslyFocusedRect provide insight into where the focus is coming from. * When overriding, be sure to call up through to the super class so that * the standard focus handling will occur. - * + * * @param gainFocus True if the View has focus; false otherwise. * @param direction The direction focus has moved when requestFocus() * is called to give this view focus. Values are @@ -2492,6 +2577,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * from (in addition to direction). Will be <code>null</code> otherwise. */ protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { + if (gainFocus) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + InputMethodManager imm = InputMethodManager.peekInstance(); if (!gainFocus) { if (isPressed()) { @@ -2506,7 +2595,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { && mAttachInfo.mHasWindowFocus) { imm.focusIn(this); } - + invalidate(); if (mOnFocusChangeListener != null) { mOnFocusChangeListener.onFocusChange(this, gainFocus); @@ -2514,6 +2603,79 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } /** + * {@inheritDoc} + */ + public void sendAccessibilityEvent(int eventType) { + if (AccessibilityManager.getInstance(mContext).isEnabled()) { + sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); + } + } + + /** + * {@inheritDoc} + */ + public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { + event.setClassName(getClass().getName()); + event.setPackageName(getContext().getPackageName()); + event.setEnabled(isEnabled()); + event.setContentDescription(mContentDescription); + + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) { + ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList; + getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); + event.setItemCount(focusablesTempList.size()); + event.setCurrentItemIndex(focusablesTempList.indexOf(this)); + focusablesTempList.clear(); + } + + dispatchPopulateAccessibilityEvent(event); + + AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event); + } + + /** + * Dispatches an {@link AccessibilityEvent} to the {@link View} children + * to be populated. + * + * @param event The event. + * + * @return True if the event population was completed. + */ + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + return false; + } + + /** + * Gets the {@link View} description. It briefly describes the view and is + * primarily used for accessibility support. Set this property to enable + * better accessibility support for your application. This is especially + * true for views that do not have textual representation (For example, + * ImageButton). + * + * @return The content descriptiopn. + * + * @attr ref android.R.styleable#View_contentDescription + */ + public CharSequence getContentDescription() { + return mContentDescription; + } + + /** + * Sets the {@link View} description. It briefly describes the view and is + * primarily used for accessibility support. Set this property to enable + * better accessibility support for your application. This is especially + * true for views that do not have textual representation (For example, + * ImageButton). + * + * @param contentDescription The content description. + * + * @attr ref android.R.styleable#View_contentDescription + */ + public void setContentDescription(CharSequence contentDescription) { + mContentDescription = contentDescription; + } + + /** * Invoked whenever this view loses focus, either by losing window focus or by losing * focus within its window. This method can be used to clear any state tied to the * focus. For instance, if a button is held pressed with the trackball and the window @@ -2522,7 +2684,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * Subclasses of View overriding this method should always call super.onFocusLost(). * * @see #onFocusChanged(boolean, int, android.graphics.Rect) - * @see #onWindowFocusChanged(boolean) + * @see #onWindowFocusChanged(boolean) * * @hide pending API council approval */ @@ -3222,11 +3384,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * @param direction The direction of the focus */ public void addFocusables(ArrayList<View> views, int direction) { - if (!isFocusable()) return; + addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); + } - if (isInTouchMode() && !isFocusableInTouchMode()) return; + /** + * Adds any focusable views that are descendants of this view (possibly + * including this view if it is focusable itself) to views. This method + * adds all focusable views regardless if we are in touch mode or + * only views focusable in touch mode if we are in touch mode depending on + * the focusable mode paramater. + * + * @param views Focusable views found so far or null if all we are interested is + * the number of focusables. + * @param direction The direction of the focus. + * @param focusableMode The type of focusables to be added. + * + * @see #FOCUSABLES_ALL + * @see #FOCUSABLES_TOUCH_MODE + */ + public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { + if (!isFocusable()) { + return; + } - views.add(this); + if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && + isInTouchMode() && !isFocusableInTouchMode()) { + return; + } + + if (views != null) { + views.add(this); + } } /** @@ -3398,14 +3586,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback { */ public void onStartTemporaryDetach() { } - + /** * Called after {@link #onStartTemporaryDetach} when the container is done * changing the view. */ public void onFinishTemporaryDetach() { } - + /** * capture information of this view for later analysis: developement only * check dynamic switch to make sure we only dump view @@ -3790,25 +3978,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * a call on that method would return a non-null InputConnection, and * they are really a first-class editor that the user would normally * start typing on when the go into a window containing your view. - * + * * <p>The default implementation always returns false. This does * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} * will not be called or the user can not otherwise perform edits on your * view; it is just a hint to the system that this is not the primary * purpose of this view. - * + * * @return Returns true if this view is a text editor, else false. */ public boolean onCheckIsTextEditor() { return false; } - + /** * Create a new InputConnection for an InputMethod to interact * with the view. The default implementation returns null, since it doesn't * support input methods. You can override this to implement such support. * This is only needed for views that take focus and text input. - * + * * <p>When implementing this, you probably also want to implement * {@link #onCheckIsTextEditor()} to indicate you will return a * non-null InputConnection. @@ -3832,7 +4020,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public boolean checkInputConnectionProxy(View view) { return false; } - + /** * Show the context menu for this view. It is not safe to hold on to the * menu after returning from this method. @@ -4563,14 +4751,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * whether an instance is opaque. Opaque Views are treated in a special way by * the View hierarchy, possibly allowing it to perform optimizations during * invalidate/draw passes. - * + * * @return True if this View is guaranteed to be fully opaque, false otherwise. * * @hide Pending API council approval */ @ViewDebug.ExportedProperty public boolean isOpaque() { - return mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE; + return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK; + } + + private void computeOpaqueFlags() { + // Opaque if: + // - Has a background + // - Background is opaque + // - Doesn't have scrollbars or scrollbars are inside overlay + + if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) { + mPrivateFlags |= OPAQUE_BACKGROUND; + } else { + mPrivateFlags &= ~OPAQUE_BACKGROUND; + } + + final int flags = mViewFlags; + if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || + (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) { + mPrivateFlags |= OPAQUE_SCROLLBARS; + } else { + mPrivateFlags &= ~OPAQUE_SCROLLBARS; + } + } + + /** + * @hide + */ + protected boolean hasOpaqueScrollbars() { + return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS; } /** @@ -4897,6 +5113,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { mViewFlags ^= SCROLLBARS_HORIZONTAL; + computeOpaqueFlags(); recomputePadding(); } } @@ -4926,6 +5143,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { mViewFlags ^= SCROLLBARS_VERTICAL; + computeOpaqueFlags(); recomputePadding(); } } @@ -4954,6 +5172,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public void setScrollBarStyle(int style) { if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); + computeOpaqueFlags(); recomputePadding(); } } @@ -5132,9 +5351,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } } } - + /** - * Override this if the vertical scrollbar needs to be hidden in a subclass, like when + * Override this if the vertical scrollbar needs to be hidden in a subclass, like when * FastScroller is visible. * @return whether to temporarily hide the vertical scrollbar * @hide @@ -5570,28 +5789,52 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } /** + * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> + * + * @return A non-scaled bitmap representing this view or null if cache is disabled. + * + * @see #getDrawingCache(boolean) + */ + public Bitmap getDrawingCache() { + return getDrawingCache(false); + } + + /** * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap * is null when caching is disabled. If caching is enabled and the cache is not ready, * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not * draw from the cache when the cache is enabled. To benefit from the cache, you must * request the drawing cache by calling this method and draw it on screen if the * returned bitmap is not null.</p> + * + * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, + * this method will create a bitmap of the same size as this view. Because this bitmap + * will be drawn scaled by the parent ViewGroup, the result on screen might show + * scaling artifacts. To avoid such artifacts, you should call this method by setting + * the auto scaling to true. Doing so, however, will generate a bitmap of a different + * size than the view. This implies that your application must be able to handle this + * size.</p> + * + * @param autoScale Indicates whether the generated bitmap should be scaled based on + * the current density of the screen when the application is in compatibility + * mode. * - * @return a bitmap representing this view or null if cache is disabled - * + * @return A bitmap representing this view or null if cache is disabled. + * * @see #setDrawingCacheEnabled(boolean) * @see #isDrawingCacheEnabled() - * @see #buildDrawingCache() + * @see #buildDrawingCache(boolean) * @see #destroyDrawingCache() */ - public Bitmap getDrawingCache() { + public Bitmap getDrawingCache(boolean autoScale) { if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { return null; } if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { - buildDrawingCache(); + buildDrawingCache(autoScale); } - return mDrawingCache == null ? null : mDrawingCache.get(); + return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) : + (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get()); } /** @@ -5610,6 +5853,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback { if (bitmap != null) bitmap.recycle(); mDrawingCache = null; } + if (mUnscaledDrawingCache != null) { + final Bitmap bitmap = mUnscaledDrawingCache.get(); + if (bitmap != null) bitmap.recycle(); + mUnscaledDrawingCache = null; + } } /** @@ -5637,18 +5885,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } /** + * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> + * + * @see #buildDrawingCache(boolean) + */ + public void buildDrawingCache() { + buildDrawingCache(false); + } + + /** * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> * * <p>If you call {@link #buildDrawingCache()} manually without calling * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> + * + * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, + * this method will create a bitmap of the same size as this view. Because this bitmap + * will be drawn scaled by the parent ViewGroup, the result on screen might show + * scaling artifacts. To avoid such artifacts, you should call this method by setting + * the auto scaling to true. Doing so, however, will generate a bitmap of a different + * size than the view. This implies that your application must be able to handle this + * size.</p> * * @see #getDrawingCache() * @see #destroyDrawingCache() */ - public void buildDrawingCache() { - if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null || - mDrawingCache.get() == null) { + public void buildDrawingCache(boolean autoScale) { + if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ? + (mDrawingCache == null || mDrawingCache.get() == null) : + (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE); @@ -5657,8 +5923,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback { EventLog.writeEvent(60002, hashCode()); } - final int width = mRight - mLeft; - final int height = mBottom - mTop; + int width = mRight - mLeft; + int height = mBottom - mTop; + + final AttachInfo attachInfo = mAttachInfo; + final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; + + if (autoScale && scalingRequired) { + width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); + height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); + } final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; final boolean opaque = drawingCacheBackgroundColor != 0 || @@ -5672,7 +5946,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } boolean clear = true; - Bitmap bitmap = mDrawingCache == null ? null : mDrawingCache.get(); + Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) : + (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get()); if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { @@ -5701,12 +5976,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback { try { bitmap = Bitmap.createBitmap(width, height, quality); - mDrawingCache = new SoftReference<Bitmap>(bitmap); + if (autoScale) { + mDrawingCache = new SoftReference<Bitmap>(bitmap); + } else { + mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap); + } } catch (OutOfMemoryError e) { // If there is not enough memory to create the bitmap cache, just // ignore the issue as bitmap caches are not required to draw the // view hierarchy - mDrawingCache = null; + if (autoScale) { + mDrawingCache = null; + } else { + mUnscaledDrawingCache = null; + } return; } @@ -5714,7 +5997,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } Canvas canvas; - final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { canvas = attachInfo.mCanvas; if (canvas == null) { @@ -5737,15 +6019,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback { computeScroll(); final int restoreCount = canvas.save(); + + if (autoScale && scalingRequired) { + final float scale = attachInfo.mApplicationScale; + canvas.scale(scale, scale); + } + canvas.translate(-mScrollX, -mScrollY); - mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; + mPrivateFlags |= DRAWN; // Fast path for layouts with no backgrounds if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } + mPrivateFlags &= ~DIRTY_MASK; dispatchDraw(canvas); } else { draw(canvas); @@ -5792,7 +6081,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { canvas = new Canvas(bitmap); } - if ((backgroundColor&0xff000000) != 0) { + if ((backgroundColor & 0xff000000) != 0) { bitmap.eraseColor(backgroundColor); } @@ -5800,6 +6089,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { final int restoreCount = canvas.save(); canvas.translate(-mScrollX, -mScrollY); + // Temporarily remove the dirty mask + int flags = mPrivateFlags; + mPrivateFlags &= ~DIRTY_MASK; + // Fast path for layouts with no backgrounds if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { dispatchDraw(canvas); @@ -5807,13 +6100,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback { draw(canvas); } + mPrivateFlags = flags; + canvas.restoreToCount(restoreCount); if (attachInfo != null) { // Restore the cached Canvas for our siblings attachInfo.mCanvas = canvas; } - + return bitmap; } @@ -5927,8 +6222,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } - final boolean dirtyOpaque = (mPrivateFlags & DIRTY_MASK) == DIRTY_OPAQUE; - mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; + final int privateFlags = mPrivateFlags; + final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE && + (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); + mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN; /* * Draw traversal performs several drawing steps which must be executed @@ -6306,7 +6603,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { boolean changed = false; if (DBG) { - System.out.println(this + " View.setFrame(" + left + "," + top + "," + Log.d("View", this + " View.setFrame(" + left + "," + top + "," + right + "," + bottom + ")"); } @@ -6709,6 +7006,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { requestLayout = true; } + computeOpaqueFlags(); + if (requestLayout) { requestLayout(); } @@ -6749,7 +7048,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { mUserPaddingBottom = bottom; final int viewFlags = mViewFlags; - + // Common case is there are no scroll bars. if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { // TODO: Deal with RTL languages to adjust left padding instead of right. @@ -6762,7 +7061,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { ? 0 : getHorizontalScrollbarHeight(); } } - + if (mPaddingLeft != left) { changed = true; mPaddingLeft = left; @@ -6899,7 +7198,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { return v; } } - + View parent = this; while (parent.mParent != null && parent.mParent instanceof View) { @@ -6920,8 +7219,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback { getLocationInWindow(location); final AttachInfo info = mAttachInfo; - location[0] += info.mWindowLeft; - location[1] += info.mWindowTop; + if (info != null) { + location[0] += info.mWindowLeft; + location[1] += info.mWindowTop; + } } /** @@ -6947,7 +7248,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { location[1] += view.mTop - view.mScrollY; viewParent = view.mParent; } - + if (viewParent instanceof ViewRoot) { // *cough* final ViewRoot vr = (ViewRoot)viewParent; @@ -7098,7 +7399,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * @return the Object stored in this view as a tag * * @see #setTag(int, Object) - * @see #getTag() + * @see #getTag() */ public Object getTag(int key) { SparseArray<Object> tags = null; @@ -7154,7 +7455,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { + "resource id."); } - setTagInternal(this, key, tag); + setTagInternal(this, key, tag); } private static void setTagInternal(View view, int key, Object tag) { @@ -7189,7 +7490,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { /** * Method that subclasses should implement to check their consistency. The type of * consistency check is indicated by the bit field passed as a parameter. - * + * * @param consistency The type of consistency. See ViewDebug for more information. * * @throws IllegalStateException if the view is in an inconsistent state. @@ -7744,7 +8045,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { /** * BZZZTT!!1! - * + * * <p>Provide haptic feedback to the user for this view. * * <p>The framework will provide haptic feedback for some built in actions, @@ -7763,7 +8064,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { /** * BZZZTT!!1! - * + * * <p>Like {@link #performHapticFeedback(int)}, with additional options. * * @param feedbackConstant One of the constants defined in @@ -8158,7 +8459,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * window. */ static class AttachInfo { - interface Callbacks { void playSoundEffect(int effectId); boolean performHapticFeedback(int effectId, boolean always); @@ -8227,11 +8527,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * The top view of the hierarchy. */ View mRootView; - + IBinder mPanelParentWindowToken; Surface mSurface; /** + * Scale factor used by the compatibility mode + */ + float mApplicationScale; + + /** + * Indicates whether the application is in compatibility mode + */ + boolean mScalingRequired; + + /** * Left position of this view's window */ int mWindowLeft; @@ -8288,6 +8598,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback { long mDrawingTime; /** + * Indicates whether or not ignoring the DIRTY_MASK flags. + */ + boolean mIgnoreDirtyState; + + /** * Indicates whether the view's window is currently in touch mode. */ boolean mInTouchMode; @@ -8365,7 +8680,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * calling up the hierarchy. */ final Rect mTmpInvalRect = new Rect(); - + + /** + * Temporary list for use in collecting focusable descendents of a view. + */ + final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24); + /** * Creates a new set of attachment information with the specified * events handler and thread. @@ -8408,18 +8728,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback { // use use a height of 1, and then wack the matrix each time we // actually use it. shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); - + paint.setShader(shader); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); } - + public void setFadeColor(int color) { if (color != 0 && color != mLastColor) { mLastColor = color; color |= 0xFF000000; - + shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP); - + paint.setShader(shader); // Restore the default transfer mode (src_over) paint.setXfermode(null); diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 8e1524b..0e36ec2 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -106,6 +106,11 @@ public class ViewConfiguration { * Minimum velocity to initiate a fling, as measured in pixels per second */ private static final int MINIMUM_FLING_VELOCITY = 50; + + /** + * Maximum velocity to initiate a fling, as measured in pixels per second + */ + private static final int MAXIMUM_FLING_VELOCITY = 4000; /** * The maximum size of View's drawing cache, expressed in bytes. This size @@ -122,6 +127,7 @@ public class ViewConfiguration { private final int mEdgeSlop; private final int mFadingEdgeLength; private final int mMinimumFlingVelocity; + private final int mMaximumFlingVelocity; private final int mScrollbarSize; private final int mTouchSlop; private final int mDoubleTapSlop; @@ -139,6 +145,7 @@ public class ViewConfiguration { mEdgeSlop = EDGE_SLOP; mFadingEdgeLength = FADING_EDGE_LENGTH; mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY; + mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY; mScrollbarSize = SCROLL_BAR_SIZE; mTouchSlop = TOUCH_SLOP; mDoubleTapSlop = DOUBLE_TAP_SLOP; @@ -164,6 +171,7 @@ public class ViewConfiguration { mEdgeSlop = (int) (density * EDGE_SLOP + 0.5f); mFadingEdgeLength = (int) (density * FADING_EDGE_LENGTH + 0.5f); mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f); + mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f); mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f); mTouchSlop = (int) (density * TOUCH_SLOP + 0.5f); mDoubleTapSlop = (int) (density * DOUBLE_TAP_SLOP + 0.5f); @@ -367,6 +375,23 @@ public class ViewConfiguration { } /** + * @return Maximum velocity to initiate a fling, as measured in pixels per second. + * + * @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead. + */ + @Deprecated + public static int getMaximumFlingVelocity() { + return MAXIMUM_FLING_VELOCITY; + } + + /** + * @return Maximum velocity to initiate a fling, as measured in pixels per second. + */ + public int getScaledMaximumFlingVelocity() { + return mMaximumFlingVelocity; + } + + /** * The maximum drawing cache size expressed in bytes. * * @return the maximum size of View's drawing cache expressed in bytes diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 74a248f..46aea02 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -87,17 +87,17 @@ public class ViewDebug { * check that this value is set to true as not to affect performance. */ public static final boolean TRACE_RECYCLER = false; - + /** * The system property of dynamic switch for capturing view information * when it is set, we dump interested fields and methods for the view on focus - */ + */ static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview"; - + /** * The system property of dynamic switch for capturing event information * when it is set, we log key events, touch/motion and trackball events - */ + */ static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent"; /** @@ -216,7 +216,7 @@ public class ViewDebug { * <pre> * * A specified String is output when the following is true: - * + * * @return An array of int to String mappings */ FlagToString[] flagMapping() default { }; @@ -228,7 +228,7 @@ public class ViewDebug { * * @return true if the properties of this property should be dumped * - * @see #prefix() + * @see #prefix() */ boolean deepExport() default false; @@ -313,15 +313,15 @@ public class ViewDebug { @Retention(RetentionPolicy.RUNTIME) public @interface CapturedViewProperty { /** - * When retrieveReturn is true, we need to retrieve second level methods + * When retrieveReturn is true, we need to retrieve second level methods * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod() - * we will set retrieveReturn = true on the annotation of + * we will set retrieveReturn = true on the annotation of * myView.getFirstLevelMethod() - * @return true if we need the second level methods + * @return true if we need the second level methods */ - boolean retrieveReturn() default false; + boolean retrieveReturn() default false; } - + private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null; private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null; @@ -401,7 +401,7 @@ public class ViewDebug { */ public static long getViewRootInstanceCount() { return ViewRoot.getInstanceCount(); - } + } /** * Outputs a trace to the currently opened recycler traces. The trace records the type of @@ -624,7 +624,7 @@ public class ViewDebug { * * This method will return immediately if TRACE_HIERARCHY is false. * - * @see #startHierarchyTracing(String, View) + * @see #startHierarchyTracing(String, View) * @see #trace(View, android.view.ViewDebug.HierarchyTraceType) */ public static void stopHierarchyTracing() { @@ -671,7 +671,7 @@ public class ViewDebug { sHierarhcyRoot = null; } - + static void dispatchCommand(View view, String command, String parameters, OutputStream clientStream) throws IOException { @@ -1039,10 +1039,10 @@ public class ViewDebug { final ArrayList<Method> foundMethods = new ArrayList<Method>(); methods = klass.getDeclaredMethods(); - + int count = methods.length; for (int i = 0; i < count; i++) { - final Method method = methods[i]; + final Method method = methods[i]; if (method.getParameterTypes().length == 0 && method.isAnnotationPresent(ExportedProperty.class) && method.getReturnType() != Void.class) { @@ -1075,7 +1075,7 @@ public class ViewDebug { klass = klass.getSuperclass(); } while (klass != Object.class); } - + private static void exportMethods(Context context, Object view, BufferedWriter out, Class<?> klass, String prefix) throws IOException { @@ -1235,10 +1235,11 @@ public class ViewDebug { for (int j = 0; j < count; j++) { final FlagToString flagMapping = mapping[j]; final boolean ifTrue = flagMapping.outputIf(); - final boolean test = (intValue & flagMapping.mask()) == flagMapping.equals(); + final int maskResult = intValue & flagMapping.mask(); + final boolean test = maskResult == flagMapping.equals(); if ((test && ifTrue) || (!test && !ifTrue)) { final String name = flagMapping.name(); - final String value = ifTrue ? "true" : "false"; + final String value = "0x" + Integer.toHexString(maskResult); writeEntry(out, prefix, name, "", value); } } @@ -1259,7 +1260,7 @@ public class ViewDebug { for (int j = 0; j < valuesCount; j++) { String name; - String value; + String value = null; final int intValue = array[j]; @@ -1275,7 +1276,6 @@ public class ViewDebug { } } - value = String.valueOf(intValue); if (hasMapping) { int mappingCount = mapping.length; for (int k = 0; k < mappingCount; k++) { @@ -1288,7 +1288,9 @@ public class ViewDebug { } if (resolveId) { - value = (String) resolveId(context, intValue); + if (value == null) value = (String) resolveId(context, intValue); + } else { + value = String.valueOf(intValue); } writeEntry(out, prefix, name, suffix, value); @@ -1396,10 +1398,10 @@ public class ViewDebug { final ArrayList<Method> foundMethods = new ArrayList<Method>(); methods = klass.getMethods(); - + int count = methods.length; for (int i = 0; i < count; i++) { - final Method method = methods[i]; + final Method method = methods[i]; if (method.getParameterTypes().length == 0 && method.isAnnotationPresent(CapturedViewProperty.class) && method.getReturnType() != Void.class) { @@ -1413,14 +1415,14 @@ public class ViewDebug { return methods; } - - private static String capturedViewExportMethods(Object obj, Class<?> klass, + + private static String capturedViewExportMethods(Object obj, Class<?> klass, String prefix) { if (obj == null) { return "null"; } - + StringBuilder sb = new StringBuilder(); final Method[] methods = capturedViewGetPropertyMethods(klass); @@ -1430,41 +1432,41 @@ public class ViewDebug { try { Object methodValue = method.invoke(obj, (Object[]) null); final Class<?> returnType = method.getReturnType(); - + CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class); if (property.retrieveReturn()) { //we are interested in the second level data only sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#")); - } else { + } else { sb.append(prefix); sb.append(method.getName()); sb.append("()="); - + if (methodValue != null) { - final String value = methodValue.toString().replace("\n", "\\n"); - sb.append(value); + final String value = methodValue.toString().replace("\n", "\\n"); + sb.append(value); } else { sb.append("null"); } sb.append("; "); } } catch (IllegalAccessException e) { - //Exception IllegalAccess, it is OK here + //Exception IllegalAccess, it is OK here //we simply ignore this method } catch (InvocationTargetException e) { - //Exception InvocationTarget, it is OK here + //Exception InvocationTarget, it is OK here //we simply ignore this method - } - } + } + } return sb.toString(); } private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) { - + if (obj == null) { return "null"; } - + StringBuilder sb = new StringBuilder(); final Field[] fields = capturedViewGetPropertyFields(klass); @@ -1486,25 +1488,25 @@ public class ViewDebug { } sb.append(' '); } catch (IllegalAccessException e) { - //Exception IllegalAccess, it is OK here + //Exception IllegalAccess, it is OK here //we simply ignore this field } } return sb.toString(); } - + /** - * Dump view info for id based instrument test generation + * Dump view info for id based instrument test generation * (and possibly further data analysis). The results are dumped - * to the log. + * to the log. * @param tag for log * @param view for dump */ - public static void dumpCapturedView(String tag, Object view) { + public static void dumpCapturedView(String tag, Object view) { Class<?> klass = view.getClass(); StringBuilder sb = new StringBuilder(klass.getName() + ": "); sb.append(capturedViewExportFields(view, klass, "")); - sb.append(capturedViewExportMethods(view, klass, "")); - Log.d(tag, sb.toString()); + sb.append(capturedViewExportMethods(view, klass, "")); + Log.d(tag, sb.toString()); } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 26fe776..f7b7f02 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -24,15 +24,16 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.Region; import android.graphics.RectF; +import android.graphics.Region; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; +import android.util.Config; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; -import android.util.Config; +import android.view.accessibility.AccessibilityEvent; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LayoutAnimationController; @@ -52,6 +53,15 @@ import java.util.ArrayList; * <p> * Also see {@link LayoutParams} for layout attributes. * </p> + * + * @attr ref android.R.styleable#ViewGroup_clipChildren + * @attr ref android.R.styleable#ViewGroup_clipToPadding + * @attr ref android.R.styleable#ViewGroup_layoutAnimation + * @attr ref android.R.styleable#ViewGroup_animationCache + * @attr ref android.R.styleable#ViewGroup_persistentDrawingCache + * @attr ref android.R.styleable#ViewGroup_alwaysDrawnWithCache + * @attr ref android.R.styleable#ViewGroup_addStatesFromChildren + * @attr ref android.R.styleable#ViewGroup_descendantFocusability */ public abstract class ViewGroup extends View implements ViewParent, ViewManager { private static final boolean DBG = false; @@ -89,7 +99,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Internal flags. - * + * * This field should be made private, so it is hidden from the SDK. * {@hide} */ @@ -142,7 +152,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * to get the index of the child to draw for that iteration. */ protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400; - + /** * When set, this ViewGroup supports static transformations on children; this causes * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be @@ -151,7 +161,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Any subclass overriding * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should * set this flags in {@link #mGroupFlags}. - * + * * {@hide} */ protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800; @@ -212,7 +222,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * When set, this ViewGroup should not intercept touch events. */ private static final int FLAG_DISALLOW_INTERCEPT = 0x80000; - + /** * Indicates which types of drawing caches are to be kept in memory. * This field should be made private, so it is hidden from the SDK. @@ -601,6 +611,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ @Override public void addFocusables(ArrayList<View> views, int direction) { + addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); + } + + /** + * {@inheritDoc} + */ + @Override + public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { final int focusableCount = views.size(); final int descendantFocusability = getDescendantFocusability(); @@ -612,7 +630,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager for (int i = 0; i < count; i++) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { - child.addFocusables(views, direction); + child.addFocusables(views, direction, focusableMode); } } } @@ -625,7 +643,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager descendantFocusability != FOCUS_AFTER_DESCENDANTS || // No focusable descendants (focusableCount == views.size())) { - super.addFocusables(views, direction); + super.addFocusables(views, direction, focusableMode); } } @@ -680,7 +698,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager ViewParent parent = mParent; if (parent != null) parent.recomputeViewAttributes(this); } - + @Override void dispatchCollectViewAttributes(int visibility) { visibility |= mViewFlags&VISIBILITY_MASK; @@ -812,16 +830,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } } - + boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) || - (action == MotionEvent.ACTION_CANCEL); + (action == MotionEvent.ACTION_CANCEL); if (isUpOrCancel) { // Note, we've already copied the previous state to our local // variable, so this takes effect on the next event mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; } - + // The event wasn't an ACTION_DOWN, dispatch it to our target if // we have one. final View target = mMotionTarget; @@ -868,18 +886,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * {@inheritDoc} */ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - + if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) { // We're already in this state, assume our ancestors are too return; } - + if (disallowIntercept) { mGroupFlags |= FLAG_DISALLOW_INTERCEPT; } else { mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; } - + // Pass it up to our parent if (mParent != null) { mParent.requestDisallowInterceptTouchEvent(disallowIntercept); @@ -1020,6 +1038,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean populated = false; + for (int i = 0, count = getChildCount(); i < count; i++) { + populated |= getChildAt(i).dispatchPopulateAccessibilityEvent(event); + } + return populated; + } + /** * {@inheritDoc} */ @@ -1139,7 +1166,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { child.setDrawingCacheEnabled(true); - child.buildDrawingCache(); + child.buildDrawingCache(true); } } @@ -1181,7 +1208,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager bindLayoutAnimation(child); if (cache) { child.setDrawingCacheEnabled(true); - child.buildDrawingCache(); + child.buildDrawingCache(true); } } } @@ -1274,7 +1301,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager post(end); } } - + /** * Returns the index of the child to draw for this iteration. Override this * if you want to change the drawing order of children. By default, it @@ -1282,14 +1309,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * <p> * NOTE: In order for this method to be called, the * {@link #FLAG_USE_CHILD_DRAWING_ORDER} must be set. - * + * * @param i The current iteration. * @return The index of the child to draw this iteration. */ protected int getChildDrawingOrder(int childCount, int i) { return i; } - + private void notifyAnimationListener() { mGroupFlags &= ~FLAG_NOTIFY_ANIMATION_LISTENER; mGroupFlags |= FLAG_ANIMATION_DONE; @@ -1403,9 +1430,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } - // Clear the flag as early as possible to allow draw() implementations + // Sets the flag as early as possible to allow draw() implementations // to call invalidate() successfully when doing animations - child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN; + child.mPrivateFlags |= DRAWN; if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) && (child.mPrivateFlags & DRAW_ANIMATION) == 0) { @@ -1417,10 +1444,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final int sx = child.mScrollX; final int sy = child.mScrollY; + boolean scalingRequired = false; Bitmap cache = null; if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE || (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) { - cache = child.getDrawingCache(); + cache = child.getDrawingCache(true); + if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; } final boolean hasNoCache = cache == null; @@ -1430,6 +1459,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager canvas.translate(cl - sx, ct - sy); } else { canvas.translate(cl, ct); + if (scalingRequired) { + // mAttachInfo cannot be null, otherwise scalingRequired == false + final float scale = 1.0f / mAttachInfo.mApplicationScale; + canvas.scale(scale, scale); + } } float alpha = 1.0f; @@ -1472,7 +1506,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (hasNoCache) { canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct)); } else { - canvas.clipRect(0, 0, cr - cl, cb - ct); + if (!scalingRequired) { + canvas.clipRect(0, 0, cr - cl, cb - ct); + } else { + canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); + } } } @@ -1482,6 +1520,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } + child.mPrivateFlags &= ~DIRTY_MASK; child.dispatchDraw(canvas); } else { child.draw(canvas); @@ -1546,7 +1585,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager children[i].setSelected(selected); } } - + @Override protected void dispatchSetPressed(boolean pressed) { final View[] children = mChildren; @@ -1577,7 +1616,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * {@inheritDoc} * - * @see #setStaticTransformationsEnabled(boolean) + * @see #setStaticTransformationsEnabled(boolean) */ protected boolean getChildStaticTransformation(View child, Transformation t) { return false; @@ -1844,10 +1883,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (child.hasFocus()) { requestChildFocus(child, child.findFocus()); } - + AttachInfo ai = mAttachInfo; if (ai != null) { - boolean lastKeepOn = ai.mKeepScreenOn; + boolean lastKeepOn = ai.mKeepScreenOn; ai.mKeepScreenOn = false; child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK)); if (ai.mKeepScreenOn) { @@ -2047,7 +2086,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } needGlobalAttributesUpdate(false); - + removeFromArray(index); if (clearChildFocus) { @@ -2080,7 +2119,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } needGlobalAttributesUpdate(false); - + if (notifyListener) { onHierarchyChangeListener.onChildViewRemoved(this, view); } @@ -2128,7 +2167,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager View clearChildFocus = null; needGlobalAttributesUpdate(false); - + for (int i = count - 1; i >= 0; i--) { final View view = children[i]; @@ -2173,7 +2212,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (child == mFocused) { child.clearFocus(); } - + if (animate && child.getAnimation() != null) { addDisappearingView(child); } else if (child.mAttachInfo != null) { @@ -2323,7 +2362,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION; // Check whether the child that requests the invalidate is fully opaque - final boolean isOpaque = child.isOpaque(); + final boolean isOpaque = child.isOpaque() && !drawAnimation && + child.getAnimation() != null; // Mark the child as dirty, using the appropriate flag // Make sure we do not set both flags at the same time final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY; @@ -3135,7 +3175,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } } - + @Override protected boolean fitSystemWindows(Rect insets) { @@ -3269,7 +3309,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * laid out. See * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes} * for a list of all child view attributes that this class supports. - * + * * <p> * The base LayoutParams class just describes how big the view wants to be * for both width and height. For each dimension, it can specify one of: @@ -3400,7 +3440,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @param output the String to prepend to the internal representation * @return a String with the following format: output + * "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }" - * + * * @hide */ public String debug(String output) { @@ -3413,7 +3453,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @param size the size to convert * @return a String instance representing the supplied size - * + * * @hide */ protected static String sizeToString(int size) { diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 5090c56..6f6e224 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -30,14 +30,18 @@ import android.os.Process; import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.Config; +import android.util.DisplayMetrics; import android.util.Log; import android.util.EventLog; import android.util.SparseArray; import android.view.View.MeasureSpec; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; import android.content.pm.PackageManager; +import android.content.res.CompatibilityInfo; import android.content.Context; import android.app.ActivityManagerNative; import android.Manifest; @@ -90,18 +94,18 @@ public final class ViewRoot extends Handler implements ViewParent, static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>(); - private static int sDrawTime; + private static int sDrawTime; long mLastTrackballTime = 0; final TrackballAxis mTrackballAxisX = new TrackballAxis(); final TrackballAxis mTrackballAxisY = new TrackballAxis(); final int[] mTmpLocation = new int[2]; - + final InputMethodCallback mInputMethodCallback; final SparseArray<Object> mPendingEvents = new SparseArray<Object>(); int mPendingEventSeq = 0; - + final Thread mThread; final WindowLeaked mLocation; @@ -123,16 +127,13 @@ public final class ViewRoot extends Handler implements ViewParent, int mHeight; Rect mDirty; // will be a graphics.Region soon boolean mIsAnimating; - // TODO: change these to scalar class. - private float mAppScale; - private float mAppScaleInverted; // = 1.0f / mAppScale - private int[] mWindowLayoutParamsBackup = null; + + 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; @@ -168,7 +169,7 @@ public final class ViewRoot extends Handler implements ViewParent, int mScrollY; int mCurScrollY; Scroller mScroller; - + EGL10 mEgl; EGLDisplay mEglDisplay; EGLContext mEglContext; @@ -178,7 +179,7 @@ public final class ViewRoot extends Handler implements ViewParent, boolean mUseGL; boolean mGlWanted; - final ViewConfiguration mViewConfiguration; + final ViewConfiguration mViewConfiguration; /** * see {@link #playSoundEffect(int)} @@ -216,7 +217,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); @@ -384,29 +384,39 @@ public final class ViewRoot extends Handler implements ViewParent, synchronized (this) { if (mView == null) { mView = view; - mAppScale = mView.getContext().getApplicationScale(); - if (mAppScale != 1.0f) { - mWindowLayoutParamsBackup = new int[4]; - } - mAppScaleInverted = 1.0f / mAppScale; mWindowAttributes.copyFrom(attrs); + + CompatibilityInfo compatibilityInfo = + mView.getContext().getResources().getCompatibilityInfo(); + mTranslator = compatibilityInfo.getTranslator(attrs); + boolean restore = false; + if (attrs != null && mTranslator != null) { + restore = true; + 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 = + mTranslator == null ? false : mTranslator.scalingRequired; + mAttachInfo.mApplicationScale = + mTranslator == null ? 1.0f : mTranslator.applicationScale; if (panelParentView != null) { mAttachInfo.mPanelParentWindowToken = panelParentView.getApplicationWindowToken(); } mAdded = true; int res; /* = WindowManagerImpl.ADD_OKAY; */ - + // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout(); - try { - res = sWindowSession.add(mWindow, attrs, + res = sWindowSession.add(mWindow, mWindowAttributes, getHostVisibility(), mAttachInfo.mContentInsets); } catch (RemoteException e) { mAdded = false; @@ -414,8 +424,15 @@ 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 (mTranslator != null) { + mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets); } - mAttachInfo.mContentInsets.scale(mAppScaleInverted); mPendingContentInsets.set(mAttachInfo.mContentInsets); mPendingVisibleInsets.set(0, 0, 0, 0); if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow); @@ -526,18 +543,20 @@ 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 || mAppScale != 1.0f) { + if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty); + if (mCurScrollY != 0 || mTranslator != null) { mTempRect.set(dirty); + dirty = mTempRect; if (mCurScrollY != 0) { - mTempRect.offset(0, -mCurScrollY); + dirty.offset(0, -mCurScrollY); } - if (mAppScale != 1.0f) { - mTempRect.scale(mAppScale); + if (mTranslator != null) { + mTranslator.translateRectInAppWindowToScreen(dirty); + } + if (mAttachInfo.mScalingRequired) { + dirty.inset(-1, -1); } - dirty = mTempRect; } - // TODO: When doing a union with mDirty != empty, we must cancel all the DIRTY_OPAQUE flags mDirty.union(dirty); if (!mWillDrawSoon) { scheduleTraversals(); @@ -553,7 +572,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!"); } @@ -582,7 +601,7 @@ public final class ViewRoot extends Handler implements ViewParent, int getHostVisibility() { return mAppVisible ? mView.getVisibility() : View.GONE; } - + private void performTraversals() { // cache mView since it is used so much below... final View host = mView; @@ -614,19 +633,22 @@ public final class ViewRoot extends Handler implements ViewParent, boolean viewVisibilityChanged = mViewVisibility != viewVisibility || mNewSurfaceNeeded; + float appScale = mAttachInfo.mApplicationScale; + WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; params = lp; } - + Rect frame = mWinFrame; if (mFirst) { fullRedrawNeeded = true; mLayoutRequested = true; - Display d = new Display(0); - desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted); - desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted); + DisplayMetrics packageMetrics = + mView.getContext().getResources().getDisplayMetrics(); + desiredWindowWidth = packageMetrics.widthPixels; + desiredWindowHeight = packageMetrics.heightPixels; // For the very first time, tell the view hierarchy that it // is attached to the window. Note that at this point the surface @@ -641,12 +663,13 @@ public final class ViewRoot extends Handler implements ViewParent, host.dispatchAttachedToWindow(attachInfo, 0); getRunQueue().executeActions(attachInfo.mHandler); //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; @@ -669,7 +692,7 @@ public final class ViewRoot extends Handler implements ViewParent, } boolean insetsChanged = false; - + if (mLayoutRequested) { if (mFirst) { host.fitSystemWindows(mAttachInfo.mContentInsets); @@ -694,9 +717,10 @@ public final class ViewRoot extends Handler implements ViewParent, || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { windowResizesToFitContent = true; - Display d = new Display(0); - desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted); - desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted); + DisplayMetrics packageMetrics = + mView.getContext().getResources().getDisplayMetrics(); + desiredWindowWidth = packageMetrics.widthPixels; + desiredWindowHeight = packageMetrics.heightPixels; } } @@ -753,7 +777,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } } - + if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) { if (!PixelFormat.formatHasAlpha(params.format)) { params.format = PixelFormat.TRANSLUCENT; @@ -782,7 +806,7 @@ public final class ViewRoot extends Handler implements ViewParent, // computed insets. insetsPending = computesInternalInsets && (mFirst || viewVisibilityChanged); - + if (mWindowAttributes.memoryType == WindowManager.LayoutParams.MEMORY_TYPE_GPU) { if (params == null) { params = mWindowAttributes; @@ -791,7 +815,6 @@ public final class ViewRoot extends Handler implements ViewParent, } } - final Rect frame = mWinFrame; boolean initialized = false; boolean contentInsetsChanged = false; boolean visibleInsetsChanged; @@ -818,7 +841,7 @@ public final class ViewRoot extends Handler implements ViewParent, + " content=" + mPendingContentInsets.toShortString() + " visible=" + mPendingVisibleInsets.toShortString() + " surface=" + mSurface); - + contentInsetsChanged = !mPendingContentInsets.equals( mAttachInfo.mContentInsets); visibleInsetsChanged = !mPendingVisibleInsets.equals( @@ -846,7 +869,7 @@ public final class ViewRoot extends Handler implements ViewParent, // all at once. newSurface = true; fullRedrawNeeded = true; - + if (mGlWanted && !mUseGL) { initializeGL(); initialized = mGlCanvas != null; @@ -864,7 +887,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; @@ -876,7 +899,7 @@ public final class ViewRoot extends Handler implements ViewParent, mHeight = frame.height(); if (initialized) { - mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale)); + mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale)); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( @@ -891,7 +914,7 @@ public final class ViewRoot extends Handler implements ViewParent, + " mHeight=" + mHeight + " measuredHeight" + host.mMeasuredHeight + " coveredInsetsChanged=" + contentInsetsChanged); - + // Ask host how big it wants to be host.measure(childWidthMeasureSpec, childHeightMeasureSpec); @@ -939,7 +962,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) { @@ -966,11 +988,10 @@ public final class ViewRoot extends Handler implements ViewParent, mTmpLocation[1] + host.mBottom - host.mTop); host.gatherTransparentRegion(mTransparentRegion); + if (mTranslator != null) { + mTranslator.translateRegionInWindowToScreen(mTransparentRegion); + } - // TODO: scale the region, like: - // Region uses native methods. We probabl should have ScalableRegion class. - - // Region does not have equals method ? if (!mTransparentRegion.equals(mPreviousTransparentRegion)) { mPreviousTransparentRegion.set(mTransparentRegion); // reconfigure window manager @@ -981,7 +1002,6 @@ public final class ViewRoot extends Handler implements ViewParent, } } - if (DBG) { System.out.println("======================================"); System.out.println("performTraversals -- after setFrame"); @@ -1001,20 +1021,23 @@ public final class ViewRoot extends Handler implements ViewParent, givenContent.left = givenContent.top = givenContent.right = givenContent.bottom = givenVisible.left = givenVisible.top = givenVisible.right = givenVisible.bottom = 0; - insets.contentInsets.scale(mAppScale); - insets.visibleInsets.scale(mAppScale); - attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); + 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) { } } } - + if (mFirst) { // handle first focus request if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()=" @@ -1052,7 +1075,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } } - + boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw(); if (!cancelDraw && !newSurface) { @@ -1140,10 +1163,9 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mViewScrollChanged = false; mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); } - + int yoff; - final boolean scrolling = mScroller != null - && mScroller.computeScrollOffset(); + final boolean scrolling = mScroller != null && mScroller.computeScrollOffset(); if (scrolling) { yoff = mScroller.getCurrY(); } else { @@ -1153,26 +1175,28 @@ public final class ViewRoot extends Handler implements ViewParent, mCurScrollY = yoff; fullRedrawNeeded = true; } + float appScale = mAttachInfo.mApplicationScale; + boolean scalingRequired = mAttachInfo.mScalingRequired; Rect dirty = mDirty; if (mUseGL) { if (!dirty.isEmpty()) { Canvas canvas = mGlCanvas; - if (mGL!=null && canvas != null) { + if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); + mAttachInfo.mIgnoreDirtyState = true; mView.mPrivateFlags |= View.DRAWN; - float scale = mAppScale; int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); - if (scale != 1.0f) { - canvas.scale(scale, scale); + if (mTranslator != null) { + mTranslator.translateCanvas(canvas); } mView.draw(canvas); if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { @@ -1182,6 +1206,8 @@ public final class ViewRoot extends Handler implements ViewParent, canvas.restoreToCount(saveCount); } + mAttachInfo.mIgnoreDirtyState = false; + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkEglErrors(); @@ -1201,20 +1227,33 @@ public final class ViewRoot extends Handler implements ViewParent, return; } - if (fullRedrawNeeded) - dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale)); + if (fullRedrawNeeded) { + mAttachInfo.mIgnoreDirtyState = true; + dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale)); + } if (DEBUG_ORIENTATION || DEBUG_DRAW) { Log.v("ViewRoot", "Draw " + mView + "/" + mWindowAttributes.getTitle() + ": dirty={" + dirty.left + "," + dirty.top + "," + dirty.right + "," + dirty.bottom + "} surface=" - + surface + " surface.isValid()=" + surface.isValid()); + + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" + + appScale + ", width=" + mWidth + ", height=" + mHeight); } Canvas canvas; try { + int left = dirty.left; + 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 || + bottom != dirty.bottom) { + mAttachInfo.mIgnoreDirtyState = true; + } + // TODO: Do this in native canvas.setDensityScale(mDensity); } catch (Surface.OutOfResourcesException e) { @@ -1242,12 +1281,11 @@ public final class ViewRoot extends Handler implements ViewParent, // need to clear it before drawing so that the child will // properly re-composite its drawing on a transparent // background. This automatically respects the clip/dirty region - if (!canvas.isOpaque()) { - canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); - } else if (yoff != 0) { - // If we are applying an offset, we need to clear the area - // where the offset doesn't appear to avoid having garbage - // left in the blank areas. + // or + // If we are applying an offset, we need to clear the area + // where the offset doesn't appear to avoid having garbage + // left in the blank areas. + if (!canvas.isOpaque() || yoff != 0) { canvas.drawColor(0, PorterDuff.Mode.CLEAR); } @@ -1256,27 +1294,27 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); mView.mPrivateFlags |= View.DRAWN; - float scale = mAppScale; - Context cxt = mView.getContext(); if (DEBUG_DRAW) { - Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + ", appScale=" + mAppScale); + Context cxt = mView.getContext(); + Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + + ", metrics=" + mView.getContext().getResources().getDisplayMetrics()); } - int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); + int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); - if (scale != 1.0f) { - // re-scale this - canvas.scale(scale, scale); + if (mTranslator != null) { + mTranslator.translateCanvas(canvas); } mView.draw(canvas); - - if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { - mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); - } } finally { + mAttachInfo.mIgnoreDirtyState = false; canvas.restoreToCount(saveCount); } + if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { + mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); + } + if (Config.DEBUG && ViewDebug.showFps) { int now = (int)SystemClock.elapsedRealtime(); if (sDrawTime != 0) { @@ -1289,7 +1327,7 @@ public final class ViewRoot extends Handler implements ViewParent, EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime); } } - + } finally { surface.unlockCanvasAndPost(canvas); } @@ -1297,7 +1335,7 @@ public final class ViewRoot extends Handler implements ViewParent, if (LOCAL_LOGV) { Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost"); } - + if (scrolling) { mFullRedrawNeeded = true; scheduleTraversals(); @@ -1310,7 +1348,7 @@ public final class ViewRoot extends Handler implements ViewParent, final Rect vi = attachInfo.mVisibleInsets; int scrollY = 0; boolean handled = false; - + if (vi.left > ci.left || vi.top > ci.top || vi.right > ci.right || vi.bottom > ci.bottom) { // We'll assume that we aren't going to change the scroll @@ -1397,7 +1435,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } } - + if (scrollY != mScrollY) { if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old=" + mScrollY + " , new=" + scrollY); @@ -1411,10 +1449,10 @@ public final class ViewRoot extends Handler implements ViewParent, } mScrollY = scrollY; } - + return handled; } - + public void requestChildFocus(View child, View focused) { checkThread(); if (mFocusedView != focused) { @@ -1494,7 +1532,7 @@ public final class ViewRoot extends Handler implements ViewParent, } catch (RemoteException e) { } } - + /** * Return true if child is an ancestor of parent, (or equal to the parent). */ @@ -1568,10 +1606,9 @@ public final class ViewRoot extends Handler implements ViewParent, } else { didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE; } - if (event != null) { - event.scale(mAppScaleInverted); + if (event != null && mTranslator != null) { + mTranslator.translateEventInScreenToAppWindow(event); } - try { boolean handled; if (mView != null && mAdded && event != null) { @@ -1657,6 +1694,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)) { @@ -1691,16 +1729,17 @@ public final class ViewRoot extends Handler implements ViewParent, if (mGlWanted && !mUseGL) { initializeGL(); if (mGlCanvas != null) { - mGlCanvas.setViewport((int) (mWidth * mAppScale), - (int) (mHeight * mAppScale)); + float appScale = mAttachInfo.mApplicationScale; + mGlCanvas.setViewport( + (int) (mWidth * appScale), (int) (mHeight * appScale)); } } } } - + mLastWasImTarget = WindowManager.LayoutParams .mayUseInputMethod(mWindowAttributes.flags); - + InputMethodManager imm = InputMethodManager.peekInstance(); if (mView != null) { if (hasWindowFocus && imm != null && mLastWasImTarget) { @@ -1708,7 +1747,7 @@ public final class ViewRoot extends Handler implements ViewParent, } mView.dispatchWindowFocusChanged(hasWindowFocus); } - + // Note: must be done after the focus change callbacks, // so all of the view state is set up correctly. if (hasWindowFocus) { @@ -1726,6 +1765,10 @@ public final class ViewRoot extends Handler implements ViewParent, ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; mHasHadWindowFocus = true; } + + if (hasWindowFocus && mView != null) { + sendAccessibilityEvents(); + } } } break; case DIE: @@ -1892,9 +1935,6 @@ public final class ViewRoot extends Handler implements ViewParent, } else { didFinish = false; } - if (event != null) { - event.scale(mAppScaleInverted); - } if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event); @@ -2120,50 +2160,50 @@ public final class ViewRoot extends Handler implements ViewParent, } /** - * log motion events + * log motion events */ private static void captureMotionLog(String subTag, MotionEvent ev) { - //check dynamic switch + //check dynamic switch if (ev == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) { return; - } - - StringBuilder sb = new StringBuilder(subTag + ": "); - sb.append(ev.getDownTime()).append(','); - sb.append(ev.getEventTime()).append(','); - sb.append(ev.getAction()).append(','); - sb.append(ev.getX()).append(','); - sb.append(ev.getY()).append(','); - sb.append(ev.getPressure()).append(','); - sb.append(ev.getSize()).append(','); - sb.append(ev.getMetaState()).append(','); - sb.append(ev.getXPrecision()).append(','); - sb.append(ev.getYPrecision()).append(','); - sb.append(ev.getDeviceId()).append(','); + } + + StringBuilder sb = new StringBuilder(subTag + ": "); + sb.append(ev.getDownTime()).append(','); + sb.append(ev.getEventTime()).append(','); + sb.append(ev.getAction()).append(','); + sb.append(ev.getX()).append(','); + sb.append(ev.getY()).append(','); + sb.append(ev.getPressure()).append(','); + sb.append(ev.getSize()).append(','); + sb.append(ev.getMetaState()).append(','); + sb.append(ev.getXPrecision()).append(','); + sb.append(ev.getYPrecision()).append(','); + sb.append(ev.getDeviceId()).append(','); sb.append(ev.getEdgeFlags()); - Log.d(TAG, sb.toString()); + Log.d(TAG, sb.toString()); } /** - * log motion events + * log motion events */ private static void captureKeyLog(String subTag, KeyEvent ev) { - //check dynamic switch - if (ev == null || + //check dynamic switch + if (ev == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) { return; } - StringBuilder sb = new StringBuilder(subTag + ": "); + StringBuilder sb = new StringBuilder(subTag + ": "); sb.append(ev.getDownTime()).append(','); sb.append(ev.getEventTime()).append(','); sb.append(ev.getAction()).append(','); - sb.append(ev.getKeyCode()).append(','); + sb.append(ev.getKeyCode()).append(','); sb.append(ev.getRepeatCount()).append(','); sb.append(ev.getMetaState()).append(','); sb.append(ev.getDeviceId()).append(','); sb.append(ev.getScanCode()); - Log.d(TAG, sb.toString()); - } + Log.d(TAG, sb.toString()); + } int enqueuePendingEvent(Object event, boolean sendDone) { int seq = mPendingEventSeq+1; @@ -2181,7 +2221,7 @@ public final class ViewRoot extends Handler implements ViewParent, } return event; } - + private void deliverKeyEvent(KeyEvent event, boolean sendDone) { // If mView is null, we just consume the key event because it doesn't // make sense to do anything else with it. @@ -2238,7 +2278,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } } - + private void deliverKeyEventToViewHierarchy(KeyEvent event, boolean sendDone) { try { if (mView != null && mAdded) { @@ -2247,8 +2287,8 @@ public final class ViewRoot extends Handler implements ViewParent, if (checkForLeavingTouchModeAndConsume(event)) { return; - } - + } + if (Config.LOGV) { captureKeyLog("captureDispatchKeyEvent", event); } @@ -2324,24 +2364,31 @@ 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; - if (params != null && mAppScale != 1.0f) { + if (params != null && mTranslator != null) { restore = true; - params.scale(mAppScale, mWindowLayoutParamsBackup); + params.backup(); + mTranslator.translateWindowLayout(params); + } + if (params != null) { + if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params); } int relayoutResult = sWindowSession.relayout( mWindow, params, - (int) (mView.mMeasuredWidth * mAppScale), - (int) (mView.mMeasuredHeight * mAppScale), + (int) (mView.mMeasuredWidth * appScale), + (int) (mView.mMeasuredHeight * appScale), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mSurface); if (restore) { - params.restore(mWindowLayoutParamsBackup); + params.restore(); + } + + if (mTranslator != null) { + mTranslator.translateRectInScreenToAppWinFrame(mWinFrame); + mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets); + mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets); } - - mPendingContentInsets.scale(mAppScaleInverted); - mPendingVisibleInsets.scale(mAppScaleInverted); - mWinFrame.scale(mAppScaleInverted); return relayoutResult; } @@ -2448,11 +2495,14 @@ public final class ViewRoot extends Handler implements ViewParent, + " visibleInsets=" + visibleInsets.toShortString() + " reportDraw=" + reportDraw); Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED); - - coveredInsets.scale(mAppScaleInverted); - visibleInsets.scale(mAppScaleInverted); - msg.arg1 = (int) (w * mAppScaleInverted); - msg.arg2 = (int) (h * mAppScaleInverted); + 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); } @@ -2511,6 +2561,21 @@ public final class ViewRoot extends Handler implements ViewParent, sendMessage(msg); } + /** + * The window is getting focus so if there is anything focused/selected + * send an {@link AccessibilityEvent} to announce that. + */ + private void sendAccessibilityEvents() { + if (!AccessibilityManager.getInstance(mView.getContext()).isEnabled()) { + return; + } + mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + View focusedView = mView.findFocus(); + if (focusedView != null && focusedView != mView) { + focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + } + public boolean showContextMenuForChild(View originalView) { return false; } @@ -2540,14 +2605,14 @@ public final class ViewRoot extends Handler implements ViewParent, boolean immediate) { return scrollToRectOrFocus(rectangle, immediate); } - + static class InputMethodCallback extends IInputMethodCallback.Stub { private WeakReference<ViewRoot> mViewRoot; public InputMethodCallback(ViewRoot viewRoot) { mViewRoot = new WeakReference<ViewRoot>(viewRoot); } - + public void finishedEvent(int seq, boolean handled) { final ViewRoot viewRoot = mViewRoot.get(); if (viewRoot != null) { @@ -2559,13 +2624,13 @@ public final class ViewRoot extends Handler implements ViewParent, // Stub -- not for use in the client. } } - + static class EventCompletion extends Handler { final IWindow mWindow; final KeyEvent mKeyEvent; final boolean mIsPointer; final MotionEvent mMotionEvent; - + EventCompletion(Looper looper, IWindow window, KeyEvent key, boolean isPointer, MotionEvent motion) { super(looper); @@ -2575,7 +2640,7 @@ public final class ViewRoot extends Handler implements ViewParent, mMotionEvent = motion; sendEmptyMessage(0); } - + @Override public void handleMessage(Message msg) { if (mKeyEvent != null) { @@ -2617,7 +2682,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } } - + static class W extends IWindow.Stub { private final WeakReference<ViewRoot> mViewRoot; private final Looper mMainLooper; @@ -2739,14 +2804,14 @@ public final class ViewRoot extends Handler implements ViewParent, * The maximum amount of acceleration we will apply. */ static final float MAX_ACCELERATION = 20; - + /** * The maximum amount of time (in milliseconds) between events in order * for us to consider the user to be doing fast trackball movements, * and thus apply an acceleration. */ static final long FAST_MOVE_TIME = 150; - + /** * Scaling factor to the time (in milliseconds) between events to how * much to multiple/divide the current acceleration. When movement @@ -2754,7 +2819,7 @@ public final class ViewRoot extends Handler implements ViewParent, * FAST_MOVE_TIME it divides it. */ static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40); - + float position; float absPosition; float acceleration = 1; @@ -2806,7 +2871,7 @@ public final class ViewRoot extends Handler implements ViewParent, } else { normTime = 0; } - + // The number of milliseconds between each movement that is // considered "normal" and will not result in any acceleration // or deceleration, scaled by the offset we have here. @@ -2964,7 +3029,7 @@ public final class ViewRoot extends Handler implements ViewParent, sRunQueues.set(rq); return rq; } - + /** * @hide */ diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 428de67..d7457a0 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -24,7 +24,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; -import android.util.Log; +import android.view.accessibility.AccessibilityEvent; /** * Abstract base class for a top-level window look and behavior policy. An @@ -153,7 +153,16 @@ public abstract class Window { * @return boolean Return true if this event was consumed. */ public boolean dispatchTrackballEvent(MotionEvent event); - + + /** + * Called to process population of {@link AccessibilityEvent}s. + * + * @param event The event. + * + * @return boolean Return true if event population was completed. + */ + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event); + /** * Instantiate the view to display in the panel for 'featureId'. * You can return null, in which case the default content (typically @@ -367,8 +376,14 @@ public abstract class Window { String title; if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) { title="Media"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) { + title="MediaOvr"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { title="Panel"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) { + title="SubPanel"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) { + title="AtchDlg"; } else { title=Integer.toString(wp.type); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index c69c281..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; @@ -210,6 +209,15 @@ public interface WindowManager extends ViewManager { public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3; /** + * Window type: window for showing overlays on top of media windows. + * These windows are displayed between TYPE_APPLICATION_MEDIA and the + * application window. They should be translucent to be useful. This + * is a big ugly hack so: + * @hide + */ + public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4; + + /** * End of types of sub-windows. */ public static final int LAST_SUB_WINDOW = 1999; @@ -466,6 +474,21 @@ public interface WindowManager extends ViewManager { */ public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; + /** Window flag: special flag to let windows be shown when the screen + * is locked. This will let application windows take precedence over + * key guard or any other lock screens. Can be used with + * {@link #FLAG_KEEP_SCREEN_ON} to turn screen on and display windows + * directly before showing the key guard window + * + * {@hide} */ + public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; + + /** Window flag: 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. @@ -787,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; @@ -800,6 +824,9 @@ public interface WindowManager extends ViewManager { public static final int SCREEN_ORIENTATION_CHANGED = 1<<10; public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11; + // internal buffer to backup/restore parameters under compatibility mode. + private int[] mCompatibilityParamsBackup = null; + public final int copyFrom(LayoutParams o) { int changes = 0; @@ -957,36 +984,45 @@ public interface WindowManager extends ViewManager { /** * Scale the layout params' coordinates and size. - * Returns the original info as a backup so that the caller can - * restore the layout params; - */ - void scale(float scale, int[] backup) { - if (scale != 1.0f) { - backup[0] = x; - backup[1] = y; - x *= scale; - y *= scale; - if (width > 0) { - backup[2] = width; - width *= scale; - } - if (height > 0) { - backup[3] = height; - height *= scale; - } + * @hide + */ + public void scale(float scale) { + x *= scale; + y *= scale; + if (width > 0) { + width *= scale; + } + if (height > 0) { + height *= scale; } } /** - * Restore the layout params' coordinates and size. - */ - void restore(int[] backup) { - x = backup[0]; - y = backup[1]; - if (width > 0) { - width = backup[2]; + * Backup the layout parameters used in compatibility mode. + * @see LayoutParams#restore() + */ + void backup() { + int[] backup = mCompatibilityParamsBackup; + if (backup == null) { + // we backup 4 elements, x, y, width, height + backup = mCompatibilityParamsBackup = new int[4]; } - if (height > 0) { + backup[0] = x; + backup[1] = y; + backup[2] = width; + backup[3] = height; + } + + /** + * Restore the layout params' coordinates, size and gravity + * @see LayoutParams#backup() + */ + void restore() { + int[] backup = mCompatibilityParamsBackup; + if (backup != null) { + x = backup[0]; + y = backup[1]; + width = backup[2]; height = backup[3]; } } diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 755d7b8..0973599 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -173,7 +173,6 @@ public class WindowManagerImpl implements WindowManager { mRoots[index] = root; mParams[index] = wparams; } - // do this last because it fires off messages to start doing things root.setView(view, wparams, panelParentView); } diff --git a/core/java/android/view/accessibility/AccessibilityEvent.aidl b/core/java/android/view/accessibility/AccessibilityEvent.aidl new file mode 100644 index 0000000..cee3604 --- /dev/null +++ b/core/java/android/view/accessibility/AccessibilityEvent.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2009, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility; + +parcelable AccessibilityEvent; diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java new file mode 100644 index 0000000..c22f991 --- /dev/null +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -0,0 +1,734 @@ +/* + * 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.view.accessibility; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents accessibility events that are sent by the system when + * something notable happens in the user interface. For example, when a + * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc. + * <p> + * This class represents various semantically different accessibility event + * types. Each event type has associated a set of related properties. In other + * words, each event type is characterized via a subset of the properties exposed + * by this class. For each event type there is a corresponding constant defined + * in this class. Since some event types are semantically close there are mask + * constants that group them together. Follows a specification of the event + * types and their associated properties: + * <p> + * <b>VIEW TYPES</b> <br> + * <p> + * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View} + * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> + * Type:{@link #TYPE_VIEW_CLICKED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()}, + * {@link #isChecked()}, + * {@link #isEnabled()}, + * {@link #isPassword()}, + * {@link #getItemCount()}, + * {@link #getCurrentItemIndex()} + * <p> + * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View} + * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br> + * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()}, + * {@link #isChecked()}, + * {@link #isEnabled()}, + * {@link #isPassword()}, + * {@link #getItemCount()}, + * {@link #getCurrentItemIndex()} + * <p> + * <b>View selected</b> - represents the event of selecting an item usually in + * the context of an {@link android.widget.AdapterView}. <br> + * Type: {@link #TYPE_VIEW_SELECTED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()}, + * {@link #isChecked()}, + * {@link #isEnabled()}, + * {@link #isPassword()}, + * {@link #getItemCount()}, + * {@link #getCurrentItemIndex()} + * <p> + * <b>View focused</b> - represents the event of focusing a + * {@link android.view.View}. <br> + * Type: {@link #TYPE_VIEW_FOCUSED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()}, + * {@link #isChecked()}, + * {@link #isEnabled()}, + * {@link #isPassword()}, + * {@link #getItemCount()}, + * {@link #getCurrentItemIndex()} + * <p> + * <b>View text changed</b> - represents the event of changing the text of an + * {@link android.widget.EditText}. <br> + * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()}, + * {@link #isChecked()}, + * {@link #isEnabled()}, + * {@link #isPassword()}, + * {@link #getItemCount()}, + * {@link #getCurrentItemIndex()}, + * {@link #getFromIndex()}, + * {@link #getAddedCount()}, + * {@link #getRemovedCount()}, + * {@link #getBeforeText()} + * <p> + * <b>TRANSITION TYPES</b> <br> + * <p> + * <b>Window state changed</b> - represents the event of opening/closing a + * {@link android.widget.PopupWindow}, {@link android.view.Menu}, + * {@link android.app.Dialog}, etc. <br> + * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()} + * <p> + * <b>NOTIFICATION TYPES</b> <br> + * <p> + * <b>Notification state changed</b> - represents the event showing/hiding + * {@link android.app.Notification}. + * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br> + * Properties: + * {@link #getClassName()}, + * {@link #getPackageName()}, + * {@link #getEventTime()}, + * {@link #getText()} + * {@link #getParcelableData()} + * <p> + * <b>Security note</b> + * <p> + * Since an event contains the text of its source privacy can be compromised by leaking of + * sensitive information such as passwords. To address this issue any event fired in response + * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password. + * + * @see android.view.accessibility.AccessibilityManager + * @see android.accessibilityservice.AccessibilityService + */ +public final class AccessibilityEvent implements Parcelable { + + /** + * Invalid selection/focus position. + * + * @see #getCurrentItemIndex() + */ + public static final int INVALID_POSITION = -1; + + /** + * Maximum length of the text fields. + * + * @see #getBeforeText() + * @see #getText() + */ + public static final int MAX_TEXT_LENGTH = 500; + + /** + * Represents the event of clicking on a {@link android.view.View} like + * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. + */ + public static final int TYPE_VIEW_CLICKED = 0x00000001; + + /** + * Represents the event of long clicking on a {@link android.view.View} like + * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. + */ + public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; + + /** + * Represents the event of selecting an item usually in the context of an + * {@link android.widget.AdapterView}. + */ + public static final int TYPE_VIEW_SELECTED = 0x00000004; + + /** + * Represents the event of focusing a {@link android.view.View}. + */ + public static final int TYPE_VIEW_FOCUSED = 0x00000008; + + /** + * Represents the event of changing the text of an {@link android.widget.EditText}. + */ + public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; + + /** + * Represents the event of opening/closing a {@link android.widget.PopupWindow}, + * {@link android.view.Menu}, {@link android.app.Dialog}, etc. + */ + public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; + + /** + * Represents the event showing/hiding a {@link android.app.Notification}. + */ + public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; + + /** + * Mask for {@link AccessibilityEvent} all types. + * + * @see #TYPE_VIEW_CLICKED + * @see #TYPE_VIEW_LONG_CLICKED + * @see #TYPE_VIEW_SELECTED + * @see #TYPE_VIEW_FOCUSED + * @see #TYPE_VIEW_TEXT_CHANGED + * @see #TYPE_WINDOW_STATE_CHANGED + * @see #TYPE_NOTIFICATION_STATE_CHANGED + */ + public static final int TYPES_ALL_MASK = 0xFFFFFFFF; + + private static final int MAX_POOL_SIZE = 2; + private static final Object mPoolLock = new Object(); + private static AccessibilityEvent sPool; + private static int sPoolSize; + + private static final int CHECKED = 0x00000001; + private static final int ENABLED = 0x00000002; + private static final int PASSWORD = 0x00000004; + private static final int FULL_SCREEN = 0x00000080; + + private AccessibilityEvent mNext; + + private int mEventType; + private int mBooleanProperties; + private int mCurrentItemIndex; + private int mItemCount; + private int mFromIndex; + private int mAddedCount; + private int mRemovedCount; + + private long mEventTime; + + private CharSequence mClassName; + private CharSequence mPackageName; + private CharSequence mContentDescription; + private CharSequence mBeforeText; + + private Parcelable mParcelableData; + + private final List<CharSequence> mText = new ArrayList<CharSequence>(); + + private boolean mIsInPool; + + /* + * Hide constructor from clients. + */ + private AccessibilityEvent() { + mCurrentItemIndex = INVALID_POSITION; + } + + /** + * Gets if the source is checked. + * + * @return True if the view is checked, false otherwise. + */ + public boolean isChecked() { + return getBooleanProperty(CHECKED); + } + + /** + * Sets if the source is checked. + * + * @param isChecked True if the view is checked, false otherwise. + */ + public void setChecked(boolean isChecked) { + setBooleanProperty(CHECKED, isChecked); + } + + /** + * Gets if the source is enabled. + * + * @return True if the view is enabled, false otherwise. + */ + public boolean isEnabled() { + return getBooleanProperty(ENABLED); + } + + /** + * Sets if the source is enabled. + * + * @param isEnabled True if the view is enabled, false otherwise. + */ + public void setEnabled(boolean isEnabled) { + setBooleanProperty(ENABLED, isEnabled); + } + + /** + * Gets if the source is a password field. + * + * @return True if the view is a password field, false otherwise. + */ + public boolean isPassword() { + return getBooleanProperty(PASSWORD); + } + + /** + * Sets if the source is a password field. + * + * @param isPassword True if the view is a password field, false otherwise. + */ + public void setPassword(boolean isPassword) { + setBooleanProperty(PASSWORD, isPassword); + } + + /** + * Sets if the source is taking the entire screen. + * + * @param isFullScreen True if the source is full screen, false otherwise. + */ + public void setFullScreen(boolean isFullScreen) { + setBooleanProperty(FULL_SCREEN, isFullScreen); + } + + /** + * Gets if the source is taking the entire screen. + * + * @return True if the source is full screen, false otherwise. + */ + public boolean isFullScreen() { + return getBooleanProperty(FULL_SCREEN); + } + + /** + * Gets the event type. + * + * @return The event type. + */ + public int getEventType() { + return mEventType; + } + + /** + * Sets the event type. + * + * @param eventType The event type. + */ + public void setEventType(int eventType) { + mEventType = eventType; + } + + /** + * Gets the number of items that can be visited. + * + * @return The number of items. + */ + public int getItemCount() { + return mItemCount; + } + + /** + * Sets the number of items that can be visited. + * + * @param itemCount The number of items. + */ + public void setItemCount(int itemCount) { + mItemCount = itemCount; + } + + /** + * Gets the index of the source in the list of items the can be visited. + * + * @return The current item index. + */ + public int getCurrentItemIndex() { + return mCurrentItemIndex; + } + + /** + * Sets the index of the source in the list of items that can be visited. + * + * @param currentItemIndex The current item index. + */ + public void setCurrentItemIndex(int currentItemIndex) { + mCurrentItemIndex = currentItemIndex; + } + + /** + * Gets the index of the first character of the changed sequence. + * + * @return The index of the first character. + */ + public int getFromIndex() { + return mFromIndex; + } + + /** + * Sets the index of the first character of the changed sequence. + * + * @param fromIndex The index of the first character. + */ + public void setFromIndex(int fromIndex) { + mFromIndex = fromIndex; + } + + /** + * Gets the number of added characters. + * + * @return The number of added characters. + */ + public int getAddedCount() { + return mAddedCount; + } + + /** + * Sets the number of added characters. + * + * @param addedCount The number of added characters. + */ + public void setAddedCount(int addedCount) { + mAddedCount = addedCount; + } + + /** + * Gets the number of removed characters. + * + * @return The number of removed characters. + */ + public int getRemovedCount() { + return mRemovedCount; + } + + /** + * Sets the number of removed characters. + * + * @param removedCount The number of removed characters. + */ + public void setRemovedCount(int removedCount) { + mRemovedCount = removedCount; + } + + /** + * Gets the time in which this event was sent. + * + * @return The event time. + */ + public long getEventTime() { + return mEventTime; + } + + /** + * Sets the time in which this event was sent. + * + * @param eventTime The event time. + */ + public void setEventTime(long eventTime) { + mEventTime = eventTime; + } + + /** + * Gets the class name of the source. + * + * @return The class name. + */ + public CharSequence getClassName() { + return mClassName; + } + + /** + * Sets the class name of the source. + * + * @param className The lass name. + */ + public void setClassName(CharSequence className) { + mClassName = className; + } + + /** + * Gets the package name of the source. + * + * @return The package name. + */ + public CharSequence getPackageName() { + return mPackageName; + } + + /** + * Sets the package name of the source. + * + * @param packageName The package name. + */ + public void setPackageName(CharSequence packageName) { + mPackageName = packageName; + } + + /** + * Gets the text of the event. The index in the list represents the priority + * of the text. Specifically, the lower the index the higher the priority. + * + * @return The text. + */ + public List<CharSequence> getText() { + return mText; + } + + /** + * Sets the text before a change. + * + * @return The text before the change. + */ + public CharSequence getBeforeText() { + return mBeforeText; + } + + /** + * Sets the text before a change. + * + * @param beforeText The text before the change. + */ + public void setBeforeText(CharSequence beforeText) { + mBeforeText = beforeText; + } + + /** + * Gets the description of the source. + * + * @return The description. + */ + public CharSequence getContentDescription() { + return mContentDescription; + } + + /** + * Sets the description of the source. + * + * @param contentDescription The description. + */ + public void setContentDescription(CharSequence contentDescription) { + mContentDescription = contentDescription; + } + + /** + * Gets the {@link Parcelable} data. + * + * @return The parcelable data. + */ + public Parcelable getParcelableData() { + return mParcelableData; + } + + /** + * Sets the {@link Parcelable} data of the event. + * + * @param parcelableData The parcelable data. + */ + public void setParcelableData(Parcelable parcelableData) { + mParcelableData = parcelableData; + } + + /** + * Returns a cached instance if such is available or a new one is + * instantiated with type property set. + * + * @param eventType The event type. + * @return An instance. + */ + public static AccessibilityEvent obtain(int eventType) { + AccessibilityEvent event = AccessibilityEvent.obtain(); + event.setEventType(eventType); + return event; + } + + /** + * Returns a cached instance if such is available or a new one is + * instantiated. + * + * @return An instance. + */ + public static AccessibilityEvent obtain() { + synchronized (mPoolLock) { + if (sPool != null) { + AccessibilityEvent event = sPool; + sPool = sPool.mNext; + sPoolSize--; + event.mNext = null; + event.mIsInPool = false; + return event; + } + return new AccessibilityEvent(); + } + } + + /** + * Return an instance back to be reused. + * <p> + * <b>Note: You must not touch the object after calling this function.</b> + */ + public void recycle() { + if (mIsInPool) { + return; + } + + clear(); + synchronized (mPoolLock) { + if (sPoolSize <= MAX_POOL_SIZE) { + mNext = sPool; + sPool = this; + mIsInPool = true; + sPoolSize++; + } + } + } + + /** + * Clears the state of this instance. + */ + private void clear() { + mEventType = 0; + mBooleanProperties = 0; + mCurrentItemIndex = INVALID_POSITION; + mItemCount = 0; + mFromIndex = 0; + mAddedCount = 0; + mRemovedCount = 0; + mEventTime = 0; + mClassName = null; + mPackageName = null; + mContentDescription = null; + mBeforeText = null; + mText.clear(); + } + + /** + * Gets the value of a boolean property. + * + * @param property The property. + * @return The value. + */ + private boolean getBooleanProperty(int property) { + return (mBooleanProperties & property) == property; + } + + /** + * Sets a boolean property. + * + * @param property The property. + * @param value The value. + */ + private void setBooleanProperty(int property, boolean value) { + if (value) { + mBooleanProperties |= property; + } else { + mBooleanProperties &= ~property; + } + } + + /** + * Creates a new instance from a {@link Parcel}. + * + * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. + */ + public void initFromParcel(Parcel parcel) { + mEventType = parcel.readInt(); + mBooleanProperties = parcel.readInt(); + mCurrentItemIndex = parcel.readInt(); + mItemCount = parcel.readInt(); + mFromIndex = parcel.readInt(); + mAddedCount = parcel.readInt(); + mRemovedCount = parcel.readInt(); + mEventTime = parcel.readLong(); + mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); + mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); + mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); + mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); + mParcelableData = parcel.readParcelable(null); + parcel.readList(mText, null); + } + + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mEventType); + parcel.writeInt(mBooleanProperties); + parcel.writeInt(mCurrentItemIndex); + parcel.writeInt(mItemCount); + parcel.writeInt(mFromIndex); + parcel.writeInt(mAddedCount); + parcel.writeInt(mRemovedCount); + parcel.writeLong(mEventTime); + TextUtils.writeToParcel(mClassName, parcel, 0); + TextUtils.writeToParcel(mPackageName, parcel, 0); + TextUtils.writeToParcel(mContentDescription, parcel, 0); + TextUtils.writeToParcel(mBeforeText, parcel, 0); + parcel.writeParcelable(mParcelableData, flags); + parcel.writeList(mText); + } + + public int describeContents() { + return 0; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(super.toString()); + builder.append("; EventType: " + mEventType); + builder.append("; EventTime: " + mEventTime); + builder.append("; ClassName: " + mClassName); + builder.append("; PackageName: " + mPackageName); + builder.append("; Text: " + mText); + builder.append("; ContentDescription: " + mContentDescription); + builder.append("; ItemCount: " + mItemCount); + builder.append("; CurrentItemIndex: " + mCurrentItemIndex); + builder.append("; IsEnabled: " + isEnabled()); + builder.append("; IsPassword: " + isPassword()); + builder.append("; IsChecked: " + isChecked()); + builder.append("; IsFullScreen: " + isFullScreen()); + builder.append("; BeforeText: " + mBeforeText); + builder.append("; FromIndex: " + mFromIndex); + builder.append("; AddedCount: " + mAddedCount); + builder.append("; RemovedCount: " + mRemovedCount); + builder.append("; ParcelableData: " + mParcelableData); + return builder.toString(); + } + + /** + * @see Parcelable.Creator + */ + public static final Parcelable.Creator<AccessibilityEvent> CREATOR = + new Parcelable.Creator<AccessibilityEvent>() { + public AccessibilityEvent createFromParcel(Parcel parcel) { + AccessibilityEvent event = AccessibilityEvent.obtain(); + event.initFromParcel(parcel); + return event; + } + + public AccessibilityEvent[] newArray(int size) { + return new AccessibilityEvent[size]; + } + }; +} diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java new file mode 100644 index 0000000..3d70959 --- /dev/null +++ b/core/java/android/view/accessibility/AccessibilityEventSource.java @@ -0,0 +1,52 @@ +/* + * 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.view.accessibility; + +/** + * This interface is implemented by classes source of {@link AccessibilityEvent}s. + */ +public interface AccessibilityEventSource { + + /** + * Handles the request for sending an {@link AccessibilityEvent} given + * the event type. The method must first check if accessibility is on + * via calling {@link AccessibilityManager#isEnabled()}, obtain + * an {@link AccessibilityEvent} from the event pool through calling + * {@link AccessibilityEvent#obtain(int)}, populate the event, and + * send it for dispatch via calling + * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)}. + * + * @see AccessibilityEvent + * @see AccessibilityManager + * + * @param eventType The event type. + */ + public void sendAccessibilityEvent(int eventType); + + /** + * Handles the request for sending an {@link AccessibilityEvent}. The + * method does not guarantee to check if accessibility is on before + * sending the event for dispatch. It is responsibility of the caller + * to do the check via calling {@link AccessibilityManager#isEnabled()}. + * + * @see AccessibilityEvent + * @see AccessibilityManager + * + * @param event The event. + */ + public void sendAccessibilityEventUnchecked(AccessibilityEvent event); +} diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java new file mode 100644 index 0000000..0186270 --- /dev/null +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility; + +import static android.util.Config.LOGV; + +import android.content.Context; +import android.content.pm.ServiceInfo; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.util.Log; + +import java.util.Collections; +import java.util.List; + +/** + * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. + * Such events are generated when something notable happens in the user interface, + * for example an {@link android.app.Activity} starts, the focus or selection of a + * {@link android.view.View} changes etc. Parties interested in handling accessibility + * events implement and register an accessibility service which extends + * {@link android.accessibilityservice.AccessibilityService}. + * + * @see AccessibilityEvent + * @see android.accessibilityservice.AccessibilityService + * @see android.content.Context#getSystemService + */ +public final class AccessibilityManager { + private static final String LOG_TAG = "AccessibilityManager"; + + static final Object sInstanceSync = new Object(); + + private static AccessibilityManager sInstance; + + private static final int DO_SET_ENABLED = 10; + + final IAccessibilityManager mService; + + final Handler mHandler; + + boolean mIsEnabled; + + final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { + public void setEnabled(boolean enabled) { + mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); + } + }; + + class MyHandler extends Handler { + + MyHandler(Looper mainLooper) { + super(mainLooper); + } + + @Override + public void handleMessage(Message message) { + switch (message.what) { + case DO_SET_ENABLED : + synchronized (mHandler) { + mIsEnabled = (message.arg1 == 1); + } + return; + default : + Log.w(LOG_TAG, "Unknown message type: " + message.what); + } + } + } + + /** + * Get an AccessibilityManager instance (create one if necessary). + * + * @hide + */ + public static AccessibilityManager getInstance(Context context) { + synchronized (sInstanceSync) { + if (sInstance == null) { + sInstance = new AccessibilityManager(context); + } + } + return sInstance; + } + + /** + * Create an instance. + * + * @param context A {@link Context}. + */ + private AccessibilityManager(Context context) { + mHandler = new MyHandler(context.getMainLooper()); + IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); + mService = IAccessibilityManager.Stub.asInterface(iBinder); + try { + mService.addClient(mClient); + } catch (RemoteException re) { + Log.e(LOG_TAG, "AccessibilityManagerService is dead", re); + } + } + + /** + * Returns if the {@link AccessibilityManager} is enabled. + * + * @return True if this {@link AccessibilityManager} is enabled, false otherwise. + */ + public boolean isEnabled() { + synchronized (mHandler) { + return mIsEnabled; + } + } + + /** + * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not + * enabled the call is a NOOP. + * + * @param event The {@link AccessibilityEvent}. + * + * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent} + * while accessibility is not enabled. + */ + public void sendAccessibilityEvent(AccessibilityEvent event) { + if (!mIsEnabled) { + throw new IllegalStateException("Accessibility off. Did you forget to check that?"); + } + boolean doRecycle = false; + try { + event.setEventTime(SystemClock.uptimeMillis()); + // it is possible that this manager is in the same process as the service but + // client using it is called through Binder from another process. Example: MMS + // app adds a SMS notification and the NotificationManagerService calls this method + long identityToken = Binder.clearCallingIdentity(); + doRecycle = mService.sendAccessibilityEvent(event); + Binder.restoreCallingIdentity(identityToken); + if (LOGV) { + Log.i(LOG_TAG, event + " sent"); + } + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error during sending " + event + " ", re); + } finally { + if (doRecycle) { + event.recycle(); + } + } + } + + /** + * Requests interruption of the accessibility feedback from all accessibility services. + */ + public void interrupt() { + if (!mIsEnabled) { + throw new IllegalStateException("Accessibility off. Did you forget to check that?"); + } + try { + mService.interrupt(); + if (LOGV) { + Log.i(LOG_TAG, "Requested interrupt from all services"); + } + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re); + } + } + + /** + * Returns the {@link ServiceInfo}s of the installed accessibility services. + * + * @return An unmodifiable list with {@link ServiceInfo}s. + */ + public List<ServiceInfo> getAccessibilityServiceList() { + List<ServiceInfo> services = null; + try { + services = mService.getAccessibilityServiceList(); + if (LOGV) { + Log.i(LOG_TAG, "Installed AccessibilityServices " + services); + } + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re); + } + return Collections.unmodifiableList(services); + } +} diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl new file mode 100644 index 0000000..32788be --- /dev/null +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -0,0 +1,39 @@ +/* //device/java/android/android/app/INotificationManager.aidl +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.view.accessibility; + +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.IAccessibilityManagerClient; +import android.content.pm.ServiceInfo; + +/** + * Interface implemented by the AccessibilityManagerService called by + * the AccessibilityMasngers. + * + * @hide + */ +interface IAccessibilityManager { + + void addClient(IAccessibilityManagerClient client); + + boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent); + + List<ServiceInfo> getAccessibilityServiceList(); + + void interrupt(); +} diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl new file mode 100644 index 0000000..1eb60fc --- /dev/null +++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl @@ -0,0 +1,29 @@ +/* + * 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.view.accessibility; + +/** + * Interface a client of the IAccessibilityManager implements to + * receive information about changes in the manager state. + * + * @hide + */ +oneway interface IAccessibilityManagerClient { + + void setEnabled(boolean enabled); + +} diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 11de3e2..7393737 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; } @@ -336,10 +340,19 @@ public class BaseInputConnection implements InputConnection { } /** - * The default implementation does nothing. + * The default implementation turns this into the enter key. */ public boolean performEditorAction(int actionCode) { - return false; + long eventTime = SystemClock.uptimeMillis(); + sendKeyEvent(new KeyEvent(eventTime, eventTime, + KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION)); + sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime, + KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION)); + return true; } /** @@ -488,12 +501,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/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index ba3f78c..dbd2682 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -143,6 +143,17 @@ class BrowserFrame extends Handler { } /** + * Load a url with "POST" method from the network into the main frame. + * @param url The url to load. + * @param data The data for POST request. + */ + public void postUrl(String url, byte[] data) { + mLoadInitFromJava = true; + nativePostUrl(url, data); + mLoadInitFromJava = false; + } + + /** * Load the content as if it was loaded by the provided base URL. The * failUrl is used as the history entry for the load data. If null or * an empty string is passed for the failUrl, then no history entry is @@ -752,6 +763,8 @@ class BrowserFrame extends Handler { */ private native void nativeLoadUrl(String url); + private native void nativePostUrl(String url, byte[] postData); + private native void nativeLoadData(String baseUrl, String data, String mimeType, String encoding, String failUrl); diff --git a/core/java/android/webkit/ByteArrayBuilder.java b/core/java/android/webkit/ByteArrayBuilder.java index 806b458..145411c 100644 --- a/core/java/android/webkit/ByteArrayBuilder.java +++ b/core/java/android/webkit/ByteArrayBuilder.java @@ -17,6 +17,7 @@ package android.webkit; import java.util.LinkedList; +import java.util.ListIterator; /** Utility class optimized for accumulating bytes, and then spitting them back out. It does not optimize for returning the result in a @@ -94,6 +95,20 @@ class ByteArrayBuilder { return mChunks.isEmpty(); } + public int size() { + return mChunks.size(); + } + + public int getByteSize() { + int total = 0; + ListIterator<Chunk> it = mChunks.listIterator(0); + while (it.hasNext()) { + Chunk c = it.next(); + total += c.mLength; + } + return total; + } + public synchronized void clear() { Chunk c = getFirstChunk(); while (c != null) { diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java index 6f1b160..66ab021 100644 --- a/core/java/android/webkit/FrameLoader.java +++ b/core/java/android/webkit/FrameLoader.java @@ -364,7 +364,7 @@ class FrameLoader { String cookie = CookieManager.getInstance().getCookie( mListener.getWebAddress()); if (cookie != null && cookie.length() > 0) { - mHeaders.put("cookie", cookie); + mHeaders.put("Cookie", cookie); } } } diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java index 2a84683..1dbd007 100644 --- a/core/java/android/webkit/JWebCoreJavaBridge.java +++ b/core/java/android/webkit/JWebCoreJavaBridge.java @@ -18,6 +18,7 @@ package android.webkit; import android.os.Handler; import android.os.Message; +import android.security.CertTool; import android.util.Log; final class JWebCoreJavaBridge extends Handler { @@ -186,6 +187,15 @@ final class JWebCoreJavaBridge extends Handler { mHasInstantTimer = false; } + private String[] getKeyStrengthList() { + return CertTool.getInstance().getSupportedKeyStrenghs(); + } + + private String getSignedPublicKey(int index, String challenge, String url) { + // generateKeyPair expects organizations which we don't have. Ignore url. + return CertTool.getInstance().generateKeyPair(index, challenge, null); + } + private native void nativeConstructor(); private native void nativeFinalize(); private native void sharedTimerFired(); diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index d583eb1..39360cd 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -25,16 +25,16 @@ import android.net.http.HttpAuthHeader; import android.net.http.RequestHandle; import android.net.http.SslCertificate; import android.net.http.SslError; -import android.net.http.SslCertificate; import android.os.Handler; import android.os.Message; +import android.security.CertTool; import android.util.Log; import android.webkit.CacheManager.CacheResult; +import android.widget.Toast; import com.android.internal.R; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -72,6 +72,8 @@ class LoadListener extends Handler implements EventHandler { private static final int HTTP_NOT_FOUND = 404; private static final int HTTP_PROXY_AUTH = 407; + private static final String CERT_MIMETYPE = "application/x-x509-ca-cert"; + private static int sNativeLoaderCount; private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder(8192); @@ -934,6 +936,12 @@ class LoadListener extends Handler implements EventHandler { // This commits the headers without checking the response status code. private void commitHeaders() { + if (mIsMainPageLoader && CERT_MIMETYPE.equals(mMimeType)) { + // In the case of downloading certificate, we will save it to the + // Keystore in commitLoad. Do not call webcore. + return; + } + // Commit the headers to WebCore int nativeResponse = createNativeResponse(); // The native code deletes the native response object. @@ -974,6 +982,30 @@ class LoadListener extends Handler implements EventHandler { private void commitLoad() { if (mCancelled) return; + if (mIsMainPageLoader && CERT_MIMETYPE.equals(mMimeType)) { + // In the case of downloading certificate, we will save it to the + // Keystore and stop the current loading so that it will not + // generate a new history page + byte[] cert = new byte[mDataBuilder.getByteSize()]; + int position = 0; + ByteArrayBuilder.Chunk c; + while (true) { + c = mDataBuilder.getFirstChunk(); + if (c == null) break; + + if (c.mLength != 0) { + System.arraycopy(c.mArray, 0, cert, position, c.mLength); + position += c.mLength; + } + mDataBuilder.releaseChunk(c); + } + CertTool.getInstance().addCertificate(cert, mContext); + Toast.makeText(mContext, R.string.certificateSaved, + Toast.LENGTH_SHORT).show(); + mBrowserFrame.stopLoading(); + return; + } + // Give the data to WebKit now PerfChecker checker = new PerfChecker(); ByteArrayBuilder.Chunk c; diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java index 9de97c9..99de56d 100644 --- a/core/java/android/webkit/TextDialog.java +++ b/core/java/android/webkit/TextDialog.java @@ -538,7 +538,8 @@ import java.util.ArrayList; * removing the password input type. */ public void setSingleLine(boolean single) { - int inputType = EditorInfo.TYPE_CLASS_TEXT; + int inputType = EditorInfo.TYPE_CLASS_TEXT + | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT; if (!single) { inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 105eacd..ec671d5 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -69,7 +69,24 @@ public class WebSettings { } int value; } - + + /** + * Enum for specifying the WebView's desired density. + * FAR makes 100% looking like in 240dpi + * MEDIUM makes 100% looking like in 160dpi + * CLOSE makes 100% looking like in 120dpi + * @hide Pending API council approval + */ + public enum ZoomDensity { + FAR(150), // 240dpi + MEDIUM(100), // 160dpi + CLOSE(75); // 120dpi + ZoomDensity(int size) { + value = size; + } + int value; + } + /** * Default cache usage pattern Use with {@link #setCacheMode}. */ @@ -105,6 +122,8 @@ public class WebSettings { LOW } + // WebView associated with this WebSettings. + private WebView mWebView; // BrowserFrame used to access the native frame pointer. private BrowserFrame mBrowserFrame; // Flag to prevent multiple SYNC messages at one time. @@ -123,7 +142,7 @@ public class WebSettings { private String mSerifFontFamily = "serif"; private String mCursiveFontFamily = "cursive"; private String mFantasyFontFamily = "fantasy"; - private String mDefaultTextEncoding = "Latin-1"; + private String mDefaultTextEncoding; private String mUserAgent; private boolean mUseDefaultUserAgent; private String mAcceptLanguage; @@ -145,6 +164,7 @@ public class WebSettings { // Don't need to synchronize the get/set methods as they // are basic types, also none of these values are used in // native WebCore code. + private ZoomDensity mDefaultZoom = ZoomDensity.MEDIUM; private RenderPriority mRenderPriority = RenderPriority.NORMAL; private int mOverrideCacheMode = LOAD_DEFAULT; private boolean mSaveFormData = true; @@ -237,9 +257,12 @@ public class WebSettings { * Package constructor to prevent clients from creating a new settings * instance. */ - WebSettings(Context context) { + WebSettings(Context context, WebView webview) { mEventHandler = new EventHandler(); mContext = context; + mWebView = webview; + mDefaultTextEncoding = context.getString(com.android.internal. + R.string.default_text_encoding); if (sLockForLocaleSettings == null) { sLockForLocaleSettings = new Object(); @@ -445,6 +468,31 @@ public class WebSettings { } /** + * Set the default zoom density of the page. This should be called from UI + * thread. + * @param zoom A ZoomDensity value + * @see WebSettings.ZoomDensity + * @hide Pending API council approval + */ + public void setDefaultZoom(ZoomDensity zoom) { + if (mDefaultZoom != zoom) { + mDefaultZoom = zoom; + mWebView.updateDefaultZoomDensity(zoom.value); + } + } + + /** + * Get the default zoom density of the page. This should be called from UI + * thread. + * @return A ZoomDensity value + * @see WebSettings.ZoomDensity + * @hide Pending API council approval + */ + public ZoomDensity getDefaultZoom() { + return mDefaultZoom; + } + + /** * Enables using light touches to make a selection and activate mouseovers. */ public void setLightTouchEnabled(boolean enabled) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 563d819..fcf946f 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -237,6 +237,7 @@ public class WebView extends AbsoluteLayout * Helper class to get velocity for fling */ VelocityTracker mVelocityTracker; + private int mMaximumFling; /** * Touch mode @@ -395,22 +396,27 @@ public class WebView extends AbsoluteLayout // width which view is considered to be fully zoomed out static final int ZOOM_OUT_WIDTH = 1008; - private static final float DEFAULT_MAX_ZOOM_SCALE = 4.0f; - private static final float DEFAULT_MIN_ZOOM_SCALE = 0.25f; + // default scale limit. Depending on the display density + private static float DEFAULT_MAX_ZOOM_SCALE; + private static float DEFAULT_MIN_ZOOM_SCALE; // scale limit, which can be set through viewport meta tag in the web page - private float mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE; - private float mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE; + private float mMaxZoomScale; + private float mMinZoomScale; private boolean mMinZoomScaleFixed = false; // initial scale in percent. 0 means using default. private int mInitialScale = 0; + // default scale. Depending on the display density. + static int DEFAULT_SCALE_PERCENT; + private float mDefaultScale; + // set to true temporarily while the zoom control is being dragged private boolean mPreviewZoomOnly = false; // computed scale and inverse, from mZoomWidth. - private float mActualScale = 1; - private float mInvActualScale = 1; + private float mActualScale; + private float mInvActualScale; // if this is non-zero, it is used on drawing rather than mActualScale private float mZoomScale; private float mInvInitialZoomScale; @@ -635,7 +641,7 @@ public class WebView extends AbsoluteLayout mZoomFitPageButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { - zoomWithPreview(1f); + zoomWithPreview(mDefaultScale); updateZoomButtonsEnabled(); } }); @@ -658,7 +664,7 @@ public class WebView extends AbsoluteLayout // or out. mZoomButtonsController.setZoomInEnabled(canZoomIn); mZoomButtonsController.setZoomOutEnabled(canZoomOut); - mZoomFitPageButton.setEnabled(mActualScale != 1); + mZoomFitPageButton.setEnabled(mActualScale != mDefaultScale); } mZoomOverviewButton.setVisibility(canZoomScrollOut() ? View.VISIBLE: View.GONE); @@ -671,13 +677,41 @@ public class WebView extends AbsoluteLayout setClickable(true); setLongClickable(true); - final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + final ViewConfiguration configuration = ViewConfiguration.get(getContext()); + final int slop = configuration.getScaledTouchSlop(); mTouchSlopSquare = slop * slop; mMinLockSnapReverseDistance = slop; + final float density = getContext().getResources().getDisplayMetrics().density; // use one line height, 16 based on our current default font, for how // far we allow a touch be away from the edge of a link - mNavSlop = (int) (16 * getContext().getResources() - .getDisplayMetrics().density); + mNavSlop = (int) (16 * density); + // density adjusted scale factors + DEFAULT_SCALE_PERCENT = (int) (100 * density); + mDefaultScale = density; + mActualScale = density; + mInvActualScale = 1 / density; + DEFAULT_MAX_ZOOM_SCALE = 4.0f * density; + DEFAULT_MIN_ZOOM_SCALE = 0.25f * density; + mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE; + mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE; + mMaximumFling = configuration.getScaledMaximumFlingVelocity(); + } + + /* package */void updateDefaultZoomDensity(int zoomDensity) { + final float density = getContext().getResources().getDisplayMetrics().density + * 100 / zoomDensity; + if (Math.abs(density - mDefaultScale) > 0.01) { + float scaleFactor = density / mDefaultScale; + // adjust the limits + mNavSlop = (int) (16 * density); + DEFAULT_SCALE_PERCENT = (int) (100 * density); + DEFAULT_MAX_ZOOM_SCALE = 4.0f * density; + DEFAULT_MIN_ZOOM_SCALE = 0.25f * density; + mDefaultScale = density; + mMaxZoomScale *= scaleFactor; + mMinZoomScale *= scaleFactor; + setNewZoomScale(mActualScale * scaleFactor, false); + } } /* package */ boolean onSavePassword(String schemePlusHost, String username, @@ -1118,6 +1152,29 @@ public class WebView extends AbsoluteLayout } /** + * Load the url with postData using "POST" method into the WebView. If url + * is not a network url, it will be loaded with {link + * {@link #loadUrl(String)} instead. + * + * @param url The url of the resource to load. + * @param postData The data will be passed to "POST" request. + * + * @hide pending API solidification + */ + public void postUrl(String url, byte[] postData) { + if (URLUtil.isNetworkUrl(url)) { + switchOutDrawHistory(); + HashMap arg = new HashMap(); + arg.put("url", url); + arg.put("data", postData); + mWebViewCore.sendMessage(EventHub.POST_URL, arg); + clearTextEntry(); + } else { + loadUrl(url); + } + } + + /** * Load the given data into the WebView. This will load the data into * WebView using the data: scheme. Content loaded through this mechanism * does not have the ability to load content from the network. @@ -4103,7 +4160,7 @@ public class WebView extends AbsoluteLayout int maxX = Math.max(computeHorizontalScrollRange() - getViewWidth(), 0); int maxY = Math.max(computeVerticalScrollRange() - getViewHeight(), 0); - mVelocityTracker.computeCurrentVelocity(1000); + mVelocityTracker.computeCurrentVelocity(1000, mMaximumFling); int vx = (int) mVelocityTracker.getXVelocity(); int vy = (int) mVelocityTracker.getYVelocity(); @@ -4134,9 +4191,9 @@ public class WebView extends AbsoluteLayout private boolean zoomWithPreview(float scale) { float oldScale = mActualScale; - // snap to 100% if it is close - if (scale > 0.95f && scale < 1.05f) { - scale = 1.0f; + // snap to DEFAULT_SCALE if it is close + if (scale > (mDefaultScale - 0.05) && scale < (mDefaultScale + 0.05)) { + scale = mDefaultScale; } setNewZoomScale(scale, false); @@ -4517,9 +4574,11 @@ public class WebView extends AbsoluteLayout break; } case SWITCH_TO_LONGPRESS: { - mTouchMode = TOUCH_DONE_MODE; - performLongClick(); - updateTextEntry(); + if (!mPreventDrag) { + mTouchMode = TOUCH_DONE_MODE; + performLongClick(); + updateTextEntry(); + } break; } case SWITCH_TO_ENTER: @@ -4651,8 +4710,8 @@ public class WebView extends AbsoluteLayout } int initialScale = msg.arg1; int viewportWidth = msg.arg2; - // by default starting a new page with 100% zoom scale. - float scale = 1.0f; + // start a new page with DEFAULT_SCALE zoom scale. + float scale = mDefaultScale; if (mInitialScale > 0) { scale = mInitialScale / 100.0f; } else { diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index e9df453..a5fa41e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -97,7 +97,7 @@ final class WebViewCore { private boolean mViewportUserScalable = true; - private int mRestoredScale = 100; + private int mRestoredScale = WebView.DEFAULT_SCALE_PERCENT; private int mRestoredX = 0; private int mRestoredY = 0; @@ -139,7 +139,7 @@ final class WebViewCore { // ready. mEventHub = new EventHub(); // Create a WebSettings object for maintaining all settings - mSettings = new WebSettings(mContext); + mSettings = new WebSettings(mContext, mWebView); // The WebIconDatabase needs to be initialized within the UI thread so // just request the instance here. WebIconDatabase.getInstance(); @@ -544,6 +544,8 @@ final class WebViewCore { "WEBKIT_DRAW", // = 130; "SYNC_SCROLL", // = 131; "REFRESH_PLUGINS", // = 132; + // this will replace REFRESH_PLUGINS in the next release + "POST_URL", // = 142; "SPLIT_PICTURE_SET", // = 133; "CLEAR_CONTENT", // = 134; "SET_FINAL_FOCUS", // = 135; @@ -589,6 +591,8 @@ final class WebViewCore { static final int WEBKIT_DRAW = 130; static final int SYNC_SCROLL = 131; static final int REFRESH_PLUGINS = 132; + // this will replace REFRESH_PLUGINS in the next release + static final int POST_URL = 142; static final int SPLIT_PICTURE_SET = 133; static final int CLEAR_CONTENT = 134; @@ -672,6 +676,13 @@ final class WebViewCore { loadUrl((String) msg.obj); break; + case POST_URL: { + HashMap param = (HashMap) msg.obj; + String url = (String) param.get("url"); + byte[] data = (byte[]) param.get("data"); + mBrowserFrame.postUrl(url, data); + break; + } case LOAD_DATA: HashMap loadParams = (HashMap) msg.obj; String baseUrl = (String) loadParams.get("baseUrl"); @@ -1549,19 +1560,33 @@ final class WebViewCore { // set the viewport settings from WebKit setViewportSettingsFromNative(); + // adjust the default scale to match the density + if (WebView.DEFAULT_SCALE_PERCENT != 100) { + float adjust = (float) WebView.DEFAULT_SCALE_PERCENT / 100.0f; + if (mViewportInitialScale > 0) { + mViewportInitialScale *= adjust; + } + if (mViewportMinimumScale > 0) { + mViewportMinimumScale *= adjust; + } + if (mViewportMaximumScale > 0) { + mViewportMaximumScale *= adjust; + } + } + // infer the values if they are not defined. if (mViewportWidth == 0) { if (mViewportInitialScale == 0) { - mViewportInitialScale = 100; + mViewportInitialScale = WebView.DEFAULT_SCALE_PERCENT; } if (mViewportMinimumScale == 0) { - mViewportMinimumScale = 100; + mViewportMinimumScale = WebView.DEFAULT_SCALE_PERCENT; } } if (mViewportUserScalable == false) { - mViewportInitialScale = 100; - mViewportMinimumScale = 100; - mViewportMaximumScale = 100; + mViewportInitialScale = WebView.DEFAULT_SCALE_PERCENT; + mViewportMinimumScale = WebView.DEFAULT_SCALE_PERCENT; + mViewportMaximumScale = WebView.DEFAULT_SCALE_PERCENT; } if (mViewportMinimumScale > mViewportInitialScale) { if (mViewportInitialScale == 0) { @@ -1575,9 +1600,10 @@ final class WebViewCore { mViewportMaximumScale = mViewportInitialScale; } else if (mViewportInitialScale == 0) { mViewportInitialScale = mViewportMaximumScale; - } + } } - if (mViewportWidth < 0 && mViewportInitialScale == 100) { + if (mViewportWidth < 0 + && mViewportInitialScale == WebView.DEFAULT_SCALE_PERCENT) { mViewportWidth = 0; } diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java index 2d431a8..1384042 100644 --- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java +++ b/core/java/android/webkit/gears/AndroidRadioDataProvider.java @@ -28,6 +28,7 @@ package android.webkit.gears; import android.content.Context; import android.telephony.CellLocation; import android.telephony.ServiceState; +import android.telephony.SignalStrength; import android.telephony.gsm.GsmCellLocation; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; @@ -54,6 +55,7 @@ public final class AndroidRadioDataProvider extends PhoneStateListener { public static final class RadioData { public int cellId = -1; public int locationAreaCode = -1; + // TODO: use new SignalStrength instead of asu public int signalStrength = -1; public int mobileCountryCode = -1; public int mobileNetworkCode = -1; @@ -179,6 +181,7 @@ public final class AndroidRadioDataProvider extends PhoneStateListener { private CellLocation cellLocation = null; /** The last known signal strength */ + // TODO: use new SignalStrength instead of asu private int signalStrength = -1; /** The last known serviceState */ @@ -207,7 +210,7 @@ public final class AndroidRadioDataProvider extends PhoneStateListener { // Register for cell id, signal strength and service state changed // notifications. telephonyManager.listen(this, PhoneStateListener.LISTEN_CELL_LOCATION - | PhoneStateListener.LISTEN_SIGNAL_STRENGTH + | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_SERVICE_STATE); } @@ -226,8 +229,9 @@ public final class AndroidRadioDataProvider extends PhoneStateListener { } @Override - public void onSignalStrengthChanged(int asu) { - signalStrength = asu; + public void onSignalStrengthsChanged(SignalStrength ss) { + int gsmSignalStrength = ss.getGsmSignalStrength(); + signalStrength = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength); notifyListeners(); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 1ca59b2..f9ca8cb 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -54,7 +54,9 @@ import java.util.ArrayList; import java.util.List; /** - * Common code shared between ListView and GridView + * Base class that can be used to implement virtualized lists of items. A list does + * not have a spatial definition here. For instance, subclases of this class can + * display the content of the list in a grid, in a carousel, as stack, etc. * * @attr ref android.R.styleable#AbsListView_listSelector * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop @@ -86,7 +88,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public static final int TRANSCRIPT_MODE_NORMAL = 1; /** * The list will automatically scroll to the bottom, no matter what items - * are currently visible. + * are currently visible. * * @see #setTranscriptMode(int) */ @@ -123,7 +125,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * Indicates the view is in the process of being flung */ static final int TOUCH_MODE_FLING = 4; - + /** * Indicates that the user is currently dragging the fast scroll thumb */ @@ -316,7 +318,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * bitmap cache after scrolling. */ boolean mScrollingCacheEnabled; - + /** * Whether or not to enable the fast scroll feature on this list */ @@ -389,7 +391,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * The last CheckForTap runnable we posted, if any */ private Runnable mPendingCheckForTap; - + /** * The last CheckForKeyLongPress runnable we posted, if any */ @@ -427,14 +429,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private FastScroller mFastScroller; - private int mTouchSlop; + private boolean mGlobalLayoutListenerAddedFilter; + private int mTouchSlop; private float mDensityScale; private InputConnection mDefInputConnection; private InputConnectionWrapper mPublicInputConnection; private Runnable mClearScrollingCache; + private int mMinimumVelocity; + private int mMaximumVelocity; /** * Interface definition for a callback to be invoked when the list or grid @@ -529,21 +534,35 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te int color = a.getColor(R.styleable.AbsListView_cacheColorHint, 0); setCacheColorHint(color); - + boolean enableFastScroll = a.getBoolean(R.styleable.AbsListView_fastScrollEnabled, false); setFastScrollEnabled(enableFastScroll); boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true); setSmoothScrollbarEnabled(smoothScrollbar); - + a.recycle(); } + private void initAbsListView() { + // Setting focusable in touch mode will set the focusable property to true + setFocusableInTouchMode(true); + setWillNotDraw(false); + setAlwaysDrawnWithCacheEnabled(false); + setScrollingCacheEnabled(true); + + final ViewConfiguration configuration = ViewConfiguration.get(mContext); + mTouchSlop = configuration.getScaledTouchSlop(); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mDensityScale = getContext().getResources().getDisplayMetrics().density; + } + /** - * Enables fast scrolling by letting the user quickly scroll through lists by - * dragging the fast scroll thumb. The adapter attached to the list may want + * Enables fast scrolling by letting the user quickly scroll through lists by + * dragging the fast scroll thumb. The adapter attached to the list may want * to implement {@link SectionIndexer} if it wishes to display alphabet preview and - * jump between sections of the list. + * jump between sections of the list. * @see SectionIndexer * @see #isFastScrollEnabled() * @param enabled whether or not to enable fast scrolling @@ -561,7 +580,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } - + /** * Returns the current state of the fast scroll feature. * @see #setFastScrollEnabled(boolean) @@ -571,10 +590,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public boolean isFastScrollEnabled() { return mFastScrollEnabled; } - + /** * If fast scroll is visible, then don't draw the vertical scrollbar. - * @hide + * @hide */ @Override protected boolean isVerticalScrollBarHidden() { @@ -592,11 +611,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * When smooth scrollbar is disabled, the position and size of the scrollbar thumb * is based solely on the number of items in the adapter and the position of the * visible items inside the adapter. This provides a stable scrollbar as the user - * navigates through a list of items with varying heights. + * navigates through a list of items with varying heights. * * @param enabled Whether or not to enable smooth scrollbar. * - * @see #setSmoothScrollbarEnabled(boolean) + * @see #setSmoothScrollbarEnabled(boolean) * @attr ref android.R.styleable#AbsListView_smoothScrollbar */ public void setSmoothScrollbarEnabled(boolean enabled) { @@ -712,17 +731,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } - private void initAbsListView() { - // Setting focusable in touch mode will set the focusable property to true - setFocusableInTouchMode(true); - setWillNotDraw(false); - setAlwaysDrawnWithCacheEnabled(false); - setScrollingCacheEnabled(true); - - mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); - mDensityScale = getContext().getResources().getDisplayMetrics().density; - } - private void useDefaultSelector() { setSelector(getResources().getDrawable( com.android.internal.R.drawable.list_selector_background)); @@ -828,7 +836,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public Parcelable onSaveInstanceState() { /* * This doesn't really make sense as the place to dismiss the - * popup, but there don't seem to be any other useful hooks + * popups, but there don't seem to be any other useful hooks * that happen early enough to keep from getting complaints * about having leaked the window. */ @@ -908,17 +916,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private boolean acceptFilter() { - if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) || - ((Filterable) getAdapter()).getFilter() == null) { - return false; - } - return true; + return mTextFilterEnabled && getAdapter() instanceof Filterable && + ((Filterable) getAdapter()).getFilter() != null; } /** * Sets the initial value for the text filter. * @param filterText The text to use for the filter. - * + * * @see #setTextFilterEnabled */ public void setFilterText(String filterText) { @@ -944,7 +949,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** - * Returns the list's text filter, if available. + * Returns the list's text filter, if available. * @return the list's text filter or null if filtering isn't enabled */ public CharSequence getTextFilter() { @@ -953,7 +958,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } return null; } - + @Override protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); @@ -1096,6 +1101,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te listPadding.bottom = mSelectionBottomPadding + mPaddingBottom; } + /** + * Subclasses should NOT override this method but + * {@link #layoutChildren()} instead. + */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); @@ -1111,17 +1120,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te protected boolean setFrame(int left, int top, int right, int bottom) { final boolean changed = super.setFrame(left, top, right, bottom); - // Reposition the popup when the frame has changed. This includes - // translating the widget, not just changing its dimension. The - // filter popup needs to follow the widget. - if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null && - mPopup.isShowing()) { - positionPopup(); + if (changed) { + // Reposition the popup when the frame has changed. This includes + // translating the widget, not just changing its dimension. The + // filter popup needs to follow the widget. + final boolean visible = getWindowVisibility() == View.VISIBLE; + if (mFiltered && visible && mPopup != null && mPopup.isShowing()) { + positionPopup(); + } } return changed; } + /** + * Subclasses must override this method to layout their children. + */ protected void layoutChildren() { } @@ -1324,6 +1338,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mDataChanged = true; rememberSyncState(); } + if (mFastScroller != null) { mFastScroller.onSizeChanged(w, h, oldw, oldh); } @@ -1494,7 +1509,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te System.arraycopy(state, enabledPos + 1, state, enabledPos, state.length - enabledPos - 1); } - + return state; } @@ -1510,6 +1525,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ViewTreeObserver treeObserver = getViewTreeObserver(); if (treeObserver != null) { treeObserver.addOnTouchModeChangeListener(this); + if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) { + treeObserver.addOnGlobalLayoutListener(this); + } } } @@ -1520,6 +1538,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ViewTreeObserver treeObserver = getViewTreeObserver(); if (treeObserver != null) { treeObserver.removeOnTouchModeChangeListener(this); + if (mTextFilterEnabled && mPopup != null) { + treeObserver.removeGlobalOnLayoutListener(this); + mGlobalLayoutListenerAddedFilter = false; + } } } @@ -1586,16 +1608,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private class WindowRunnnable { private int mOriginalAttachCount; - + public void rememberWindowAttachCount() { mOriginalAttachCount = getWindowAttachCount(); } - + public boolean sameWindow() { return hasWindowFocus() && getWindowAttachCount() == mOriginalAttachCount; } } - + private class PerformClick extends WindowRunnnable implements Runnable { View mChild; int mClickMotionPosition; @@ -1622,7 +1644,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final long longPressId = mAdapter.getItemId(mMotionPosition); boolean handled = false; - if (sameWindow() && !mDataChanged) { + if (sameWindow() && !mDataChanged) { handled = performLongPress(child, longPressPosition, longPressId); } if (handled) { @@ -1636,7 +1658,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } - + private class CheckForKeyLongPress extends WindowRunnnable implements Runnable { public void run() { if (isPressed() && mSelectedPosition >= 0) { @@ -1812,7 +1834,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTouchMode = TOUCH_MODE_DONE_WAITING; } } else { - mTouchMode = TOUCH_MODE_DONE_WAITING; + mTouchMode = TOUCH_MODE_DONE_WAITING; } } } @@ -1867,13 +1889,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @Override public boolean onTouchEvent(MotionEvent ev) { - if (mFastScroller != null) { boolean intercepted = mFastScroller.onTouchEvent(ev); if (intercepted) { return true; - } + } } + final int action = ev.getAction(); final int x = (int) ev.getX(); final int y = (int) ev.getY(); @@ -2041,12 +2063,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te break; case TOUCH_MODE_SCROLL: final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); - int initialVelocity = (int)velocityTracker.getYVelocity(); - - if ((Math.abs(initialVelocity) > - ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) && - (getChildCount() > 0)) { + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + final int initialVelocity = (int) velocityTracker.getYVelocity(); + if (Math.abs(initialVelocity) > mMinimumVelocity && (getChildCount() > 0)) { if (mFlingRunnable == null) { mFlingRunnable = new FlingRunnable(); } @@ -2059,10 +2078,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } setPressed(false); - + // Need to redraw since we probably aren't drawing the selector anymore invalidate(); - + final Handler handler = getHandler(); if (handler != null) { handler.removeCallbacks(mPendingCheckForLongPress); @@ -2106,7 +2125,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return true; } - + @Override public void draw(Canvas canvas) { super.draw(canvas); @@ -2121,14 +2140,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te int x = (int) ev.getX(); int y = (int) ev.getY(); View v; - + if (mFastScroller != null) { boolean intercepted = mFastScroller.onInterceptTouchEvent(ev); if (intercepted) { return true; } } - + switch (action) { case MotionEvent.ACTION_DOWN: { int motionPosition = findMotionRow(y); @@ -2775,7 +2794,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te /** * Removes the filter window */ - void dismissPopup() { + private void dismissPopup() { if (mPopup != null) { mPopup.dismiss(); } @@ -2978,7 +2997,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } return null; } - + /** * For filtering we proxy an input connection to an internal text editor, * and this allows the proxying to happen. @@ -2987,7 +3006,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public boolean checkInputConnectionProxy(View view) { return view == mTextFilter; } - + /** * Creates the window for the text filter and populates it with an EditText field; * @@ -3017,6 +3036,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te p.setBackgroundDrawable(null); mPopup = p; getViewTreeObserver().addOnGlobalLayoutListener(this); + mGlobalLayoutListenerAddedFilter = true; } if (animateEntrance) { mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilter); @@ -3379,7 +3399,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mCurrentScrap = scrapViews[0]; mScrapViews = scrapViews; } - + public boolean shouldRecycleViewType(int viewType) { return viewType >= 0; } diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index 173e80f..7d2fcbc 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -24,11 +24,12 @@ import android.os.SystemClock; import android.util.AttributeSet; import android.util.SparseArray; import android.view.ContextMenu; +import android.view.SoundEffectConstants; import android.view.View; -import android.view.ViewGroup; import android.view.ViewDebug; -import android.view.SoundEffectConstants; +import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; +import android.view.accessibility.AccessibilityEvent; /** @@ -618,7 +619,9 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { } /** - * Sets the currently selected item + * Sets the currently selected item. To support accessibility subclasses that + * override this method must invoke the overriden super method first. + * * @param position Index (starting at 0) of the data item to be selected. */ public abstract void setSelection(int position); @@ -844,6 +847,11 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { fireOnSelected(); } } + + // we fire selection events here not in View + if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } } private void fireOnSelected() { @@ -861,6 +869,35 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { } @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean populated = false; + // This is an exceptional case which occurs when a window gets the + // focus and sends a focus event via its focused child to announce + // current focus/selection. AdapterView fires selection but not focus + // events so we change the event type here. + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) { + event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + + // we send selection events only from AdapterView to avoid + // generation of such event for each child + View selectedView = getSelectedView(); + if (selectedView != null) { + populated = selectedView.dispatchPopulateAccessibilityEvent(event); + } + + if (!populated) { + if (selectedView != null) { + event.setEnabled(selectedView.isEnabled()); + } + event.setItemCount(getCount()); + event.setCurrentItemIndex(getSelectedItemPosition()); + } + + return populated; + } + + @Override protected boolean canAnimate() { return super.canAnimate() && mItemCount > 0; } diff --git a/core/java/android/widget/AlphabetIndexer.java b/core/java/android/widget/AlphabetIndexer.java index 4e466a0..f50676a 100644 --- a/core/java/android/widget/AlphabetIndexer.java +++ b/core/java/android/widget/AlphabetIndexer.java @@ -248,8 +248,8 @@ public class AlphabetIndexer extends DataSetObserver implements SectionIndexer { public int getSectionForPosition(int position) { int savedCursorPos = mDataCursor.getPosition(); mDataCursor.moveToPosition(position); - mDataCursor.moveToPosition(savedCursorPos); String curName = mDataCursor.getString(mColumnIndex); + mDataCursor.moveToPosition(savedCursorPos); // Linear search, as there are only a few items in the section index // Could speed this up later if it actually gets used. for (int i = 0; i < mAlphabetLength; i++) { diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index 5fa00e7..c4b5ef8 100755 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -124,25 +124,25 @@ public class AppSecurityPermissions implements View.OnClickListener { if(pkg == null) { return; } - // Extract shared user permissions if any + // Get requested permissions + if (pkg.requestedPermissions != null) { + ArrayList<String> strList = pkg.requestedPermissions; + int size = strList.size(); + if (size > 0) { + extractPerms(strList.toArray(new String[size]), permSet); + } + } + // Get permissions related to shared user if any if(pkg.mSharedUserId != null) { int sharedUid; try { sharedUid = mPm.getUidForSharedUser(pkg.mSharedUserId); + getAllUsedPermissions(sharedUid, permSet); } catch (NameNotFoundException e) { Log.w(TAG, "Could'nt retrieve shared user id for:"+pkg.packageName); - return; } - getAllUsedPermissions(sharedUid, permSet); - } else { - ArrayList<String> strList = pkg.requestedPermissions; - int size; - if((strList == null) || ((size = strList.size()) == 0)) { - return; - } - // Extract permissions defined in current package - extractPerms(strList.toArray(new String[size]), permSet); } + // Retrieve list of permissions for(PermissionInfo tmpInfo : permSet) { mPermsList.add(tmpInfo); } @@ -176,14 +176,9 @@ public class AppSecurityPermissions implements View.OnClickListener { Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName); return; } - if(pkgInfo == null) { - return; - } - String strList[] = pkgInfo.requestedPermissions; - if(strList == null) { - return; + if ((pkgInfo != null) && (pkgInfo.requestedPermissions != null)) { + extractPerms(pkgInfo.requestedPermissions, permSet); } - extractPerms(strList, permSet); } private void extractPerms(String strList[], Set<PermissionInfo> permSet) { diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java index c28210d..32e5504 100644 --- a/core/java/android/widget/ArrayAdapter.java +++ b/core/java/android/widget/ArrayAdapter.java @@ -348,7 +348,12 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { "ArrayAdapter requires the resource ID to be a TextView", e); } - text.setText(getItem(position).toString()); + T item = getItem(position); + if (item instanceof CharSequence) { + text.setText((CharSequence)item); + } else { + text.setText(item.toString()); + } return view; } diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index a1d16ea..675aba2 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; @@ -122,10 +124,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe private boolean mBlockCompletion; private AutoCompleteTextView.ListSelectorHider mHideSelector; - - // Indicates whether this AutoCompleteTextView is attached to a window or not - // The widget is attached to a window when mAttachCount > 0 - private int mAttachCount; + private Runnable mShowDropDownRunnable; private AutoCompleteTextView.PassThroughClickListener mPassThroughClickListener; @@ -170,6 +169,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); @@ -258,6 +259,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> @@ -589,7 +618,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; } @@ -637,15 +666,19 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownList.getAdapter().getCount() - 1)) { // When the selection is at the top, we block the key // event to prevent focus from moving. - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); + clearListSelection(); mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - mPopup.update(); + showDropDown(); return true; + } else { + // WARNING: Please read the comment where mListSelectionHidden + // is declared + mDropDownList.mListSelectionHidden = false; } + consumed = mDropDownList.onKeyDown(keyCode, event); - if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" - + consumed); + if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed); + if (consumed) { // If it handled the key event, then the user is // navigating in the list, so we should put it in front. @@ -655,7 +688,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 @@ -755,7 +788,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); } @@ -788,9 +821,12 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * it back. */ public void clearListSelection() { - if (mDropDownList != null) { - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); + final DropDownListView list = mDropDownList; + if (list != null) { + // WARNING: Please read the comment where mListSelectionHidden is declared + list.mListSelectionHidden = true; + list.hideSelector(); + list.requestLayout(); } } @@ -801,6 +837,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe */ public void setListSelection(int position) { if (mPopup.isShowing() && (mDropDownList != null)) { + mDropDownList.mListSelectionHidden = false; mDropDownList.setSelection(position); // ListView.setSelection() will call requestLayout() } @@ -893,7 +930,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } } - if (mDropDownDismissedOnCompletion) { + if (mDropDownDismissedOnCompletion && !mDropDownAlwaysVisible) { dismissDropDown(); } } @@ -950,6 +987,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * @param text the selected suggestion in the drop down list */ protected void replaceText(CharSequence text) { + clearComposingText(); + setText(text); // make sure we keep the caret at the end of the text view Editable spannable = getText(); @@ -958,7 +997,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** {@inheritDoc} */ public void onFilterComplete(int count) { - if (mAttachCount <= 0) return; + // Not attached to window, don't update drop-down + if (getWindowVisibility() == View.GONE) return; /* * This checks enoughToFilter() again because filtering requests @@ -971,7 +1011,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe if (hasFocus() && hasWindowFocus()) { showDropDown(); } - } else { + } else if (!mDropDownAlwaysVisible) { dismissDropDown(); } } @@ -980,7 +1020,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); performValidation(); - if (!hasWindowFocus) { + if (!hasWindowFocus && !mDropDownAlwaysVisible) { dismissDropDown(); } } @@ -989,7 +1029,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(); } } @@ -997,13 +1037,11 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - mAttachCount++; } @Override protected void onDetachedFromWindow() { dismissDropDown(); - mAttachCount--; super.onDetachedFromWindow(); } @@ -1044,12 +1082,26 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } /** + * Issues a runnable to show the dropdown as soon as possible. + * + * @hide internal used only by Search Dialog + */ + public void showDropDownAfterLayout() { + post(mShowDropDownRunnable); + } + + /** * <p>Displays the drop down on screen.</p> */ 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. @@ -1059,20 +1111,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); // use outside touchable to dismiss drop down when touching outside of it, so @@ -1082,8 +1165,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mPopup.showAsDropDown(getDropDownAnchorView(), mDropDownHorizontalOffset, mDropDownVerticalOffset); mDropDownList.setSelection(ListView.INVALID_POSITION); - mDropDownList.hideSelector(); - mDropDownList.requestFocus(); + clearListSelection(); post(mHideSelector); } } @@ -1119,6 +1201,22 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mHideSelector = new ListSelectorHider(); + /** + * This Runnable exists for the sole purpose of checking if the view layout has got + * completed and if so call showDropDown to display the drop down. This is used to show + * the drop down as soon as possible after user opens up the search dialog, without + * waiting for the normal UI pipeline to do it's job which is slower than this method. + */ + mShowDropDownRunnable = new Runnable() { + public void run() { + // View layout should be all done before displaying the drop down. + View view = getDropDownAnchorView(); + if (view != null && view.getWindowToken() != null) { + showDropDown(); + } + } + }; + mDropDownList = new DropDownListView(context); mDropDownList.setSelector(mDropDownListHighlight); mDropDownList.setAdapter(mAdapter); @@ -1126,6 +1224,22 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownList.setOnItemClickListener(mDropDownItemClickListener); mDropDownList.setFocusable(true); mDropDownList.setFocusableInTouchMode(true); + mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> parent, View view, + int position, long id) { + + if (position != -1) { + DropDownListView dropDownList = mDropDownList; + + if (dropDownList != null) { + dropDownList.mListSelectionHidden = false; + } + } + } + + public void onNothingSelected(AdapterView<?> parent) { + } + }); if (mItemSelectedListener != null) { mDropDownList.setOnItemSelectedListener(mItemSelectedListener); @@ -1180,10 +1294,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) { @@ -1249,10 +1365,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe private class ListSelectorHider implements Runnable { public void run() { - if (mDropDownList != null) { - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); - } + clearListSelection(); } } @@ -1279,6 +1392,36 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * passed to the drop down; the list only looks focused.</p> */ private static class DropDownListView extends ListView { + /* + * WARNING: This is a workaround for a touch mode issue. + * + * Touch mode is propagated lazily to windows. This causes problems in + * the following scenario: + * - Type something in the AutoCompleteTextView and get some results + * - Move down with the d-pad to select an item in the list + * - Move up with the d-pad until the selection disappears + * - Type more text in the AutoCompleteTextView *using the soft keyboard* + * and get new results; you are now in touch mode + * - The selection comes back on the first item in the list, even though + * the list is supposed to be in touch mode + * + * Using the soft keyboard triggers the touch mode change but that change + * is propagated to our window only after the first list layout, therefore + * after the list attempts to resurrect the selection. + * + * The trick to work around this issue is to pretend the list is in touch + * mode when we know that the selection should not appear, that is when + * we know the user moved the selection away from the list. + * + * This boolean is set to true whenever we explicitely hide the list's + * selection and reset to false whenver we know the user moved the + * selection back to the list. + * + * When this boolean is true, isInTouchMode() returns true, otherwise it + * returns super.isInTouchMode(). + */ + private boolean mListSelectionHidden; + /** * <p>Creates a new list view wrapper.</p> * @@ -1324,6 +1467,12 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe return mSelectionBottomPadding; } + @Override + public boolean isInTouchMode() { + // WARNING: Please read the comment where mListSelectionHidden is declared + return mListSelectionHidden || super.isInTouchMode(); + } + /** * <p>Returns the focus state in the drop down.</p> * diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index abcc715..fd590ed 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -16,14 +16,15 @@ package android.widget; +import com.android.internal.R; + import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; - -import com.android.internal.R; +import android.view.accessibility.AccessibilityEvent; /** @@ -194,5 +195,13 @@ public class CheckedTextView extends TextView implements Checkable { invalidate(); } } - + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean populated = super.dispatchPopulateAccessibilityEvent(event); + if (!populated) { + event.setChecked(mChecked); + } + return populated; + } } diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index d4482dc..98b0976 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -26,7 +26,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.Gravity; - +import android.view.accessibility.AccessibilityEvent; /** * <p> @@ -124,6 +124,7 @@ public abstract class CompoundButton extends Button implements Checkable { if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); } + mBroadcasting = false; } } @@ -205,6 +206,25 @@ public abstract class CompoundButton extends Button implements Checkable { } @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean populated = super.dispatchPopulateAccessibilityEvent(event); + + if (!populated) { + int resourceId = 0; + if (mChecked) { + resourceId = R.string.accessibility_compound_button_selected; + } else { + resourceId = R.string.accessibility_compound_button_unselected; + } + String state = getResources().getString(resourceId); + event.getText().add(state); + event.setChecked(mChecked); + } + + return populated; + } + + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java index 0fc8f49..5360621 100644 --- a/core/java/android/widget/ExpandableListView.java +++ b/core/java/android/widget/ExpandableListView.java @@ -1083,6 +1083,11 @@ public class ExpandableListView extends ListView { @Override public void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index 3368477..cd965fc 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -134,7 +134,7 @@ class FastScroller { mScrollCompleted = true; - getSections(); + getSectionsFromIndexer(); mOverlayPos = new RectF(); mScrollFade = new ScrollFade(); @@ -250,7 +250,18 @@ class FastScroller { } } - private void getSections() { + SectionIndexer getSectionIndexer() { + return mSectionIndexer; + } + + Object[] getSections() { + if (mListAdapter == null && mList != null) { + getSectionsFromIndexer(); + } + return mSections; + } + + private void getSectionsFromIndexer() { Adapter adapter = mList.getAdapter(); mSectionIndexer = null; if (adapter instanceof HeaderViewListAdapter) { @@ -391,8 +402,7 @@ class FastScroller { boolean onInterceptTouchEvent(MotionEvent ev) { if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) { - if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY && - ev.getY() <= mThumbY + mThumbH) { + if (isPointInside(ev.getX(), ev.getY())) { setState(STATE_DRAGGING); return true; } @@ -404,20 +414,20 @@ class FastScroller { if (mState == STATE_NONE) { return false; } - if (me.getAction() == MotionEvent.ACTION_DOWN) { - if (me.getX() > mList.getWidth() - mThumbW - && me.getY() >= mThumbY - && me.getY() <= mThumbY + mThumbH) { - + + final int action = me.getAction(); + + if (action == MotionEvent.ACTION_DOWN) { + if (isPointInside(me.getX(), me.getY())) { setState(STATE_DRAGGING); if (mListAdapter == null && mList != null) { - getSections(); + getSectionsFromIndexer(); } cancelFling(); return true; } - } else if (me.getAction() == MotionEvent.ACTION_UP) { + } else if (action == MotionEvent.ACTION_UP) { if (mState == STATE_DRAGGING) { setState(STATE_VISIBLE); final Handler handler = mHandler; @@ -425,7 +435,7 @@ class FastScroller { handler.postDelayed(mScrollFade, 1000); return true; } - } else if (me.getAction() == MotionEvent.ACTION_MOVE) { + } else if (action == MotionEvent.ACTION_MOVE) { if (mState == STATE_DRAGGING) { final int viewHeight = mList.getHeight(); // Jitter @@ -448,7 +458,11 @@ class FastScroller { } return false; } - + + boolean isPointInside(float x, float y) { + return x > mList.getWidth() - mThumbW && y >= mThumbY && y <= mThumbY + mThumbH; + } + public class ScrollFade implements Runnable { long mStartTime; diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 80fbf9e..3afd5d4 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -353,25 +353,24 @@ public class FrameLayout extends ViewGroup { if (mForeground != null) { final Drawable foreground = mForeground; + if (mForegroundBoundsChanged) { mForegroundBoundsChanged = false; - if (foreground != null) { - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - final int w = mRight-mLeft; - final int h = mBottom-mTop; - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); - } + final Rect selfBounds = mSelfBounds; + final Rect overlayBounds = mOverlayBounds; - Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds); - foreground.setBounds(overlayBounds); + final int w = mRight-mLeft; + final int h = mBottom-mTop; + + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); } + + Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), + foreground.getIntrinsicHeight(), selfBounds, overlayBounds); + foreground.setBounds(overlayBounds); } foreground.draw(canvas); diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 02fc7c6..f86b37c 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -114,6 +114,8 @@ public class HorizontalScrollView extends FrameLayout { private boolean mSmoothScrollingEnabled = true; private int mTouchSlop; + private int mMinimumVelocity; + private int mMaximumVelocity; public HorizontalScrollView(Context context) { this(context, null); @@ -179,7 +181,10 @@ public class HorizontalScrollView extends FrameLayout { setFocusable(true); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setWillNotDraw(false); - mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + final ViewConfiguration configuration = ViewConfiguration.get(mContext); + mTouchSlop = configuration.getScaledTouchSlop(); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); } @Override @@ -477,12 +482,10 @@ public class HorizontalScrollView extends FrameLayout { break; case MotionEvent.ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getXVelocity(); - if ((Math.abs(initialVelocity) > - ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) && - getChildCount() > 0) { + if ((Math.abs(initialVelocity) > mMinimumVelocity) && getChildCount() > 0) { fling(-initialVelocity); } diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java index 4c1cbf6..d417e40 100644 --- a/core/java/android/widget/ImageButton.java +++ b/core/java/android/widget/ImageButton.java @@ -27,9 +27,35 @@ import java.util.Map; /** * <p> - * An image button displays an image that can be pressed, or clicked, by the - * user. - * </p> + * Displays a button with an image (instead of text) that can be pressed + * or clicked by the user. By default, an ImageButton looks like a regular + * {@link android.widget.Button}, with the standard button background + * that changes color during different button states. The image on the surface + * of the button is defined either by the {@code android:src} attribute in the + * {@code <ImageButton>} XML element or by the + * {@link #setImageResource(int)} method.</p> + * + * <p>To remove the standard button background image, define your own + * background image or set the background color to be transparent.</p> + * <p>To indicate the different button states (focused, selected, etc.), you can + * define a different image for each state. E.g., a blue image by default, an + * orange one for when focused, and a yellow one for when pressed. An easy way to + * do this is with an XML drawable "selector." For example:</p> + * <pre> + * <?xml version="1.0" encoding="utf-8"?> + * <selector xmlns:android="http://schemas.android.com/apk/res/android"> + * <item android:drawable="@drawable/button_normal" /> <!-- default --> + * <item android:state_pressed="true" + * android:drawable="@drawable/button_pressed" /> <!-- pressed --> + * <item android:state_focused="true" + * android:drawable="@drawable/button_focused" /> <!-- focused --> + * </selector></pre> + * + * <p>Save the XML file in your project {@code res/drawable/} folder and then + * reference it as a drawable for the source of your ImageButton (in the + * {@code android:src} attribute). Android will automatically change the image + * based on the state of the button and the corresponding images + * defined in the XML.</p> * * <p><strong>XML attributes</strong></p> * <p> diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 480b0b8..2796774 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -32,6 +32,8 @@ import android.net.Uri; import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.widget.RemoteViews.RemoteView; @@ -848,7 +850,7 @@ public class ImageView extends View { public int getBaseline() { return mBaselineAligned ? getMeasuredHeight() : -1; } - + /** * Set a tinting option for the image. * @@ -878,7 +880,7 @@ public class ImageView extends View { invalidate(); } } - + public void setAlpha(int alpha) { alpha &= 0xFF; // keep it legal if (mAlpha != alpha) { diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 5472d68..f8a6f89 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -21,6 +21,7 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.PixelFormat; +import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.graphics.drawable.ColorDrawable; import android.os.Parcel; @@ -35,6 +36,7 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewParent; import android.view.SoundEffectConstants; +import android.view.accessibility.AccessibilityEvent; import com.google.android.collect.Lists; import com.android.internal.R; @@ -132,6 +134,7 @@ public class ListView extends AbsListView { // used for temporary calculations. private final Rect mTempRect = new Rect(); + private Paint mDividerPaint; // the single allocated result per list view; kinda cheesey but avoids // allocating these thingies too often. @@ -171,6 +174,8 @@ public class ListView extends AbsListView { setDividerHeight(dividerHeight); } + setChoiceMode(a.getInt(R.styleable.ListView_choiceMode, CHOICE_MODE_NONE)); + mHeaderDividersEnabled = a.getBoolean(R.styleable.ListView_headerDividersEnabled, true); mFooterDividersEnabled = a.getBoolean(R.styleable.ListView_footerDividersEnabled, true); @@ -1845,6 +1850,39 @@ public class ListView extends AbsListView { } } + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean populated = super.dispatchPopulateAccessibilityEvent(event); + + // If the item count is less than 15 then subtract disabled items from the count and + // position. Otherwise ignore disabled items. + if (!populated) { + int itemCount = 0; + int currentItemIndex = getSelectedItemPosition(); + + ListAdapter adapter = getAdapter(); + if (adapter != null) { + final int count = adapter.getCount(); + if (count < 15) { + for (int i = 0; i < count; i++) { + if (adapter.isEnabled(i)) { + itemCount++; + } else if (i <= currentItemIndex) { + currentItemIndex--; + } + } + } else { + itemCount = count; + } + } + + event.setItemCount(itemCount); + event.setCurrentItemIndex(currentItemIndex); + } + + return populated; + } + /** * setSelectionAfterHeaderView set the selection to be the first list item * after the header views. @@ -2786,12 +2824,20 @@ public class ListView extends AbsListView { */ @Override public boolean isOpaque() { - return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque) || super.isOpaque(); + return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque && + hasOpaqueScrollbars()) || super.isOpaque(); } @Override public void setCacheColorHint(int color) { - mIsCacheColorOpaque = (color >>> 24) == 0xFF; + final boolean opaque = (color >>> 24) == 0xFF; + mIsCacheColorOpaque = opaque; + if (opaque) { + if (mDividerPaint == null) { + mDividerPaint = new Paint(); + } + mDividerPaint.setColor(color); + } super.setCacheColorHint(color); } @@ -2814,6 +2860,17 @@ public class ListView extends AbsListView { final int first = mFirstPosition; final boolean areAllItemsSelectable = mAreAllItemsSelectable; final ListAdapter adapter = mAdapter; + // If the list is opaque *and* the background is not, we want to + // fill a rect where the dividers would be for non-selectable items + // If the list is opaque and the background is also opaque, we don't + // need to draw anything since the background will do it for us + final boolean fillForMissingDividers = isOpaque() && !super.isOpaque(); + + if (fillForMissingDividers && mDividerPaint == null && mIsCacheColorOpaque) { + mDividerPaint = new Paint(); + mDividerPaint.setColor(getCacheColorHint()); + } + final Paint paint = mDividerPaint; if (!mStackFromBottom) { int bottom; @@ -2825,12 +2882,18 @@ public class ListView extends AbsListView { View child = getChildAt(i); bottom = child.getBottom(); // Don't draw dividers next to items that are not enabled - if (bottom < listBottom && (areAllItemsSelectable || - (adapter.isEnabled(first + i) && (i == count - 1 || - adapter.isEnabled(first + i + 1))))) { - bounds.top = bottom; - bounds.bottom = bottom + dividerHeight; - drawDivider(canvas, bounds, i); + if (bottom < listBottom) { + if ((areAllItemsSelectable || + (adapter.isEnabled(first + i) && (i == count - 1 || + adapter.isEnabled(first + i + 1))))) { + bounds.top = bottom; + bounds.bottom = bottom + dividerHeight; + drawDivider(canvas, bounds, i); + } else if (fillForMissingDividers) { + bounds.top = bottom; + bounds.bottom = bottom + dividerHeight; + canvas.drawRect(bounds, paint); + } } } } @@ -2844,16 +2907,22 @@ public class ListView extends AbsListView { View child = getChildAt(i); top = child.getTop(); // Don't draw dividers next to items that are not enabled - if (top > listTop && (areAllItemsSelectable || - (adapter.isEnabled(first + i) && (i == count - 1 || - adapter.isEnabled(first + i + 1))))) { - bounds.top = top - dividerHeight; - bounds.bottom = top; - // Give the method the child ABOVE the divider, so we - // subtract one from our child - // position. Give -1 when there is no child above the - // divider. - drawDivider(canvas, bounds, i - 1); + if (top > listTop) { + if ((areAllItemsSelectable || + (adapter.isEnabled(first + i) && (i == count - 1 || + adapter.isEnabled(first + i + 1))))) { + bounds.top = top - dividerHeight; + bounds.bottom = top; + // Give the method the child ABOVE the divider, so we + // subtract one from our child + // position. Give -1 when there is no child above the + // divider. + drawDivider(canvas, bounds, i - 1); + } else if (fillForMissingDividers) { + bounds.top = top - dividerHeight; + bounds.bottom = top; + canvas.drawRect(bounds, paint); + } } } } @@ -3195,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/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java index 05abc26..ae80277 100644 --- a/core/java/android/widget/MultiAutoCompleteTextView.java +++ b/core/java/android/widget/MultiAutoCompleteTextView.java @@ -195,6 +195,8 @@ public class MultiAutoCompleteTextView extends AutoCompleteTextView { */ @Override protected void replaceText(CharSequence text) { + clearComposingText(); + int end = getSelectionEnd(); int start = mTokenizer.findTokenStart(getText(), end); diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 78c7bd8..0c2cd55 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -18,6 +18,8 @@ package android.widget; import com.android.internal.R; +import android.content.Context; +import android.content.res.TypedArray; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -33,8 +35,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.os.IBinder; -import android.content.Context; -import android.content.res.TypedArray; import android.util.AttributeSet; import java.lang.ref.WeakReference; @@ -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; @@ -1017,6 +1017,7 @@ public class PopupWindow { unregisterForScrollChanged(); mWindowManager.removeView(mPopupView); + if (mPopupView != mContentView && mPopupView instanceof ViewGroup) { ((ViewGroup) mPopupView).removeView(mContentView); } @@ -1071,6 +1072,20 @@ public class PopupWindow { mWindowManager.updateViewLayout(mPopupView, p); } } + + /** + * <p>Updates the dimension of the popup window. Calling this function + * also updates the window with the current popup state as described + * for {@link #update()}.</p> + * + * @param width the new width + * @param height the new height + */ + public void update(int width, int height) { + WindowManager.LayoutParams p = (WindowManager.LayoutParams) + mPopupView.getLayoutParams(); + update(p.x, p.y, width, height, false); + } /** * <p>Updates the position and the dimension of the popup window. Width and @@ -1115,8 +1130,7 @@ public class PopupWindow { return; } - WindowManager.LayoutParams p = (WindowManager.LayoutParams) - mPopupView.getLayoutParams(); + WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); boolean update = force; @@ -1203,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) { @@ -1316,7 +1329,16 @@ public class PopupWindow { return super.onTouchEvent(event); } } - + + @Override + public void sendAccessibilityEvent(int eventType) { + // clinets are interested in the content not the container, make it event source + if (mContentView != null) { + mContentView.sendAccessibilityEvent(eventType); + } else { + super.sendAccessibilityEvent(eventType); + } + } } } diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 441414a..2c9e71e 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -30,6 +30,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.StateListDrawable; +import android.graphics.drawable.Animatable; import android.graphics.drawable.shapes.RoundRectShape; import android.graphics.drawable.shapes.Shape; import android.util.AttributeSet; @@ -683,7 +684,7 @@ public class ProgressBar extends View { return; } - if (mIndeterminateDrawable instanceof AnimationDrawable) { + if (mIndeterminateDrawable instanceof Animatable) { mShouldStartAnimationDrawable = true; mAnimation = null; } else { @@ -708,8 +709,8 @@ public class ProgressBar extends View { void stopAnimation() { mAnimation = null; mTransformation = null; - if (mIndeterminateDrawable instanceof AnimationDrawable) { - ((AnimationDrawable) mIndeterminateDrawable).stop(); + if (mIndeterminateDrawable instanceof Animatable) { + ((Animatable) mIndeterminateDrawable).stop(); mShouldStartAnimationDrawable = false; } } @@ -818,8 +819,8 @@ public class ProgressBar extends View { } d.draw(canvas); canvas.restore(); - if (mShouldStartAnimationDrawable && d instanceof AnimationDrawable) { - ((AnimationDrawable) d).start(); + if (mShouldStartAnimationDrawable && d instanceof Animatable) { + ((Animatable) d).start(); mShouldStartAnimationDrawable = false; } } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index edbb3db..e62dda5 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -16,40 +16,59 @@ package android.widget; +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.view.View; -import android.view.ViewGroup; +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; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.widget.RemoteViews.RemoteView; -import android.graphics.Rect; -import com.android.internal.R; +import java.util.Comparator; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.LinkedList; +import java.util.HashSet; +import java.util.ArrayList; /** * A Layout where the positions of the children can be described in relation to each other or to the * parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if * view Y is dependent on the position of view X, make sure the view X comes first in the layout. - * + * * <p> * Note that you cannot have a circular dependency between the size of the RelativeLayout and the * position of its children. For example, you cannot have a RelativeLayout whose height is set to * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to * {@link #ALIGN_PARENT_BOTTOM}. * </p> - * + * * <p> * Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for * layout attributes * </p> - * + * * @attr ref android.R.styleable#RelativeLayout_gravity * @attr ref android.R.styleable#RelativeLayout_ignoreGravity */ @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; /** @@ -137,6 +156,13 @@ public class RelativeLayout extends ViewGroup { private final Rect mSelfBounds = new Rect(); private int mIgnoreGravity; + 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); } @@ -225,7 +251,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; @@ -254,7 +327,6 @@ public class RelativeLayout extends ViewGroup { height = myHeight; } - int len = this.getChildCount(); mHasBaselineAlignedChild = false; View ignore = null; @@ -268,22 +340,50 @@ public class RelativeLayout extends ViewGroup { int right = Integer.MIN_VALUE; int bottom = Integer.MIN_VALUE; + boolean offsetHorizontalAxis = false; + boolean offsetVerticalAxis = false; + if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) { ignore = findViewById(mIgnoreGravity); } - for (int i = 0; i < len; i++) { - View child = getChildAt(i); + final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY; + final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY; + + View[] views = mSortedHorizontalChildren; + 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, myHeight); + if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) { + offsetHorizontalAxis = true; + } + } + } + + views = mSortedVerticalChildren; + 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); + if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) { + offsetVerticalAxis = true; + } - if (widthMode != MeasureSpec.EXACTLY) { + if (isWrapContentWidth) { width = Math.max(width, params.mRight); } - if (heightMode != MeasureSpec.EXACTLY) { + + if (isWrapContentHeight) { height = Math.max(height, params.mBottom); } @@ -300,15 +400,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) { @@ -319,8 +419,8 @@ public class RelativeLayout extends ViewGroup { } } - if (widthMode != MeasureSpec.EXACTLY) { - // Width already has left padding in it since it was calculated by looking at + if (isWrapContentWidth) { + // Width already has left padding in it since it was calculated by looking at // the right of each child view width += mPaddingRight; @@ -330,9 +430,23 @@ public class RelativeLayout extends ViewGroup { width = Math.max(width, getSuggestedMinimumWidth()); width = resolveSize(width, widthMeasureSpec); + + if (offsetHorizontalAxis) { + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getVisibility() != GONE) { + LayoutParams params = (LayoutParams) child.getLayoutParams(); + final int[] rules = params.getRules(); + if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) { + centerHorizontal(child, params, width); + } + } + } + } } - if (heightMode != MeasureSpec.EXACTLY) { - // Height already has top padding in it since it was calculated by looking at + + if (isWrapContentHeight) { + // Height already has top padding in it since it was calculated by looking at // the bottom of each child view height += mPaddingBottom; @@ -342,6 +456,19 @@ public class RelativeLayout extends ViewGroup { height = Math.max(height, getSuggestedMinimumHeight()); height = resolveSize(height, heightMeasureSpec); + + if (offsetVerticalAxis) { + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getVisibility() != GONE) { + LayoutParams params = (LayoutParams) child.getLayoutParams(); + final int[] rules = params.getRules(); + if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) { + centerVertical(child, params, height); + } + } + } + } } if (horizontalGravity || verticalGravity) { @@ -355,7 +482,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(); @@ -409,9 +536,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, @@ -425,6 +550,21 @@ public class RelativeLayout extends ViewGroup { child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } + private void measureChildHorizontal(View child, LayoutParams params, int myWidth, int myHeight) { + int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft, + params.mRight, params.width, + params.leftMargin, params.rightMargin, + mPaddingLeft, mPaddingRight, + myWidth); + int childHeightMeasureSpec; + if (params.width == LayoutParams.FILL_PARENT) { + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST); + } + 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 @@ -504,19 +644,9 @@ 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 boolean positionChildHorizontal(View child, LayoutParams params, int myWidth, + boolean wrapContent) { + int[] rules = params.getRules(); if (params.mLeft < 0 && params.mRight >= 0) { @@ -527,13 +657,26 @@ public class RelativeLayout extends ViewGroup { params.mRight = params.mLeft + child.getMeasuredWidth(); } else if (params.mLeft < 0 && params.mRight < 0) { // Both left and right vary - if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_HORIZONTAL]) { - centerHorizontal(child, params, myWidth); + if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) { + if (!wrapContent) { + centerHorizontal(child, params, myWidth); + } else { + params.mLeft = mPaddingLeft + params.leftMargin; + params.mRight = params.mLeft + child.getMeasuredWidth(); + } + return true; } else { params.mLeft = mPaddingLeft + params.leftMargin; params.mRight = params.mLeft + child.getMeasuredWidth(); } } + return false; + } + + private boolean positionChildVertical(View child, LayoutParams params, int myHeight, + boolean wrapContent) { + + int[] rules = params.getRules(); if (params.mTop < 0 && params.mBottom >= 0) { // Bottom is fixed, but top varies @@ -543,26 +686,23 @@ public class RelativeLayout extends ViewGroup { params.mBottom = params.mTop + child.getMeasuredHeight(); } else if (params.mTop < 0 && params.mBottom < 0) { // Both top and bottom vary - if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_VERTICAL]) { - centerVertical(child, params, myHeight); + if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) { + if (!wrapContent) { + centerVertical(child, params, myHeight); + } else { + params.mTop = mPaddingTop + params.topMargin; + params.mBottom = params.mTop + child.getMeasuredHeight(); + } + return true; } else { params.mTop = mPaddingTop + params.topMargin; params.mBottom = params.mTop + child.getMeasuredHeight(); } } + return false; } - /** - * 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; @@ -622,6 +762,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; @@ -684,18 +829,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.mKeyNodes.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.mKeyNodes.get((rules[relation])); + if (node == null) return null; + v = node.view; } return v; @@ -782,6 +925,57 @@ public class RelativeLayout extends ViewGroup { return new LayoutParams(p); } + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + if (mTopToBottomLeftToRightSet == null) { + mTopToBottomLeftToRightSet = new TreeSet<View>(new TopToBottomLeftToRightComparator()); + } + + // sort children top-to-bottom and left-to-right + for (int i = 0, count = getChildCount(); i < count; i++) { + mTopToBottomLeftToRightSet.add(getChildAt(i)); + } + + for (View view : mTopToBottomLeftToRightSet) { + if (view.dispatchPopulateAccessibilityEvent(event)) { + mTopToBottomLeftToRightSet.clear(); + return true; + } + } + + mTopToBottomLeftToRightSet.clear(); + return false; + } + + /** + * Compares two views in left-to-right and top-to-bottom fashion. + */ + private class TopToBottomLeftToRightComparator implements Comparator<View> { + public int compare(View first, View second) { + // top - bottom + int topDifference = first.getTop() - second.getTop(); + if (topDifference != 0) { + return topDifference; + } + // left - right + int leftDifference = first.getLeft() - second.getLeft(); + if (leftDifference != 0) { + return leftDifference; + } + // break tie by height + int heightDiference = first.getHeight() - second.getHeight(); + if (heightDiference != 0) { + return heightDiference; + } + // break tie by width + int widthDiference = first.getWidth() - second.getWidth(); + if (widthDiference != 0) { + return widthDiference; + } + return 0; + } + } + /** * Per-child layout information associated with RelativeLayout. * @@ -823,7 +1017,7 @@ public class RelativeLayout extends ViewGroup { @ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf") }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true"), - @ViewDebug.IntToString(from = 0, to = "FALSE/NO_ID") + @ViewDebug.IntToString(from = 0, to = "false/NO_ID") }) private int[] mRules = new int[VERB_COUNT]; @@ -975,4 +1169,284 @@ public class RelativeLayout extends ViewGroup { return mRules; } } + + private static class DependencyGraph { + /** + * List of all views in the graph. + */ + private ArrayList<Node> mNodes = new ArrayList<Node>(); + + /** + * List of nodes in the graph. Each node is identified by its + * view id (see View#getId()). + */ + private SparseArray<Node> mKeyNodes = 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 ArrayList<Node> nodes = mNodes; + final int count = nodes.size(); + + for (int i = 0; i < count; i++) { + nodes.get(i).release(); + } + nodes.clear(); + + mKeyNodes.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) { + final int id = view.getId(); + final Node node = Node.acquire(view); + + if (id != View.NO_ID) { + mKeyNodes.put(id, node); + } + + mNodes.add(node); + } + + /** + * 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> keyNodes = mKeyNodes; + final ArrayList<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.get(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.get(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 = keyNodes.get(rule); + if (dependency == node) { + throw new IllegalStateException("A view cannot have a dependency" + + " on itself"); + } + if (dependency == null) { + continue; + } + // 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.get(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 + */ + // The pool is static, so all nodes instances are shared across + // activities, that's why we give it a rather high limit + private static final int POOL_LIMIT = 100; + 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/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7936f65..2dac652 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -20,10 +20,8 @@ import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.PorterDuff; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Parcel; @@ -36,15 +34,12 @@ import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater.Filter; import android.view.View.OnClickListener; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import java.lang.Class; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -69,13 +64,7 @@ public class RemoteViews implements Parcelable, Filter { * The resource ID of the layout file. (Added to the parcel) */ private int mLayoutId; - - /** - * The Context object used to inflate the layout file. Also may - * be used by actions if they need access to the senders resources. - */ - private Context mContext; - + /** * An array of actions to perform on the view tree once it has been * inflated @@ -85,7 +74,7 @@ public class RemoteViews implements Parcelable, Filter { /** * This annotation indicates that a subclass of View is alllowed to be used - * with the {@link android.widget.RemoteViews} mechanism. + * with the {@link RemoteViews} mechanism. */ @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @@ -116,7 +105,7 @@ public class RemoteViews implements Parcelable, Filter { public int describeContents() { return 0; } - }; + } /** * Equivalent to calling @@ -232,15 +221,17 @@ public class RemoteViews implements Parcelable, Filter { targetDrawable = imageView.getDrawable(); } - // Perform modifications only if values are set correctly - if (alpha != -1) { - targetDrawable.setAlpha(alpha); - } - if (colorFilter != -1 && filterMode != null) { - targetDrawable.setColorFilter(colorFilter, filterMode); - } - if (level != -1) { - targetDrawable.setLevel(level); + if (targetDrawable != null) { + // Perform modifications only if values are set correctly + if (alpha != -1) { + targetDrawable.setAlpha(alpha); + } + if (colorFilter != -1 && filterMode != null) { + targetDrawable.setColorFilter(colorFilter, filterMode); + } + if (level != -1) { + targetDrawable.setLevel(level); + } } } @@ -289,6 +280,7 @@ public class RemoteViews implements Parcelable, Filter { this.viewId = in.readInt(); this.methodName = in.readString(); this.type = in.readInt(); + //noinspection ConstantIfStatement if (false) { Log.d("RemoteViews", "read viewId=0x" + Integer.toHexString(this.viewId) + " methodName=" + this.methodName + " type=" + this.type); @@ -340,31 +332,32 @@ public class RemoteViews implements Parcelable, Filter { out.writeInt(this.viewId); out.writeString(this.methodName); out.writeInt(this.type); + //noinspection ConstantIfStatement if (false) { Log.d("RemoteViews", "write viewId=0x" + Integer.toHexString(this.viewId) + " methodName=" + this.methodName + " type=" + this.type); } switch (this.type) { case BOOLEAN: - out.writeInt(((Boolean)this.value).booleanValue() ? 1 : 0); + out.writeInt((Boolean) this.value ? 1 : 0); break; case BYTE: - out.writeByte(((Byte)this.value).byteValue()); + out.writeByte((Byte) this.value); break; case SHORT: - out.writeInt(((Short)this.value).shortValue()); + out.writeInt((Short) this.value); break; case INT: - out.writeInt(((Integer)this.value).intValue()); + out.writeInt((Integer) this.value); break; case LONG: - out.writeLong(((Long)this.value).longValue()); + out.writeLong((Long) this.value); break; case FLOAT: - out.writeFloat(((Float)this.value).floatValue()); + out.writeFloat((Float) this.value); break; case DOUBLE: - out.writeDouble(((Double)this.value).doubleValue()); + out.writeDouble((Double) this.value); break; case CHAR: out.writeInt((int)((Character)this.value).charValue()); @@ -430,7 +423,7 @@ public class RemoteViews implements Parcelable, Filter { } Class klass = view.getClass(); - Method method = null; + Method method; try { method = klass.getMethod(this.methodName, getParameterType()); } @@ -446,6 +439,7 @@ public class RemoteViews implements Parcelable, Filter { } try { + //noinspection ConstantIfStatement if (false) { Log.d("RemoteViews", "view: " + klass.getName() + " calling method: " + this.methodName + "(" + param.getName() + ") with " @@ -816,13 +810,12 @@ public class RemoteViews implements Parcelable, Filter { * @return The inflated view hierarchy */ public View apply(Context context, ViewGroup parent) { - View result = null; + View result; Context c = prepareContext(context); - Resources r = c.getResources(); - LayoutInflater inflater = (LayoutInflater) c - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater inflater = (LayoutInflater) + c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater = inflater.cloneInContext(c); inflater.setFilter(this); @@ -858,12 +851,12 @@ public class RemoteViews implements Parcelable, Filter { } private Context prepareContext(Context context) { - Context c = null; + Context c; String packageName = mPackage; if (packageName != null) { try { - c = context.createPackageContext(packageName, 0); + c = context.createPackageContext(packageName, Context.CONTEXT_RESTRICTED); } catch (NameNotFoundException e) { Log.e(LOG_TAG, "Package name " + packageName + " not found"); c = context; @@ -872,8 +865,6 @@ public class RemoteViews implements Parcelable, Filter { c = context; } - mContext = c; - return c; } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index c9b3751..90e1242 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -115,6 +115,8 @@ public class ScrollView extends FrameLayout { private boolean mSmoothScrollingEnabled = true; private int mTouchSlop; + private int mMinimumVelocity; + private int mMaximumVelocity; public ScrollView(Context context) { this(context, null); @@ -180,7 +182,10 @@ public class ScrollView extends FrameLayout { setFocusable(true); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setWillNotDraw(false); - mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + final ViewConfiguration configuration = ViewConfiguration.get(mContext); + mTouchSlop = configuration.getScaledTouchSlop(); + mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); } @Override @@ -478,12 +483,10 @@ public class ScrollView extends FrameLayout { break; case MotionEvent.ACTION_UP: final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getYVelocity(); - if ((Math.abs(initialVelocity) > - ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) && - getChildCount() > 0) { + if ((Math.abs(initialVelocity) > mMinimumVelocity) && getChildCount() > 0) { fling(-initialVelocity); } diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java index 92561ed..f706744 100644 --- a/core/java/android/widget/SlidingDrawer.java +++ b/core/java/android/widget/SlidingDrawer.java @@ -16,21 +16,22 @@ package android.widget; -import android.view.ViewGroup; -import android.view.View; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.SoundEffectConstants; +import android.R; import android.content.Context; import android.content.res.TypedArray; -import android.util.AttributeSet; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.Bitmap; -import android.os.SystemClock; import android.os.Handler; import android.os.Message; -import android.R; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; /** * SlidingDrawer hides content out of the screen and allows the user to drag a handle @@ -746,6 +747,8 @@ public class SlidingDrawer extends ViewGroup { openDrawer(); invalidate(); requestLayout(); + + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } /** @@ -777,6 +780,7 @@ public class SlidingDrawer extends ViewGroup { scrollListener.onScrollStarted(); } animateClose(mVertical ? mHandle.getTop() : mHandle.getLeft()); + if (scrollListener != null) { scrollListener.onScrollEnded(); } @@ -798,6 +802,9 @@ public class SlidingDrawer extends ViewGroup { scrollListener.onScrollStarted(); } animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft()); + + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + if (scrollListener != null) { scrollListener.onScrollEnded(); } @@ -827,6 +834,7 @@ public class SlidingDrawer extends ViewGroup { } mExpanded = true; + if (mOnDrawerOpenListener != null) { mOnDrawerOpenListener.onDrawerOpened(); } diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java index dc2c70d..103d44d 100644 --- a/core/java/android/widget/TabHost.java +++ b/core/java/android/widget/TabHost.java @@ -87,8 +87,9 @@ public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchMode /** - * <p>Call setup() before adding tabs if loading TabHost using findViewById(). <i><b>However</i></b>: You do - * not need to call setup() after getTabHost() in {@link android.app.TabActivity TabActivity}. + * <p>Call setup() before adding tabs if loading TabHost using findViewById(). + * <i><b>However</i></b>: You do not need to call setup() after getTabHost() + * in {@link android.app.TabActivity TabActivity}. * Example:</p> <pre>mTabHost = (TabHost)findViewById(R.id.tabhost); mTabHost.setup(); @@ -176,7 +177,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); // leaving touch mode.. if nothing has focus, let's give it to // the indicator of the current tab if (!mCurrentView.hasFocus() || mCurrentView.isFocused()) { - mTabWidget.getChildAt(mCurrentTab).requestFocus(); + mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus(); } } } @@ -196,6 +197,12 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView(); tabIndicator.setOnKeyListener(mTabKeyListener); + + // If this is a custom view, then do not draw the bottom strips for + // the tab indicators. + if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) { + mTabWidget.setDrawBottomStrips(false); + } mTabWidget.addView(tabIndicator); mTabSpecs.add(tabSpec); @@ -234,7 +241,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); public View getCurrentTabView() { if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) { - return mTabWidget.getChildAt(mCurrentTab); + return mTabWidget.getChildTabViewAt(mCurrentTab); } return null; } @@ -272,7 +279,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); && (mCurrentView.isRootNamespace()) && (mCurrentView.hasFocus()) && (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) { - mTabWidget.getChildAt(mCurrentTab).requestFocus(); + mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus(); playSoundEffect(SoundEffectConstants.NAVIGATION_UP); return true; } @@ -363,14 +370,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); * * @param tag * Which tab was selected. - * @return The view to distplay the contents of the selected tab. + * @return The view to display the contents of the selected tab. */ View createTabContent(String tag); } /** - * A tab has a tab indictor, content, and a tag that is used to keep + * A tab has a tab indicator, content, and a tag that is used to keep * track of it. This builder helps choose among these options. * * For the tab indicator, your choices are: @@ -410,6 +417,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } /** + * Specify a view as the tab indicator. + */ + public TabSpec setIndicator(View view) { + mIndicatorStrategy = new ViewIndicatorStrategy(view); + return this; + } + + /** * Specify the id of the view that should be used as the content * of the tab. */ @@ -436,7 +451,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } - String getTag() { + public String getTag() { return mTag; } } @@ -525,6 +540,22 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } /** + * How to create a tab indicator by specifying a view. + */ + private class ViewIndicatorStrategy implements IndicatorStrategy { + + private final View mView; + + private ViewIndicatorStrategy(View view) { + mView = view; + } + + public View createIndicatorView() { + return mView; + } + } + + /** * How to create the tab content via a view id. */ private class ViewIdContentStrategy implements ContentStrategy { @@ -607,7 +638,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } mLaunchedView = wd; - // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activies for now so they can get + // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get // focus if none of their children have it. They need focus to be able to // display menu items. // diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 20cddcb..a26bfa2 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -49,6 +49,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { private Drawable mBottomLeftStrip; private Drawable mBottomRightStrip; private boolean mStripMoved; + private Drawable mDividerDrawable; + private boolean mDrawBottomStrips = true; public TabWidget(Context context) { this(context, null); @@ -87,9 +89,68 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { setOnFocusChangeListener(this); } + /** + * Returns the tab indicator view at the given index. + * + * @param index the zero-based index of the tab indicator view to return + * @return the tab indicator view at the given index + */ + public View getChildTabViewAt(int index) { + // If we are using dividers, then instead of tab views at 0, 1, 2, ... + // we have tab views at 0, 2, 4, ... + if (mDividerDrawable != null) { + index *= 2; + } + return getChildAt(index); + } + + /** + * Returns the number of tab indicator views. + * @return the number of tab indicator views. + */ + public int getTabCount() { + int children = getChildCount(); + + // If we have dividers, then we will always have an odd number of + // children: 1, 3, 5, ... and we want to convert that sequence to + // this: 1, 2, 3, ... + if (mDividerDrawable != null) { + children = (children + 1) / 2; + } + return children; + } + + /** + * Sets the drawable to use as a divider between the tab indicators. + * @param drawable the divider drawable + */ + public void setDividerDrawable(Drawable drawable) { + mDividerDrawable = drawable; + } + + /** + * Sets the drawable to use as a divider between the tab indicators. + * @param resId the resource identifier of the drawable to use as a + * divider. + */ + public void setDividerDrawable(int resId) { + mDividerDrawable = mContext.getResources().getDrawable(resId); + } + + /** + * Controls whether the bottom strips on the tab indicators are drawn or + * not. The default is to draw them. If the user specifies a custom + * view for the tab indicators, then the TabHost class calls this method + * to disable drawing of the bottom strips. + * @param drawBottomStrips true if the bottom strips should be drawn. + */ + void setDrawBottomStrips(boolean drawBottomStrips) { + mDrawBottomStrips = drawBottomStrips; + } + @Override public void childDrawableStateChanged(View child) { - if (child == getChildAt(mSelectedTab)) { + if (child == getChildTabViewAt(mSelectedTab)) { // To make sure that the bottom strip is redrawn invalidate(); } @@ -100,7 +161,14 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { public void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); - View selectedChild = getChildAt(mSelectedTab); + // If the user specified a custom view for the tab indicators, then + // do not draw the bottom strips. + if (!mDrawBottomStrips) { + // Skip drawing the bottom strips. + return; + } + + View selectedChild = getChildTabViewAt(mSelectedTab); mBottomLeftStrip.setState(selectedChild.getDrawableState()); mBottomRightStrip.setState(selectedChild.getDrawableState()); @@ -157,13 +225,13 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { * @see #focusCurrentTab */ public void setCurrentTab(int index) { - if (index < 0 || index >= getChildCount()) { + if (index < 0 || index >= getTabCount()) { return; } - getChildAt(mSelectedTab).setSelected(false); + getChildTabViewAt(mSelectedTab).setSelected(false); mSelectedTab = index; - getChildAt(mSelectedTab).setSelected(true); + getChildTabViewAt(mSelectedTab).setSelected(true); mStripMoved = true; } @@ -189,17 +257,17 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { // change the focus if applicable. if (oldTab != index) { - getChildAt(index).requestFocus(); + getChildTabViewAt(index).requestFocus(); } } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); - int count = getChildCount(); + int count = getTabCount(); - for (int i=0; i<count; i++) { - View child = getChildAt(i); + for (int i = 0; i < count; i++) { + View child = getChildTabViewAt(i); child.setEnabled(enabled); } } @@ -218,17 +286,26 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { child.setFocusable(true); child.setClickable(true); + // If we have dividers between the tabs and we already have at least one + // tab, then add a divider before adding the next tab. + if (mDividerDrawable != null && getTabCount() > 0) { + View divider = new View(mContext); + final LinearLayout.LayoutParams lp = new LayoutParams( + mDividerDrawable.getIntrinsicWidth(), + mDividerDrawable.getIntrinsicHeight()); + lp.setMargins(0, 0, 0, 0); + divider.setLayoutParams(lp); + divider.setBackgroundDrawable(mDividerDrawable); + super.addView(divider); + } super.addView(child); // TODO: detect this via geometry with a tabwidget listener rather // than potentially interfere with the view's listener - child.setOnClickListener(new TabClickListener(getChildCount() - 1)); + child.setOnClickListener(new TabClickListener(getTabCount() - 1)); child.setOnFocusChangeListener(this); } - - - /** * Provides a way for {@link TabHost} to be notified that the user clicked on a tab indicator. */ @@ -238,14 +315,15 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { public void onFocusChange(View v, boolean hasFocus) { if (v == this && hasFocus) { - getChildAt(mSelectedTab).requestFocus(); + getChildTabViewAt(mSelectedTab).requestFocus(); return; } if (hasFocus) { int i = 0; - while (i < getChildCount()) { - if (getChildAt(i) == v) { + int numTabs = getTabCount(); + while (i < numTabs) { + if (getChildTabViewAt(i) == v) { setCurrentTab(i); mSelectionChangedListener.onTabSelectionChanged(i, false); break; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index adfc74f..d8ed4f0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,6 +16,11 @@ package android.widget; +import com.android.internal.util.FastMath; +import com.android.internal.widget.EditableInputConnection; + +import org.xmlpull.v1.XmlPullParserException; + import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; @@ -31,17 +36,17 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; +import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.ResultReceiver; import android.os.SystemClock; -import android.os.Message; import android.text.BoringLayout; +import android.text.ClipboardManager; import android.text.DynamicLayout; import android.text.Editable; import android.text.GetChars; import android.text.GraphicsOperations; -import android.text.ClipboardManager; import android.text.InputFilter; import android.text.InputType; import android.text.Layout; @@ -49,9 +54,9 @@ import android.text.ParcelableSpan; import android.text.Selection; import android.text.SpanWatcher; import android.text.Spannable; +import android.text.SpannableString; import android.text.Spanned; import android.text.SpannedString; -import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; @@ -64,19 +69,18 @@ import android.text.method.KeyListener; import android.text.method.LinkMovementMethod; import android.text.method.MetaKeyKeyListener; import android.text.method.MovementMethod; -import android.text.method.TimeKeyListener; - import android.text.method.PasswordTransformationMethod; import android.text.method.SingleLineTransformationMethod; import android.text.method.TextKeyListener; +import android.text.method.TimeKeyListener; import android.text.method.TransformationMethod; import android.text.style.ParagraphStyle; import android.text.style.URLSpan; import android.text.style.UpdateAppearance; import android.text.util.Linkify; import android.util.AttributeSet; -import android.util.Log; import android.util.FloatMath; +import android.util.Log; import android.util.TypedValue; import android.view.ContextMenu; import android.view.Gravity; @@ -89,25 +93,22 @@ import android.view.ViewDebug; import android.view.ViewRoot; import android.view.ViewTreeObserver; import android.view.ViewGroup.LayoutParams; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.AnimationUtils; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.EditorInfo; import android.widget.RemoteViews.RemoteView; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; -import com.android.internal.util.FastMath; -import com.android.internal.widget.EditableInputConnection; - -import org.xmlpull.v1.XmlPullParserException; - /** * Displays text to the user and optionally allows them to edit it. A TextView * is a complete text editor, however the basic class is configured to not @@ -126,6 +127,8 @@ import org.xmlpull.v1.XmlPullParserException; * @attr ref android.R.styleable#TextView_textColor * @attr ref android.R.styleable#TextView_textColorHighlight * @attr ref android.R.styleable#TextView_textColorHint + * @attr ref android.R.styleable#TextView_textAppearance + * @attr ref android.R.styleable#TextView_textColorLink * @attr ref android.R.styleable#TextView_textSize * @attr ref android.R.styleable#TextView_textScaleX * @attr ref android.R.styleable#TextView_typeface @@ -163,13 +166,22 @@ import org.xmlpull.v1.XmlPullParserException; * @attr ref android.R.styleable#TextView_capitalize * @attr ref android.R.styleable#TextView_autoText * @attr ref android.R.styleable#TextView_editable + * @attr ref android.R.styleable#TextView_freezesText + * @attr ref android.R.styleable#TextView_ellipsize * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableBottom * @attr ref android.R.styleable#TextView_drawableRight * @attr ref android.R.styleable#TextView_drawableLeft + * @attr ref android.R.styleable#TextView_drawablePadding * @attr ref android.R.styleable#TextView_lineSpacingExtra * @attr ref android.R.styleable#TextView_lineSpacingMultiplier * @attr ref android.R.styleable#TextView_marqueeRepeatLimit + * @attr ref android.R.styleable#TextView_inputType + * @attr ref android.R.styleable#TextView_imeOptions + * @attr ref android.R.styleable#TextView_privateImeOptions + * @attr ref android.R.styleable#TextView_imeActionLabel + * @attr ref android.R.styleable#TextView_imeActionId + * @attr ref android.R.styleable#TextView_editorExtras */ @RemoteView public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { @@ -404,6 +416,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean singleLine = false; int maxlength = -1; CharSequence text = ""; + CharSequence hint = null; int shadowcolor = 0; float dx = 0, dy = 0, r = 0; boolean password = false; @@ -531,7 +544,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case com.android.internal.R.styleable.TextView_hint: - setHint(a.getText(attr)); + hint = a.getText(attr); break; case com.android.internal.R.styleable.TextView_text: @@ -861,6 +874,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } setText(text, bufferType); + if (hint != null) setHint(hint); /* * Views are not normally focusable unless specified to be. @@ -1328,9 +1342,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else { // We need to retain the last set padding, so just clear // out all of the fields in the existing structure. + if (dr.mDrawableLeft != null) dr.mDrawableLeft.setCallback(null); dr.mDrawableLeft = null; + if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null); dr.mDrawableTop = null; + if (dr.mDrawableRight != null) dr.mDrawableRight.setCallback(null); dr.mDrawableRight = null; + if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null); dr.mDrawableBottom = null; dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0; dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0; @@ -1343,19 +1361,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mDrawables = dr = new Drawables(); } + if (dr.mDrawableLeft != left && dr.mDrawableLeft != null) { + dr.mDrawableLeft.setCallback(null); + } dr.mDrawableLeft = left; + if (dr.mDrawableTop != left && dr.mDrawableTop != null) { + dr.mDrawableTop.setCallback(null); + } dr.mDrawableTop = top; + if (dr.mDrawableRight != left && dr.mDrawableRight != null) { + dr.mDrawableRight.setCallback(null); + } dr.mDrawableRight = right; + if (dr.mDrawableBottom != left && dr.mDrawableBottom != null) { + dr.mDrawableBottom.setCallback(null); + } dr.mDrawableBottom = bottom; final Rect compoundRect = dr.mCompoundRect; - int[] state = null; + int[] state; state = getDrawableState(); if (left != null) { left.setState(state); left.copyBounds(compoundRect); + left.setCallback(this); dr.mDrawableSizeLeft = compoundRect.width(); dr.mDrawableHeightLeft = compoundRect.height(); } else { @@ -1365,6 +1396,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (right != null) { right.setState(state); right.copyBounds(compoundRect); + right.setCallback(this); dr.mDrawableSizeRight = compoundRect.width(); dr.mDrawableHeightRight = compoundRect.height(); } else { @@ -1374,6 +1406,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (top != null) { top.setState(state); top.copyBounds(compoundRect); + top.setCallback(this); dr.mDrawableSizeTop = compoundRect.height(); dr.mDrawableWidthTop = compoundRect.width(); } else { @@ -1383,6 +1416,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (bottom != null) { bottom.setState(state); bottom.copyBounds(compoundRect); + bottom.setCallback(this); dr.mDrawableSizeBottom = compoundRect.height(); dr.mDrawableWidthBottom = compoundRect.width(); } else { @@ -2785,8 +2819,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener checkForRelayout(); } - if (mText.length() == 0) + if (mText.length() == 0) { invalidate(); + } } /** @@ -3646,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 @@ -3666,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 @@ -3680,6 +3717,54 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } @Override + public void invalidateDrawable(Drawable drawable) { + if (verifyDrawable(drawable)) { + final Rect dirty = drawable.getBounds(); + int scrollX = mScrollX; + int scrollY = mScrollY; + + // IMPORTANT: The coordinates below are based on the coordinates computed + // for each compound drawable in onDraw(). Make sure to update each section + // accordingly. + final TextView.Drawables drawables = mDrawables; + if (drawables != null) { + if (drawable == drawables.mDrawableLeft) { + final int compoundPaddingTop = getCompoundPaddingTop(); + final int compoundPaddingBottom = getCompoundPaddingBottom(); + final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; + + scrollX += mPaddingLeft; + scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightLeft) / 2; + } else if (drawable == drawables.mDrawableRight) { + final int compoundPaddingTop = getCompoundPaddingTop(); + final int compoundPaddingBottom = getCompoundPaddingBottom(); + final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; + + scrollX += (mRight - mLeft - mPaddingRight - drawables.mDrawableSizeRight); + scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightRight) / 2; + } else if (drawable == drawables.mDrawableTop) { + final int compoundPaddingLeft = getCompoundPaddingLeft(); + final int compoundPaddingRight = getCompoundPaddingRight(); + final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft; + + scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthTop) / 2; + scrollY += mPaddingTop; + } else if (drawable == drawables.mDrawableBottom) { + final int compoundPaddingLeft = getCompoundPaddingLeft(); + final int compoundPaddingRight = getCompoundPaddingRight(); + final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft; + + scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthBottom) / 2; + scrollY += (mBottom - mTop - mPaddingBottom - drawables.mDrawableSizeBottom); + } + } + + invalidate(dirty.left + scrollX, dirty.top + scrollY, + dirty.right + scrollX, dirty.bottom + scrollY); + } + } + + @Override protected void onDraw(Canvas canvas) { restartMarqueeIfNeeded(); @@ -3707,6 +3792,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop; int hspace = right - left - compoundPaddingRight - compoundPaddingLeft; + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. if (dr.mDrawableLeft != null) { canvas.save(); canvas.translate(scrollX + mPaddingLeft, @@ -3716,6 +3803,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener canvas.restore(); } + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. if (dr.mDrawableRight != null) { canvas.save(); canvas.translate(scrollX + right - left - mPaddingRight - dr.mDrawableSizeRight, @@ -3724,6 +3813,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener canvas.restore(); } + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. if (dr.mDrawableTop != null) { canvas.save(); canvas.translate(scrollX + compoundPaddingLeft + (hspace - dr.mDrawableWidthTop) / 2, @@ -3732,6 +3823,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener canvas.restore(); } + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. if (dr.mDrawableBottom != null) { canvas.save(); canvas.translate(scrollX + compoundPaddingLeft + @@ -4714,10 +4807,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener alignment = Layout.Alignment.ALIGN_NORMAL; } + boolean shouldEllipsize = mEllipsize != null && mInput == null; + if (mText instanceof Spannable) { mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w, alignment, mSpacingMult, - mSpacingAdd, mIncludePad, mEllipsize, + mSpacingAdd, mIncludePad, mInput == null ? mEllipsize : null, ellipsisWidth); } else { if (boring == UNKNOWN_BORING) { @@ -4744,7 +4839,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Log.e("aaa", "Boring: " + mTransformed); mSavedLayout = (BoringLayout) mLayout; - } else if (mEllipsize != null && boring.width <= w) { + } else if (shouldEllipsize && boring.width <= w) { if (mSavedLayout != null) { mLayout = mSavedLayout. replaceOrMake(mTransformed, mTextPaint, @@ -4757,7 +4852,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boring, mIncludePad, mEllipsize, ellipsisWidth); } - } else if (mEllipsize != null) { + } else if (shouldEllipsize) { mLayout = new StaticLayout(mTransformed, 0, mTransformed.length(), mTextPaint, w, alignment, mSpacingMult, @@ -4769,7 +4864,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mIncludePad); // Log.e("aaa", "Boring but wide: " + mTransformed); } - } else if (mEllipsize != null) { + } else if (shouldEllipsize) { mLayout = new StaticLayout(mTransformed, 0, mTransformed.length(), mTextPaint, w, alignment, mSpacingMult, @@ -4782,9 +4877,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + shouldEllipsize = mEllipsize != null; mHintLayout = null; if (mHint != null) { + if (shouldEllipsize) hintWidth = w; + if (hintBoring == UNKNOWN_BORING) { hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mHintBoring); @@ -4794,24 +4892,50 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (hintBoring != null) { - if (hintBoring.width <= hintWidth) { + if (hintBoring.width <= hintWidth && + (!shouldEllipsize || hintBoring.width <= ellipsisWidth)) { if (mSavedHintLayout != null) { mHintLayout = mSavedHintLayout. replaceOrMake(mHint, mTextPaint, - hintWidth, alignment, mSpacingMult, - mSpacingAdd, hintBoring, mIncludePad); + hintWidth, alignment, mSpacingMult, mSpacingAdd, + hintBoring, mIncludePad); } else { mHintLayout = BoringLayout.make(mHint, mTextPaint, - hintWidth, alignment, mSpacingMult, - mSpacingAdd, hintBoring, mIncludePad); + hintWidth, alignment, mSpacingMult, mSpacingAdd, + hintBoring, mIncludePad); } mSavedHintLayout = (BoringLayout) mHintLayout; + } else if (shouldEllipsize && hintBoring.width <= hintWidth) { + if (mSavedHintLayout != null) { + mHintLayout = mSavedHintLayout. + replaceOrMake(mHint, mTextPaint, + hintWidth, alignment, mSpacingMult, mSpacingAdd, + hintBoring, mIncludePad, mEllipsize, + ellipsisWidth); + } else { + mHintLayout = BoringLayout.make(mHint, mTextPaint, + hintWidth, alignment, mSpacingMult, mSpacingAdd, + hintBoring, mIncludePad, mEllipsize, + ellipsisWidth); + } + } else if (shouldEllipsize) { + mHintLayout = new StaticLayout(mHint, + 0, mHint.length(), + mTextPaint, hintWidth, alignment, mSpacingMult, + mSpacingAdd, mIncludePad, mEllipsize, + ellipsisWidth); } else { mHintLayout = new StaticLayout(mHint, mTextPaint, hintWidth, alignment, mSpacingMult, mSpacingAdd, mIncludePad); } + } else if (shouldEllipsize) { + mHintLayout = new StaticLayout(mHint, + 0, mHint.length(), + mTextPaint, hintWidth, alignment, mSpacingMult, + mSpacingAdd, mIncludePad, mEllipsize, + ellipsisWidth); } else { mHintLayout = new StaticLayout(mHint, mTextPaint, hintWidth, alignment, mSpacingMult, mSpacingAdd, @@ -4895,8 +5019,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - private static final BoringLayout.Metrics UNKNOWN_BORING = - new BoringLayout.Metrics(); + private static final BoringLayout.Metrics UNKNOWN_BORING = new BoringLayout.Metrics(); @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -4923,8 +5046,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (des < 0) { - boring = BoringLayout.isBoring(mTransformed, mTextPaint, - mBoring); + boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring); if (boring != null) { mBoring = boring; } @@ -4934,8 +5056,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (boring == null || boring == UNKNOWN_BORING) { if (des < 0) { - des = (int) FloatMath.ceil(Layout. - getDesiredWidth(mTransformed, mTextPaint)); + des = (int) FloatMath.ceil(Layout.getDesiredWidth(mTransformed, mTextPaint)); } width = des; @@ -4953,13 +5074,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int hintDes = -1; int hintWidth; - if (mHintLayout != null) { + if (mHintLayout != null && mEllipsize == null) { hintDes = desired(mHintLayout); } if (hintDes < 0) { - hintBoring = BoringLayout.isBoring(mHint, mTextPaint, - mHintBoring); + hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mHintBoring); if (hintBoring != null) { mHintBoring = hintBoring; } @@ -4967,8 +5087,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (hintBoring == null || hintBoring == UNKNOWN_BORING) { if (hintDes < 0) { - hintDes = (int) FloatMath.ceil(Layout. - getDesiredWidth(mHint, mTextPaint)); + hintDes = (int) FloatMath.ceil( + Layout.getDesiredWidth(mHint, mTextPaint)); } hintWidth = hintDes; @@ -5014,20 +5134,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mLayout == null) { makeNewLayout(want, hintWant, boring, hintBoring, - width - getCompoundPaddingLeft() - getCompoundPaddingRight(), - false); + width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false); } else if ((mLayout.getWidth() != want) || (hintWidth != hintWant) || (mLayout.getEllipsizedWidth() != width - getCompoundPaddingLeft() - getCompoundPaddingRight())) { if (mHint == null && mEllipsize == null && want > mLayout.getWidth() && (mLayout instanceof BoringLayout || - (fromexisting && des >= 0 && des <= want))) { + (fromexisting && des >= 0 && des <= want))) { mLayout.increaseWidthTo(want); } else { makeNewLayout(want, hintWant, boring, hintBoring, - width - getCompoundPaddingLeft() - getCompoundPaddingRight(), - false); + width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false); } } else { // Width has not changed. @@ -5048,11 +5166,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - int unpaddedHeight = height - getCompoundPaddingTop() - - getCompoundPaddingBottom(); + int unpaddedHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom(); if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) { - unpaddedHeight = Math.min(unpaddedHeight, - mLayout.getLineTop(mMaximum)); + unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum)); } /* @@ -5071,8 +5187,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private int getDesiredHeight() { - return Math.max(getDesiredHeight(mLayout, true), - getDesiredHeight(mHintLayout, false)); + return Math.max( + getDesiredHeight(mLayout, true), + getDesiredHeight(mHintLayout, mEllipsize != null)); } private int getDesiredHeight(Layout layout, boolean cap) { @@ -5715,6 +5832,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void startMarquee() { + // Do not ellipsize EditText + if (mInput != null) return; + if (compressText(getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight())) { return; } @@ -6129,10 +6249,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private class ChangeWatcher implements TextWatcher, SpanWatcher { + + private CharSequence mBeforeText; + public void beforeTextChanged(CharSequence buffer, int start, int before, int after) { if (DEBUG_EXTRACT) Log.v(TAG, "beforeTextChanged start=" + start + " before=" + before + " after=" + after + ": " + buffer); + + if (AccessibilityManager.getInstance(mContext).isEnabled()) { + mBeforeText = buffer.toString(); + } + TextView.this.sendBeforeTextChanged(buffer, start, before, after); } @@ -6141,6 +6269,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (DEBUG_EXTRACT) Log.v(TAG, "onTextChanged start=" + start + " before=" + before + " after=" + after + ": " + buffer); TextView.this.handleTextChanged(buffer, start, before, after); + + if (AccessibilityManager.getInstance(mContext).isEnabled() && + (isFocused() || isSelected() && + isShown())) { + sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after); + mBeforeText = null; + } } public void afterTextChanged(Editable buffer) { @@ -6336,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); } } @@ -6525,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: @@ -6776,6 +6919,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + boolean isPassword = + (mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION)) == + (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD); + + if (!isPassword) { + CharSequence text = getText(); + if (TextUtils.isEmpty(text)) { + text = getHint(); + } + if (!TextUtils.isEmpty(text)) { + if (text.length() > AccessibilityEvent.MAX_TEXT_LENGTH) { + text = text.subSequence(0, AccessibilityEvent.MAX_TEXT_LENGTH + 1); + } + event.getText().add(text); + } + } else { + event.setPassword(isPassword); + } + return false; + } + + void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, + int fromIndex, int removedCount, int addedCount) { + AccessibilityEvent event = + AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + event.setFromIndex(fromIndex); + event.setRemovedCount(removedCount); + event.setAddedCount(addedCount); + event.setBeforeText(beforeText); + sendAccessibilityEventUnchecked(event); + } + + @Override protected void onCreateContextMenu(ContextMenu menu) { super.onCreateContextMenu(menu); boolean added = false; diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index ff74787..670692f 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -21,8 +21,8 @@ import android.app.ITransientNotification; import android.content.Context; import android.content.res.Resources; import android.graphics.PixelFormat; -import android.os.RemoteException; import android.os.Handler; +import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.view.Gravity; @@ -278,7 +278,7 @@ public class Toast { } tv.setText(s); } - + // ======================================================================================= // All the gunk below is the interaction with the Notification Service, which handles // the proper ordering of these system-wide. @@ -373,6 +373,7 @@ public class Toast { TAG, "REMOVE! " + mView + " in " + this); mWM.removeView(mView); } + mView = null; } } diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 6d3a2d3..20dd8a6 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -55,6 +55,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { private SurfaceHolder mSurfaceHolder = null; private MediaPlayer mMediaPlayer = null; private boolean mIsPrepared; + private boolean mIsPlaybackCompleted; private int mVideoWidth; private int mVideoHeight; private int mSurfaceWidth; @@ -260,7 +261,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mSeekWhenPrepared = 0; } if (mStartWhenPrepared) { - mMediaPlayer.start(); + start(); mStartWhenPrepared = false; if (mMediaController != null) { mMediaController.show(); @@ -281,7 +282,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mSeekWhenPrepared = 0; } if (mStartWhenPrepared) { - mMediaPlayer.start(); + start(); mStartWhenPrepared = false; } } @@ -291,6 +292,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { + mIsPlaybackCompleted = true; if (mMediaController != null) { mMediaController.hide(); } @@ -405,7 +407,9 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mMediaPlayer.seekTo(mSeekWhenPrepared); mSeekWhenPrepared = 0; } - mMediaPlayer.start(); + if (!mIsPlaybackCompleted) { + start(); + } if (mMediaController != null) { mMediaController.show(); } @@ -490,6 +494,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { } public void start() { + mIsPlaybackCompleted = false; if (mMediaPlayer != null && mIsPrepared) { mMediaPlayer.start(); mStartWhenPrepared = false; diff --git a/core/java/android/widget/ViewSwitcher.java b/core/java/android/widget/ViewSwitcher.java index f4f23a8..0dcaf95 100644 --- a/core/java/android/widget/ViewSwitcher.java +++ b/core/java/android/widget/ViewSwitcher.java @@ -16,8 +16,6 @@ package android.widget; -import java.util.Map; - import android.content.Context; import android.util.AttributeSet; import android.view.View; diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index d9fb78b..bae4dad 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -81,27 +81,27 @@ public class ZoomButtonsController implements View.OnTouchListener { private static final int ZOOM_CONTROLS_TOUCH_PADDING = 20; private int mTouchPaddingScaledSq; - private Context mContext; - private WindowManager mWindowManager; + private final Context mContext; + private final WindowManager mWindowManager; private boolean mAutoDismissControls = true; /** * The view that is being zoomed by this zoom controller. */ - private View mOwnerView; + private final View mOwnerView; /** * The location of the owner view on the screen. This is recalculated * each time the zoom controller is shown. */ - private int[] mOwnerViewRawLocation = new int[2]; + private final int[] mOwnerViewRawLocation = new int[2]; /** * The container that is added as a window. */ - private FrameLayout mContainer; + private final FrameLayout mContainer; private LayoutParams mContainerLayoutParams; - private int[] mContainerRawLocation = new int[2]; + private final int[] mContainerRawLocation = new int[2]; private ZoomControls mControls; @@ -113,7 +113,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * The {@link #mTouchTargetView}'s location in window, set on touch down. */ - private int[] mTouchTargetWindowLocation = new int[2]; + private final int[] mTouchTargetWindowLocation = new int[2]; /** * If the zoom controller is dismissed but the user is still in a touch @@ -128,8 +128,8 @@ public class ZoomButtonsController implements View.OnTouchListener { /** Whether the container has been added to the window manager. */ private boolean mIsVisible; - private Rect mTempRect = new Rect(); - private int[] mTempIntArray = new int[2]; + private final Rect mTempRect = new Rect(); + private final int[] mTempIntArray = new int[2]; private OnZoomListener mCallback; @@ -141,13 +141,13 @@ public class ZoomButtonsController implements View.OnTouchListener { */ private Runnable mPostedVisibleInitializer; - private IntentFilter mConfigurationChangedFilter = + private final IntentFilter mConfigurationChangedFilter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); /** * Needed to reposition the zoom controls after configuration changes. */ - private BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!mIsVisible) return; @@ -167,7 +167,7 @@ public class ZoomButtonsController implements View.OnTouchListener { */ private static final int MSG_POST_SET_VISIBLE = 4; - private Handler mHandler = new Handler() { + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -444,6 +444,9 @@ public class ZoomButtonsController implements View.OnTouchListener { } private void refreshPositioningVariables() { + // if the mOwnerView is detached from window then skip. + if (mOwnerView.getWindowToken() == null) return; + // Position the zoom controls on the bottom of the owner view. int ownerHeight = mOwnerView.getHeight(); int ownerWidth = mOwnerView.getWidth(); diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index e1ff2a5..4bac593 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -18,6 +18,8 @@ package com.android.internal.app; import com.android.internal.os.BatteryStatsImpl; +import android.telephony.SignalStrength; + interface IBatteryStats { byte[] getStatistics(); void noteStartWakelock(int uid, String name, int type); @@ -33,8 +35,9 @@ interface IBatteryStats { void noteUserActivity(int uid, int event); void notePhoneOn(); void notePhoneOff(); - void notePhoneSignalStrength(int asu); + void notePhoneSignalStrength(in SignalStrength signalStrength); void notePhoneDataConnectionState(int dataType, boolean hasData); + void 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 ce39768..af06965 100644 --- a/core/java/com/android/internal/backup/IBackupTransport.aidl +++ b/core/java/com/android/internal/backup/IBackupTransport.aidl @@ -16,6 +16,8 @@ package com.android.internal.backup; +import android.backup.RestoreSet; +import android.content.pm.PackageInfo; import android.os.ParcelFileDescriptor; /** {@hide} */ @@ -25,7 +27,7 @@ interface IBackupTransport { 1. set up the connection to the destination - set up encryption - for Google cloud, log in using the user's gaia credential or whatever - - for sd, spin off the backup transport and establish communication with it + - for adb, just set up the all-in-one destination file 2. send each app's backup transaction - parse the data file for key/value pointers etc - send key/blobsize set to the Google cloud, get back quota ok/rejected response @@ -36,34 +38,112 @@ interface IBackupTransport { - sd target streams raw data into encryption envelope then to sd? 3. shut down connection to destination - cloud: tear down connection etc - - sd: close the file and shut down the writer proxy + - adb: close the file */ /** - * 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. + * Ask the transport where, on local device storage, to keep backup state blobs. + * This is per-transport so that mock transports used for testing can coexist with + * "live" backup services without interfering with the live bookkeeping. The + * returned string should be a name that is expected to be unambiguous among all + * available backup transports; the name of the class implementing the transport + * is a good choice. * - * @return Zero on success; a nonzero error code on failure. + * @return A unique name, suitable for use as a file or directory name, that the + * Backup Manager could use to disambiguate state files associated with + * different backup transports. */ - int startSession(); + String transportDirName(); /** - * Send one application's data to the backup destination. + * Verify that this is a suitable time for a backup pass. This should return zero + * if a backup is reasonable right now, some positive value otherwise. This method + * will be called outside of the {@link #startSession}/{@link #endSession} pair. * - * @param packageName The identity of the application whose data is being backed up. + * <p>If this is not a suitable time for a backup, the transport should return a + * backoff delay, in milliseconds, after which the Backup Manager should try again. + * + * @return Zero if this is a suitable time for a backup pass, or a positive time delay + * in milliseconds to suggest deferring the backup pass for a while. + */ + long requestBackupTime(); + + /** + * 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. + * BackupService.doBackup() method. This may be a pipe rather than a file on + * persistent media, so it may not be seekable. + * @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 performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd); + + /** + * Erase the give application's data from the backup destination. This clears + * out the given package's data from the current backup set, making it as though + * the app had never yet been backed up. After this is called, {@link finishBackup} + * must be called to ensure that the operation is recorded successfully. + * + * @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 clearBackupData(in PackageInfo packageInfo); + + /** + * Finish sending application data to the backup destination. This must be + * called after {@link #performBackup} or {@link clearBackupData} to ensure that + * all data is sent. Only when this method returns true can a backup be assumed + * to have succeeded. + * + * @return false if errors occurred (the backup should be aborted and rescheduled), + * true if everything is OK. */ - int performBackup(String packageName, in ParcelFileDescriptor data); + boolean finishBackup(); /** - * Terminate the backup session, closing files, freeing memory, and cleaning up whatever - * other state the transport required. + * Get the set of backups currently available over this transport. * - * @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. + * @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(); + + /** + * 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}. + * @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}). + */ + boolean startRestore(long token, in PackageInfo[] packages); + + /** + * 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). + */ + String nextRestorePackage(); + + /** + * 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 new file mode 100644 index 0000000..2facce2 --- /dev/null +++ b/core/java/com/android/internal/backup/LocalTransport.java @@ -0,0 +1,200 @@ +package com.android.internal.backup; + +import android.backup.BackupDataInput; +import android.backup.BackupDataOutput; +import android.backup.RestoreSet; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import org.bouncycastle.util.encoders.Base64; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +/** + * Backup transport for stashing stuff into a known location on disk, and + * later restoring from there. For testing only. + */ + +public class LocalTransport extends IBackupTransport.Stub { + private static final String TAG = "LocalTransport"; + private static final boolean DEBUG = true; + + private static final String TRANSPORT_DIR_NAME + = "com.android.internal.backup.LocalTransport"; + + private Context mContext; + private PackageManager mPackageManager; + private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup"); + private PackageInfo[] mRestorePackages = null; + private int mRestorePackage = -1; // Index into mRestorePackages + + + public LocalTransport(Context context) { + if (DEBUG) Log.v(TAG, "Transport constructed"); + mContext = context; + mPackageManager = context.getPackageManager(); + } + + + public String transportDirName() throws RemoteException { + return TRANSPORT_DIR_NAME; + } + + public long requestBackupTime() throws RemoteException { + // any time is a good time for local backup + return 0; + } + + public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) + throws RemoteException { + if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName); + + File packageDir = new File(mDataDir, packageInfo.packageName); + packageDir.mkdirs(); + + // Each 'record' in the restore set is kept in its own file, named by + // the record key. Wind through the data file, extracting individual + // record operations and building a set of all the updates to apply + // in this update. + BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor()); + try { + int bufSize = 512; + byte[] buf = new byte[bufSize]; + while (changeSet.readNextHeader()) { + String key = changeSet.getKey(); + String base64Key = new String(Base64.encode(key.getBytes())); + File entityFile = new File(packageDir, base64Key); + + int dataSize = changeSet.getDataSize(); + + if (DEBUG) Log.v(TAG, "Got change set key=" + key + " size=" + dataSize + + " key64=" + base64Key); + + if (dataSize >= 0) { + FileOutputStream entity = new FileOutputStream(entityFile); + + if (dataSize > bufSize) { + bufSize = dataSize; + buf = new byte[bufSize]; + } + changeSet.readEntityData(buf, 0, dataSize); + if (DEBUG) Log.v(TAG, " data size " + dataSize); + + try { + entity.write(buf, 0, dataSize); + } catch (IOException e) { + Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath()); + return false; + } finally { + entity.close(); + } + } else { + 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); + return false; + } + } + + public boolean clearBackupData(PackageInfo packageInfo) { + if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName); + + File packageDir = new File(mDataDir, packageInfo.packageName); + for (File f : packageDir.listFiles()) { + f.delete(); + } + packageDir.delete(); + return true; + } + + public boolean finishBackup() throws RemoteException { + if (DEBUG) Log.v(TAG, "finishBackup()"); + return true; + } + + // Restore handling + public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException { + // one hardcoded restore set + RestoreSet set = new RestoreSet("Local disk image", "flash", 0); + RestoreSet[] array = { set }; + return array; + } + + public boolean startRestore(long token, PackageInfo[] packages) { + if (DEBUG) Log.v(TAG, "start restore " + token); + mRestorePackages = packages; + mRestorePackage = -1; + return true; + } + + 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; + } + } + + if (DEBUG) Log.v(TAG, " no more packages to restore"); + return ""; + } + + 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(); + 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(); + } + } + return true; + } catch (IOException e) { + Log.e(TAG, "Unable to read backup records", e); + return false; + } + } + + public void finishRestore() { + if (DEBUG) Log.v(TAG, "finishRestore()"); + } +} diff --git a/core/java/com/android/internal/backup/SystemBackupAgent.java b/core/java/com/android/internal/backup/SystemBackupAgent.java new file mode 100644 index 0000000..6b396d7 --- /dev/null +++ b/core/java/com/android/internal/backup/SystemBackupAgent.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.backup; + +import android.backup.AbsoluteFileBackupHelper; +import android.backup.BackupHelperAgent; + +/** + * Backup agent for various system-managed data + */ +public class SystemBackupAgent extends BackupHelperAgent { + // the set of files that we back up whole, as absolute paths + String[] mFiles = { + /* WallpaperService.WALLPAPER_FILE */ + "/data/data/com.android.settings/files/wallpaper", + }; + + public void onCreate() { + addHelper("system_files", new AbsoluteFileBackupHelper(this, mFiles)); + } +} diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index e8356a2..a03802d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -23,23 +23,24 @@ import android.os.ParcelFormatException; import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; +import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.SparseArray; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.Set; /** * All information we are collecting about things that can happen that impact @@ -54,7 +55,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 34; + private static final int VERSION = 39; private final File mFile; private final File mBackupFile; @@ -95,7 +96,7 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mScreenOn; StopwatchTimer mScreenOnTimer; - + int mScreenBrightnessBin = -1; final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -104,6 +105,12 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mPhoneOn; StopwatchTimer mPhoneOnTimer; + boolean mAudioOn; + StopwatchTimer mAudioOnTimer; + + boolean mVideoOn; + StopwatchTimer mVideoOnTimer; + int mPhoneSignalStrengthBin = -1; final StopwatchTimer[] mPhoneSignalStrengthsTimer = new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS]; @@ -132,18 +139,27 @@ public final class BatteryStatsImpl extends BatteryStats { long mTrackBatteryUptimeStart; long mTrackBatteryPastRealtime; long mTrackBatteryRealtimeStart; - + long mUnpluggedBatteryUptime; long mUnpluggedBatteryRealtime; - + /* * These keep track of battery levels (1-100) at the last plug event and the last unplug event. */ int mDischargeStartLevel; int mDischargeCurrentLevel; - + long mLastWriteTime = 0; // Milliseconds - + + // Mobile data transferred while on battery + private long[] mMobileDataTx = new long[4]; + private long[] mMobileDataRx = new long[4]; + private long[] mTotalDataTx = new long[4]; + private long[] mTotalDataRx = new long[4]; + + private long mRadioDataUptime; + private long mRadioDataStart; + /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ @@ -175,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; @@ -319,6 +337,13 @@ public final class BatteryStatsImpl extends BatteryStats { */ long mUnpluggedTime; + /** + * Constructs from a parcel. + * @param type + * @param unpluggables + * @param powerType + * @param in + */ Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { mType = type; @@ -631,7 +656,6 @@ public final class BatteryStatsImpl extends BatteryStats { * was actually held for an interesting duration. */ long mAcquireTime; - StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool, ArrayList<Unpluggable> unpluggables, Parcel in) { @@ -692,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) { @@ -882,7 +910,40 @@ public final class BatteryStatsImpl extends BatteryStats { } return kwlt; } - + + private void doDataPlug(long[] dataTransfer, long currentBytes) { + dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED]; + dataTransfer[STATS_UNPLUGGED] = -1; + } + + private void doDataUnplug(long[] dataTransfer, long currentBytes) { + dataTransfer[STATS_UNPLUGGED] = currentBytes; + } + + private long getCurrentRadioDataUptimeMs() { + try { + File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); + if (!awakeTimeFile.exists()) return 0; + BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); + String line = br.readLine(); + br.close(); + return Long.parseLong(line); + } catch (NumberFormatException nfe) { + // Nothing + } catch (IOException ioe) { + // Nothing + } + return 0; + } + + public long getRadioDataUptimeMs() { + if (mRadioDataStart == -1) { + return mRadioDataUptime; + } else { + return getCurrentRadioDataUptimeMs() - mRadioDataStart; + } + } + public void doUnplug(long batteryUptime, long batteryRealtime) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { Uid u = mUidStats.valueAt(iu); @@ -894,8 +955,16 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i = mUnpluggables.size() - 1; i >= 0; i--) { mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); } + // Track total mobile data + doDataUnplug(mMobileDataRx, NetStat.getMobileRxBytes()); + doDataUnplug(mMobileDataTx, NetStat.getMobileTxBytes()); + doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes()); + doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes()); + // Track radio awake time + mRadioDataStart = getCurrentRadioDataUptimeMs(); + mRadioDataUptime = 0; } - + public void doPlug(long batteryUptime, long batteryRealtime) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { Uid u = mUidStats.valueAt(iu); @@ -911,16 +980,23 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i = mUnpluggables.size() - 1; i >= 0; i--) { mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); } + doDataPlug(mMobileDataRx, NetStat.getMobileRxBytes()); + doDataPlug(mMobileDataTx, NetStat.getMobileTxBytes()); + doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes()); + doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes()); + // Track radio awake time + mRadioDataUptime = getRadioDataUptimeMs(); + mRadioDataStart = -1; } - + 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() { if (!mScreenOn) { mScreenOn = true; @@ -962,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() { @@ -981,15 +1054,43 @@ public final class BatteryStatsImpl extends BatteryStats { mPhoneOnTimer.stopRunningLocked(this); } } - - public void notePhoneSignalStrengthLocked(int asu) { + + 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; - if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; - else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; - else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; - else bin = SIGNAL_STRENGTH_POOR; + + if (!signalStrength.isGsm()) { + int dBm = signalStrength.getCdmaDbm(); + if (dBm >= -75) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + else if (dBm >= -85) bin = SIGNAL_STRENGTH_GREAT; + else if (dBm >= -95) bin = SIGNAL_STRENGTH_GOOD; + else if (dBm >= -100) bin = SIGNAL_STRENGTH_MODERATE; + else bin = SIGNAL_STRENGTH_POOR; + } else { + int asu = signalStrength.getGsmSignalStrength(); + if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT; + else if (asu >= 8) bin = SIGNAL_STRENGTH_GOOD; + else if (asu >= 4) bin = SIGNAL_STRENGTH_MODERATE; + else bin = SIGNAL_STRENGTH_POOR; + } if (mPhoneSignalStrengthBin != bin) { if (mPhoneSignalStrengthBin >= 0) { mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this); @@ -1017,6 +1118,7 @@ public final class BatteryStatsImpl extends BatteryStats { break; } } + if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); if (mPhoneDataConnectionType != bin) { if (mPhoneDataConnectionType >= 0) { mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); @@ -1033,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(); } } @@ -1052,14 +1148,43 @@ 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; } } + + public void noteAudioOnLocked(int uid) { + if (!mAudioOn) { + mAudioOn = true; + mAudioOnTimer.startRunningLocked(this); + } + getUidStatsLocked(uid).noteAudioTurnedOnLocked(); + } + public void noteAudioOffLocked(int uid) { + if (mAudioOn) { + mAudioOn = false; + mAudioOnTimer.stopRunningLocked(this); + } + getUidStatsLocked(uid).noteAudioTurnedOffLocked(); + } + + public void noteVideoOnLocked(int uid) { + if (!mVideoOn) { + mVideoOn = true; + mVideoOnTimer.startRunningLocked(this); + } + getUidStatsLocked(uid).noteVideoTurnedOnLocked(); + } + + public void noteVideoOffLocked(int uid) { + if (mVideoOn) { + mVideoOn = false; + mVideoOnTimer.stopRunningLocked(this); + } + getUidStatsLocked(uid).noteVideoTurnedOffLocked(); + } + public void noteWifiRunningLocked() { if (!mWifiRunning) { mWifiRunning = true; @@ -1089,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) { @@ -1139,7 +1246,7 @@ public final class BatteryStatsImpl extends BatteryStats { return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( batteryRealtime, which); } - + @Override public int getInputEventCount(int which) { return mInputEventCounter.getCountLocked(which); } @@ -1147,7 +1254,7 @@ public final class BatteryStatsImpl extends BatteryStats { @Override public long getPhoneOnTime(long batteryRealtime, int which) { return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); } - + @Override public long getPhoneSignalStrengthTime(int strengthBin, long batteryRealtime, int which) { return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( @@ -1214,9 +1321,15 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mScanWifiLockOut; StopwatchTimer mScanWifiLockTimer; - + boolean mWifiMulticastEnabled; StopwatchTimer mWifiMulticastTimer; + + boolean mAudioTurnedOn; + StopwatchTimer mAudioTurnedOnTimer; + + boolean mVideoTurnedOn; + StopwatchTimer mVideoTurnedOnTimer; Counter[] mUserActivityCounters; @@ -1247,6 +1360,8 @@ public final class BatteryStatsImpl extends BatteryStats { mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, null, mUnpluggables); + mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); + mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); } @Override @@ -1268,11 +1383,13 @@ public final class BatteryStatsImpl extends BatteryStats { public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { return mPackageStats; } - + + @Override public int getUid() { return mUid; } - + + @Override public long getTcpBytesReceived(int which) { if (which == STATS_LAST) { return mLoadedTcpBytesReceived; @@ -1291,7 +1408,8 @@ public final class BatteryStatsImpl extends BatteryStats { return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0 ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0); } - + + @Override public long getTcpBytesSent(int which) { if (which == STATS_LAST) { return mLoadedTcpBytesSent; @@ -1331,6 +1449,38 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public void noteVideoTurnedOnLocked() { + if (!mVideoTurnedOn) { + mVideoTurnedOn = true; + mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteVideoTurnedOffLocked() { + if (mVideoTurnedOn) { + mVideoTurnedOn = false; + mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteAudioTurnedOnLocked() { + if (!mAudioTurnedOn) { + mAudioTurnedOn = true; + mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteAudioTurnedOffLocked() { + if (mAudioTurnedOn) { + mAudioTurnedOn = false; + mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + + @Override public void noteFullWifiLockReleasedLocked() { if (mFullWifiLockOut) { mFullWifiLockOut = false; @@ -1374,7 +1524,17 @@ public final class BatteryStatsImpl extends BatteryStats { public long getWifiTurnedOnTime(long batteryRealtime, int which) { return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); } - + + @Override + public long getAudioTurnedOnTime(long batteryRealtime, int which) { + return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); + } + + @Override + public long getVideoTurnedOnTime(long batteryRealtime, int which) { + return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); + } + @Override public long getFullWifiLockTime(long batteryRealtime, int which) { return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); @@ -1425,7 +1585,7 @@ public final class BatteryStatsImpl extends BatteryStats { return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); } - + void writeToParcelLocked(Parcel out, long batteryRealtime) { out.writeInt(mWakelockStats.size()); for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { @@ -1463,6 +1623,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mTcpBytesSentAtLastUnplug); mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); mFullWifiLockTimer.writeToParcel(out, batteryRealtime); + mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); + mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); mScanWifiLockTimer.writeToParcel(out, batteryRealtime); mWifiMulticastTimer.writeToParcel(out, batteryRealtime); if (mUserActivityCounters == null) { @@ -1522,6 +1684,10 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in); mFullWifiLockOut = false; mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); + mAudioTurnedOn = false; + mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in); + mVideoTurnedOn = false; + mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in); mScanWifiLockOut = false; mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); mWifiMulticastEnabled = false; @@ -1632,7 +1798,8 @@ public final class BatteryStatsImpl extends BatteryStats { public Timer getSensorTime() { return mTimer; } - + + @Override public int getHandle() { return mHandle; } @@ -1658,6 +1825,11 @@ public final class BatteryStatsImpl extends BatteryStats { int mStarts; /** + * Amount of time the process was running in the foreground. + */ + long mForegroundTime; + + /** * The amount of user time loaded from a previous save. */ long mLoadedUserTime; @@ -1673,6 +1845,11 @@ public final class BatteryStatsImpl extends BatteryStats { int mLoadedStarts; /** + * The amount of foreground time loaded from a previous save. + */ + long mLoadedForegroundTime; + + /** * The amount of user time loaded from the previous run. */ long mLastUserTime; @@ -1688,6 +1865,11 @@ public final class BatteryStatsImpl extends BatteryStats { int mLastStarts; /** + * The amount of foreground time loaded from the previous run + */ + long mLastForegroundTime; + + /** * The amount of user time when last unplugged. */ long mUnpluggedUserTime; @@ -1702,6 +1884,11 @@ public final class BatteryStatsImpl extends BatteryStats { */ int mUnpluggedStarts; + /** + * The amount of foreground time since unplugged. + */ + long mUnpluggedForegroundTime; + Proc() { mUnpluggables.add(this); } @@ -1710,6 +1897,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUnpluggedUserTime = mUserTime; mUnpluggedSystemTime = mSystemTime; mUnpluggedStarts = mStarts; + mUnpluggedForegroundTime = mForegroundTime; } public void plug(long batteryUptime, long batteryRealtime) { @@ -1721,30 +1909,38 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mUserTime); out.writeLong(mSystemTime); + out.writeLong(mForegroundTime); out.writeInt(mStarts); out.writeLong(mLoadedUserTime); out.writeLong(mLoadedSystemTime); + out.writeLong(mLoadedForegroundTime); out.writeInt(mLoadedStarts); out.writeLong(mLastUserTime); out.writeLong(mLastSystemTime); + out.writeLong(mLastForegroundTime); out.writeInt(mLastStarts); out.writeLong(mUnpluggedUserTime); out.writeLong(mUnpluggedSystemTime); + out.writeLong(mUnpluggedForegroundTime); out.writeInt(mUnpluggedStarts); } void readFromParcelLocked(Parcel in) { mUserTime = in.readLong(); mSystemTime = in.readLong(); + mForegroundTime = in.readLong(); mStarts = in.readInt(); mLoadedUserTime = in.readLong(); mLoadedSystemTime = in.readLong(); + mLoadedForegroundTime = in.readLong(); mLoadedStarts = in.readInt(); mLastUserTime = in.readLong(); mLastSystemTime = in.readLong(); + mLastForegroundTime = in.readLong(); mLastStarts = in.readInt(); mUnpluggedUserTime = in.readLong(); mUnpluggedSystemTime = in.readLong(); + mUnpluggedForegroundTime = in.readLong(); mUnpluggedStarts = in.readInt(); } @@ -1757,6 +1953,10 @@ public final class BatteryStatsImpl extends BatteryStats { mSystemTime += stime; } + public void addForegroundTimeLocked(long ttime) { + mForegroundTime += ttime; + } + public void incStartsLocked() { mStarts++; } @@ -1794,6 +1994,22 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public long getForegroundTime(int which) { + long val; + if (which == STATS_LAST) { + val = mLastForegroundTime; + } else { + val = mForegroundTime; + if (which == STATS_CURRENT) { + val -= mLoadedForegroundTime; + } else if (which == STATS_UNPLUGGED) { + val -= mUnpluggedForegroundTime; + } + } + return val; + } + + @Override public int getStarts(int which) { int val; if (which == STATS_LAST) { @@ -2315,7 +2531,7 @@ public final class BatteryStatsImpl extends BatteryStats { StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); if (t != null) { t.stopRunningLocked(BatteryStatsImpl.this); - } + } } public BatteryStatsImpl getBatteryStats() { @@ -2526,7 +2742,44 @@ public final class BatteryStatsImpl extends BatteryStats { public long getBatteryRealtime(long curTime) { return getBatteryRealtimeLocked(curTime); } - + + private long getTcpBytes(long current, long[] dataBytes, int which) { + if (which == STATS_LAST) { + return dataBytes[STATS_LAST]; + } else { + if (which == STATS_UNPLUGGED) { + if (dataBytes[STATS_UNPLUGGED] < 0) { + return dataBytes[STATS_LAST]; + } else { + return current - dataBytes[STATS_UNPLUGGED]; + } + } else if (which == STATS_TOTAL) { + return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL]; + } + return current - dataBytes[STATS_CURRENT]; + } + } + + /** Only STATS_UNPLUGGED works properly */ + public long getMobileTcpBytesSent(int which) { + return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getMobileTcpBytesReceived(int which) { + return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getTotalTcpBytesSent(int which) { + return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getTotalTcpBytesReceived(int which) { + return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which); + } + @Override public int getDischargeStartLevel() { synchronized(this) { @@ -2567,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. @@ -2578,6 +2831,24 @@ 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 pid) { + int uid; + if (mUidCache.containsKey(name)) { + uid = mUidCache.get(name); + } else { + uid = Process.getUidForPid(pid); + mUidCache.put(name, uid); + } + Uid u = getUidStatsLocked(uid); + return u.getProcessStatsLocked(name); + } + + /** * Retrieve the statistics object for a particular process, creating * if needed. */ @@ -2752,6 +3023,10 @@ public final class BatteryStatsImpl extends BatteryStats { u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in); u.mFullWifiLockOut = false; u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); + u.mAudioTurnedOn = false; + u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in); + u.mVideoTurnedOn = false; + u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in); u.mScanWifiLockOut = false; u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); u.mWifiMulticastEnabled = false; @@ -2888,6 +3163,8 @@ public final class BatteryStatsImpl extends BatteryStats { u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); @@ -3046,11 +3323,24 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeCurrentLevel = in.readInt(); mLastWriteTime = in.readLong(); + mMobileDataRx[STATS_LAST] = in.readLong(); + mMobileDataRx[STATS_UNPLUGGED] = -1; + mMobileDataTx[STATS_LAST] = in.readLong(); + mMobileDataTx[STATS_UNPLUGGED] = -1; + mTotalDataRx[STATS_LAST] = in.readLong(); + mTotalDataRx[STATS_UNPLUGGED] = -1; + mTotalDataTx[STATS_LAST] = in.readLong(); + mTotalDataTx[STATS_UNPLUGGED] = -1; + + mRadioDataUptime = in.readLong(); + mRadioDataStart = -1; + mKernelWakelockStats.clear(); int NKW = in.readInt(); for (int ikw = 0; ikw < NKW; ikw++) { if (in.readInt() != 0) { String wakelockName = in.readString(); + in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); mKernelWakelockStats.put(wakelockName, kwlt); } @@ -3119,6 +3409,14 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(mDischargeCurrentLevel); out.writeLong(mLastWriteTime); + out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED)); + out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED)); + out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED)); + out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); + + // Write radio uptime for data + out.writeLong(getRadioDataUptimeMs()); + out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { SamplingTimer kwlt = ent.getValue(); diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java new file mode 100644 index 0000000..4a8d8b1 --- /dev/null +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + + +import android.content.Context; +import android.content.res.XmlResourceParser; + +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Reports power consumption values for various device activities. Reads values from an XML file. + * Customize the XML file for different devices. + * [hidden] + */ +public class PowerProfile { + + /** + * No power consumption, or accounted for elsewhere. + */ + public static final String POWER_NONE = "none"; + + /** + * Power consumption when CPU is in power collapse mode. + */ + public static final String POWER_CPU_IDLE = "cpu.idle"; + + /** + * Power consumption when CPU is running at normal speed. + */ + public static final String POWER_CPU_NORMAL = "cpu.normal"; + + /** + * Power consumption when CPU is running at full speed. + */ + public static final String POWER_CPU_FULL = "cpu.full"; + + /** + * Power consumption when WiFi driver is scanning for networks. + */ + public static final String POWER_WIFI_SCAN = "wifi.scan"; + + /** + * Power consumption when WiFi driver is on. + */ + public static final String POWER_WIFI_ON = "wifi.on"; + + /** + * Power consumption when WiFi driver is transmitting/receiving. + */ + public static final String POWER_WIFI_ACTIVE = "wifi.active"; + + /** + * Power consumption when GPS is on. + */ + public static final String POWER_GPS_ON = "gps.on"; + + /** + * Power consumption when Bluetooth driver is on. + */ + public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; + + /** + * Power consumption when Bluetooth driver is transmitting/receiving. + */ + public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; + + /** + * Power consumption when screen is on, not including the backlight power. + */ + public static final String POWER_SCREEN_ON = "screen.on"; + + /** + * Power consumption when cell radio is on but not on a call. + */ + public static final String POWER_RADIO_ON = "radio.on"; + + /** + * Power consumption when talking on the phone. + */ + public static final String POWER_RADIO_ACTIVE = "radio.active"; + + /** + * Power consumption at full backlight brightness. If the backlight is at + * 50% brightness, then this should be multiplied by 0.5 + */ + public static final String POWER_SCREEN_FULL = "screen.full"; + + /** + * Power consumed by the audio hardware when playing back audio content. This is in addition + * to the CPU power, probably due to a DSP and / or amplifier. + */ + public static final String POWER_AUDIO = "dsp.audio"; + + /** + * Power consumed by any media hardware when playing back video content. This is in addition + * to the CPU power, probably due to a DSP. + */ + public static final String POWER_VIDEO = "dsp.video"; + + static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>(); + + private static final String TAG_DEVICE = "device"; + private static final String TAG_ITEM = "item"; + private static final String TAG_ARRAY = "array"; + private static final String TAG_ARRAYITEM = "value"; + private static final String ATTR_NAME = "name"; + + public PowerProfile(Context context) { + // Read the XML file for the given profile (normally only one per + // device) + if (sPowerMap.size() == 0) { + readPowerValuesFromXml(context); + } + } + + private void readPowerValuesFromXml(Context context) { + int id = com.android.internal.R.xml.power_profile; + XmlResourceParser parser = context.getResources().getXml(id); + boolean parsingArray = false; + ArrayList<Double> array = new ArrayList<Double>(); + String arrayName = null; + + try { + XmlUtils.beginDocument(parser, TAG_DEVICE); + + while (true) { + XmlUtils.nextElement(parser); + + String element = parser.getName(); + if (element == null) break; + + if (parsingArray && !element.equals(TAG_ARRAYITEM)) { + // Finish array + sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); + parsingArray = false; + } + if (element.equals(TAG_ARRAY)) { + parsingArray = true; + array.clear(); + arrayName = parser.getAttributeValue(null, ATTR_NAME); + } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { + String name = null; + if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); + if (parser.next() == XmlPullParser.TEXT) { + String power = parser.getText(); + double value = 0; + try { + value = Double.valueOf(power); + } catch (NumberFormatException nfe) { + } + if (element.equals(TAG_ITEM)) { + sPowerMap.put(name, value); + } else if (parsingArray) { + array.add(value); + } + } + } + } + if (parsingArray) { + sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); + } + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + parser.close(); + } + } + + /** + * Returns the average current in mA consumed by the subsystem + * @param type the subsystem type + * @return the average current in milliAmps. + */ + public double getAveragePower(String type) { + if (sPowerMap.containsKey(type)) { + Object data = sPowerMap.get(type); + if (data instanceof Double[]) { + return ((Double[])data)[0]; + } else { + return (Double) sPowerMap.get(type); + } + } else { + return 0; + } + } + + /** + * Returns the average current in mA consumed by the subsystem for the given level. + * @param type the subsystem type + * @param level the level of power at which the subsystem is running. For instance, the + * signal strength of the cell network between 0 and 4 (if there are 4 bars max.). + * If there is no data for multiple levels, the level is ignored. + * @return the average current in milliAmps. + */ + 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 && level >= 0) { + return values[level]; + } else if (level < 0) { + return 0; + } else { + return values[values.length - 1]; + } + } else { + return (Double) data; + } + } else { + return 0; + } + } +} diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index ac8b589..f67a235 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -467,7 +467,7 @@ public class ZygoteInit { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003", - "--capabilities=121715744,121715744", + "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java index 4757919..86f74f3 100644 --- a/core/java/com/android/internal/util/BitwiseInputStream.java +++ b/core/java/com/android/internal/util/BitwiseInputStream.java @@ -65,30 +65,31 @@ public class BitwiseInputStream { /** * Read some data and increment the current position. * - * @param bits the amount of data to read (gte 0, lte 8) + * The 8-bit limit on access to bitwise streams is intentional to + * avoid endianness issues. * + * @param bits the amount of data to read (gte 0, lte 8) * @return byte of read data (possibly partially filled, from lsb) */ - public byte read(int bits) throws AccessException { + public int read(int bits) throws AccessException { int index = mPos >>> 3; int offset = 16 - (mPos & 0x07) - bits; // &7==%8 if ((bits < 0) || (bits > 8) || ((mPos + bits) > mEnd)) { throw new AccessException("illegal read " + "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")"); } - int data = (mBuf[index] & 0x00FF) << 8; - if (offset < 8) data |= (mBuf[index + 1] & 0xFF); + int data = (mBuf[index] & 0xFF) << 8; + if (offset < 8) data |= mBuf[index + 1] & 0xFF; data >>>= offset; data &= (-1 >>> (32 - bits)); mPos += bits; - return (byte)data; + return data; } /** * Read data in bulk into a byte array and increment the current position. * * @param bits the amount of data to read - * * @return newly allocated byte array of read data */ public byte[] readByteArray(int bits) throws AccessException { diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java index 1b974ce..70c0be8 100644 --- a/core/java/com/android/internal/util/BitwiseOutputStream.java +++ b/core/java/com/android/internal/util/BitwiseOutputStream.java @@ -82,6 +82,9 @@ public class BitwiseOutputStream { /** * Write some data and increment the current position. * + * The 8-bit limit on access to bitwise streams is intentional to + * avoid endianness issues. + * * @param bits the amount of data to write (gte 0, lte 8) * @param data to write, will be masked to expose only bits param from lsb */ @@ -95,8 +98,8 @@ public class BitwiseOutputStream { int offset = 16 - (mPos & 0x07) - bits; // &7==%8 data <<= offset; mPos += bits; - mBuf[index] |= (data >>> 8); - if (offset < 8) mBuf[index + 1] |= (data & 0x00FF); + mBuf[index] |= data >>> 8; + if (offset < 8) mBuf[index + 1] |= data & 0xFF; } /** diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java index 871c925..922f5be 100644 --- a/core/java/com/google/android/net/GoogleHttpClient.java +++ b/core/java/com/google/android/net/GoogleHttpClient.java @@ -37,6 +37,10 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.LayeredSocketFactory; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.scheme.SocketFactory; import org.apache.http.impl.client.EntityEnclosingRequestWrapper; import org.apache.http.impl.client.RequestWrapper; import org.apache.http.params.HttpParams; @@ -44,6 +48,8 @@ import org.apache.http.protocol.HttpContext; import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache; import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; @@ -66,25 +72,22 @@ public class GoogleHttpClient implements HttpClient { private final AndroidHttpClient mClient; private final ContentResolver mResolver; - private final String mUserAgent; + private final String mAppName, mUserAgent; + private final ThreadLocal<Boolean> mConnectionAllocated = new ThreadLocal<Boolean>(); /** - * Create an HTTP client. Normally one client is shared throughout an app. - * @param resolver to use for accessing URL rewriting rules. - * @param userAgent to report in your HTTP requests. - * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)} + * Create an HTTP client without SSL session persistence. + * @deprecated Use {@link #GoogleHttpClient(android.content.Context, String, boolean)} */ public GoogleHttpClient(ContentResolver resolver, String userAgent) { mClient = AndroidHttpClient.newInstance(userAgent); mResolver = resolver; - mUserAgent = userAgent; + mUserAgent = mAppName = userAgent; } /** - * GoogleHttpClient(Context, String, boolean) - without SSL session - * persistence. - * - * @deprecated use Context instead of ContentResolver. + * Create an HTTP client without SSL session persistence. + * @deprecated Use {@link #GoogleHttpClient(android.content.Context, String, boolean)} */ public GoogleHttpClient(ContentResolver resolver, String appAndVersion, boolean gzipCapable) { @@ -111,21 +114,72 @@ public class GoogleHttpClient implements HttpClient { * headers. Needed because Google servers require gzip in the User-Agent * in order to return gzip'd content. */ - public GoogleHttpClient(Context context, String appAndVersion, - boolean gzipCapable) { - this(context.getContentResolver(), SSLClientSessionCacheFactory.getCache(context), + public GoogleHttpClient(Context context, String appAndVersion, boolean gzipCapable) { + this(context.getContentResolver(), + SSLClientSessionCacheFactory.getCache(context), appAndVersion, gzipCapable); } - private GoogleHttpClient(ContentResolver resolver, SSLClientSessionCache cache, + private GoogleHttpClient(ContentResolver resolver, + SSLClientSessionCache cache, String appAndVersion, boolean gzipCapable) { String userAgent = appAndVersion + " (" + Build.DEVICE + " " + Build.ID + ")"; if (gzipCapable) { userAgent = userAgent + "; gzip"; } + mClient = AndroidHttpClient.newInstance(userAgent, cache); mResolver = resolver; + mAppName = appAndVersion; mUserAgent = userAgent; + + // Wrap all the socket factories with the appropriate wrapper. (Apache + // HTTP, curse its black and stupid heart, inspects the SocketFactory to + // see if it's a LayeredSocketFactory, so we need two wrapper classes.) + SchemeRegistry registry = getConnectionManager().getSchemeRegistry(); + for (String name : registry.getSchemeNames()) { + Scheme scheme = registry.unregister(name); + SocketFactory sf = scheme.getSocketFactory(); + if (sf instanceof LayeredSocketFactory) { + sf = new WrappedLayeredSocketFactory((LayeredSocketFactory) sf); + } else { + sf = new WrappedSocketFactory(sf); + } + registry.register(new Scheme(name, sf, scheme.getDefaultPort())); + } + } + + /** + * Delegating wrapper for SocketFactory records when sockets are connected. + * We use this to know whether a connection was created vs reused, to + * gather per-app statistics about connection reuse rates. + * (Note, we record only *connection*, not *creation* of sockets -- + * what we care about is the network overhead of an actual TCP connect.) + */ + private class WrappedSocketFactory implements SocketFactory { + private SocketFactory mDelegate; + private WrappedSocketFactory(SocketFactory delegate) { mDelegate = delegate; } + public final Socket createSocket() throws IOException { return mDelegate.createSocket(); } + public final boolean isSecure(Socket s) { return mDelegate.isSecure(s); } + + public final Socket connectSocket( + Socket s, String h, int p, + InetAddress la, int lp, HttpParams params) throws IOException { + mConnectionAllocated.set(Boolean.TRUE); + return mDelegate.connectSocket(s, h, p, la, lp, params); + } + } + + /** Like WrappedSocketFactory, but for the LayeredSocketFactory subclass. */ + private class WrappedLayeredSocketFactory + extends WrappedSocketFactory implements LayeredSocketFactory { + private LayeredSocketFactory mDelegate; + private WrappedLayeredSocketFactory(LayeredSocketFactory sf) { super(sf); mDelegate = sf; } + + public final Socket createSocket(Socket s, String host, int port, boolean autoClose) + throws IOException { + return mDelegate.createSocket(s, host, port, autoClose); + } } /** @@ -140,24 +194,21 @@ public class GoogleHttpClient implements HttpClient { public HttpResponse executeWithoutRewriting( HttpUriRequest request, HttpContext context) throws IOException { - String code = "Error"; + int code = -1; long start = SystemClock.elapsedRealtime(); try { HttpResponse response; - // TODO: if we're logging network stats, and if the apache library is configured - // to follow redirects, count each redirect as an additional round trip. + mConnectionAllocated.set(null); - // see if we're logging network stats. - boolean logNetworkStats = NetworkStatsEntity.shouldLogNetworkStats(); + if (NetworkStatsEntity.shouldLogNetworkStats()) { + // TODO: if we're logging network stats, and if the apache library is configured + // to follow redirects, count each redirect as an additional round trip. - if (logNetworkStats) { int uid = android.os.Process.myUid(); long startTx = NetStat.getUidTxBytes(uid); long startRx = NetStat.getUidRxBytes(uid); response = mClient.execute(request, context); - code = Integer.toString(response.getStatusLine().getStatusCode()); - HttpEntity origEntity = response == null ? null : response.getEntity(); if (origEntity != null) { // yeah, we compute the same thing below. we do need to compute this here @@ -165,30 +216,39 @@ public class GoogleHttpClient implements HttpClient { long now = SystemClock.elapsedRealtime(); long elapsed = now - start; NetworkStatsEntity entity = new NetworkStatsEntity(origEntity, - mUserAgent, uid, startTx, startRx, + mAppName, uid, startTx, startRx, elapsed /* response latency */, now /* processing start time */); response.setEntity(entity); } } else { response = mClient.execute(request, context); - code = Integer.toString(response.getStatusLine().getStatusCode()); } + code = response.getStatusLine().getStatusCode(); return response; - } catch (IOException e) { - code = "IOException"; - throw e; } finally { // Record some statistics to the checkin service about the outcome. // Note that this is only describing execute(), not body download. + // We assume the database writes are much faster than network I/O, + // and not worth running in a background thread or anything. try { long elapsed = SystemClock.elapsedRealtime() - start; ContentValues values = new ContentValues(); - values.put(Checkin.Stats.TAG, - Checkin.Stats.Tag.HTTP_STATUS + ":" + - mUserAgent + ":" + code); values.put(Checkin.Stats.COUNT, 1); values.put(Checkin.Stats.SUM, elapsed / 1000.0); + + values.put(Checkin.Stats.TAG, Checkin.Stats.Tag.HTTP_REQUEST + ":" + mAppName); + mResolver.insert(Checkin.Stats.CONTENT_URI, values); + + // No sockets and no exceptions means we successfully reused a connection + if (mConnectionAllocated.get() == null && code >= 0) { + values.put(Checkin.Stats.TAG, Checkin.Stats.Tag.HTTP_REUSED + ":" + mAppName); + mResolver.insert(Checkin.Stats.CONTENT_URI, values); + } + + String status = code < 0 ? "IOException" : Integer.toString(code); + values.put(Checkin.Stats.TAG, + Checkin.Stats.Tag.HTTP_STATUS + ":" + mAppName + ":" + status); mResolver.insert(Checkin.Stats.CONTENT_URI, values); } catch (Exception e) { Log.e(TAG, "Error recording stats", e); diff --git a/core/java/com/google/android/util/GoogleWebContentHelper.java b/core/java/com/google/android/util/GoogleWebContentHelper.java index 2911420..8291e29 100644 --- a/core/java/com/google/android/util/GoogleWebContentHelper.java +++ b/core/java/com/google/android/util/GoogleWebContentHelper.java @@ -130,7 +130,18 @@ public class GoogleWebContentHelper { mWebView.loadUrl(mSecureUrl); return this; } - + + /** + * Loads data into the webview and also provides a failback url + * @return This {@link GoogleWebContentHelper} so methods can be chained. + */ + public GoogleWebContentHelper loadDataWithFailUrl(String base, String data, + String mimeType, String encoding, String failUrl) { + ensureViews(); + mWebView.loadDataWithBaseURL(base, data, mimeType, encoding, failUrl); + return this; + } + /** * Helper to handle the back key. Returns true if the back key was handled, * otherwise returns false. diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 4839b6f..888cb11 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES:= \ ActivityManager.cpp \ AndroidRuntime.cpp \ CursorWindow.cpp \ + Time.cpp \ com_google_android_gles_jni_EGLImpl.cpp \ com_google_android_gles_jni_GLImpl.cpp.arm \ android_opengl_GLES10.cpp \ @@ -117,7 +118,10 @@ LOCAL_SRC_FILES:= \ android_location_GpsLocationProvider.cpp \ com_android_internal_os_ZygoteInit.cpp \ com_android_internal_graphics_NativeUtils.cpp \ - android_backup_FileBackupHelper.cpp + android_backup_BackupDataInput.cpp \ + android_backup_BackupDataOutput.cpp \ + android_backup_FileBackupHelperBase.cpp \ + android_backup_BackupHelperDispatcher.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ @@ -164,8 +168,7 @@ LOCAL_SHARED_LIBRARIES := \ libicui18n \ libicudata \ libmedia \ - libwpa_client \ - libemoji + libwpa_client ifeq ($(BOARD_HAVE_BLUETOOTH),true) LOCAL_C_INCLUDES += \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index aa6450d..c815301 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -155,7 +155,10 @@ extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env); extern int register_android_util_Base64(JNIEnv* env); extern int register_android_location_GpsLocationProvider(JNIEnv* env); -extern int register_android_backup_FileBackupHelper(JNIEnv *env); +extern int register_android_backup_BackupDataInput(JNIEnv *env); +extern int register_android_backup_BackupDataOutput(JNIEnv *env); +extern int register_android_backup_FileBackupHelperBase(JNIEnv *env); +extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1126,7 +1129,10 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_ddm_DdmHandleNativeHeap), REG_JNI(register_android_util_Base64), REG_JNI(register_android_location_GpsLocationProvider), - REG_JNI(register_android_backup_FileBackupHelper), + REG_JNI(register_android_backup_BackupDataInput), + REG_JNI(register_android_backup_BackupDataOutput), + REG_JNI(register_android_backup_FileBackupHelperBase), + REG_JNI(register_android_backup_BackupHelperDispatcher), }; /* diff --git a/core/jni/Time.cpp b/core/jni/Time.cpp new file mode 100644 index 0000000..f3037f3 --- /dev/null +++ b/core/jni/Time.cpp @@ -0,0 +1,199 @@ +#include "TimeUtils.h" +#include <stdio.h> +#include <cutils/tztime.h> + +namespace android { + +static void +dump(const Time& t) +{ + #ifdef HAVE_TM_GMTOFF + long tm_gmtoff = t.t.tm_gmtoff; + #else + long tm_gmtoff = 0; + #endif + printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n", + t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday, + t.t.tm_hour, t.t.tm_min, t.t.tm_sec, + t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday); +} + +Time::Time() +{ + t.tm_sec = 0; + t.tm_min = 0; + t.tm_hour = 0; + t.tm_mday = 0; + t.tm_mon = 0; + t.tm_year = 0; + t.tm_wday = 0; + t.tm_yday = 0; + t.tm_isdst = -1; // we don't know, so let the C library determine + #ifdef HAVE_TM_GMTOFF + t.tm_gmtoff = 0; + #endif +} + + +#define COMPARE_FIELD(field) do { \ + int diff = a.t.field - b.t.field; \ + if (diff != 0) return diff; \ + } while(0) + +int +Time::compare(Time& a, Time& b) +{ + if (0 == strcmp(a.timezone, b.timezone)) { + // if the timezones are the same, we can easily compare the two + // times. Otherwise, convert to milliseconds and compare that. + // This requires that object be normalized. + COMPARE_FIELD(tm_year); + COMPARE_FIELD(tm_mon); + COMPARE_FIELD(tm_mday); + COMPARE_FIELD(tm_hour); + COMPARE_FIELD(tm_min); + COMPARE_FIELD(tm_sec); + return 0; + } else { + int64_t am = a.toMillis(false /* use isDst */); + int64_t bm = b.toMillis(false /* use isDst */); + int64_t diff = am-bm; + return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0); + } +} + +static const int DAYS_PER_MONTH[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + +static inline int days_this_month(int year, int month) +{ + int n = DAYS_PER_MONTH[month]; + if (n != 28) { + return n; + } else { + int y = year; + return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28; + } +} + +void +Time::switchTimezone(const char* timezone) +{ + time_t seconds = mktime_tz(&(this->t), this->timezone); + localtime_tz(&seconds, &(this->t), timezone); +} + +String8 +Time::format(const char *format, const struct strftime_locale *locale) const +{ + char buf[257]; + int n = strftime_tz(buf, 257, format, &(this->t), locale); + if (n > 0) { + return String8(buf); + } else { + return String8(); + } +} + +static inline short +tochar(int n) +{ + return (n >= 0 && n <= 9) ? ('0'+n) : ' '; +} + +static inline short +next_char(int *m, int k) +{ + int n = *m / k; + *m = *m % k; + return tochar(n); +} + +void +Time::format2445(short* buf, bool hasTime) const +{ + int n; + + n = t.tm_year+1900; + buf[0] = next_char(&n, 1000); + buf[1] = next_char(&n, 100); + buf[2] = next_char(&n, 10); + buf[3] = tochar(n); + + n = t.tm_mon+1; + buf[4] = next_char(&n, 10); + buf[5] = tochar(n); + + n = t.tm_mday; + buf[6] = next_char(&n, 10); + buf[7] = tochar(n); + + if (hasTime) { + buf[8] = 'T'; + + n = t.tm_hour; + buf[9] = next_char(&n, 10); + buf[10] = tochar(n); + + n = t.tm_min; + buf[11] = next_char(&n, 10); + buf[12] = tochar(n); + + n = t.tm_sec; + buf[13] = next_char(&n, 10); + buf[14] = tochar(n); + bool inUtc = strcmp("UTC", timezone) == 0; + if (inUtc) { + buf[15] = 'Z'; + } + } +} + +String8 +Time::toString() const +{ + String8 str; + char* s = str.lockBuffer(150); + #ifdef HAVE_TM_GMTOFF + long tm_gmtoff = t.tm_gmtoff; + #else + long tm_gmtoff = 0; + #endif + sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", + t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst, + (int)(((Time*)this)->toMillis(false /* use isDst */)/1000)); + str.unlockBuffer(); + return str; +} + +void +Time::setToNow() +{ + time_t seconds; + time(&seconds); + localtime_tz(&seconds, &(this->t), this->timezone); +} + +int64_t +Time::toMillis(bool ignoreDst) +{ + if (ignoreDst) { + this->t.tm_isdst = -1; + } + int64_t r = mktime_tz(&(this->t), this->timezone); + if (r == -1) + return -1; + return r * 1000; +} + +void +Time::set(int64_t millis) +{ + time_t seconds = millis / 1000; + localtime_tz(&seconds, &(this->t), this->timezone); +} + +}; // namespace android + diff --git a/core/jni/TimeUtils.h b/core/jni/TimeUtils.h new file mode 100644 index 0000000..b19e021 --- /dev/null +++ b/core/jni/TimeUtils.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_TIME_H +#define ANDROID_TIME_H + +#include <time.h> +#include <cutils/tztime.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/time.h> +#include <utils/String8.h> +#include <utils/String16.h> + +namespace android { + +/* + * This class is the core implementation of the android.util.Time java + * class. It doesn't implement some of the methods that are implemented + * in Java. They could be done here, but it's not expected that this class + * will be used. If that assumption is incorrect, feel free to update this + * file. The reason to do it here is to not mix the implementation of this + * class and the jni glue code. + */ +class Time +{ +public: + struct tm t; + + // this object doesn't own this string + const char *timezone; + + enum { + SEC = 1, + MIN = 2, + HOUR = 3, + MDAY = 4, + MON = 5, + YEAR = 6, + WDAY = 7, + YDAY = 8 + }; + + static int compare(Time& a, Time& b); + + Time(); + + void switchTimezone(const char *timezone); + String8 format(const char *format, const struct strftime_locale *locale) const; + void format2445(short* buf, bool hasTime) const; + String8 toString() const; + void setToNow(); + int64_t toMillis(bool ignoreDst); + void set(int64_t millis); + + inline void set(int sec, int min, int hour, int mday, int mon, int year, + int isdst) + { + this->t.tm_sec = sec; + this->t.tm_min = min; + this->t.tm_hour = hour; + this->t.tm_mday = mday; + this->t.tm_mon = mon; + this->t.tm_year = year; + this->t.tm_isdst = isdst; +#ifdef HAVE_TM_GMTOFF + this->t.tm_gmtoff = 0; +#endif + this->t.tm_wday = 0; + this->t.tm_yday = 0; + } +}; + +}; // namespace android + +#endif // ANDROID_TIME_H diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 65f44d5..af8ecf5 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/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 1fd15d6..137707f 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -311,7 +311,7 @@ static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream, int sampleSize) { SkPixelRef* pr; // only use ashmem for large images, since mmaps come at a price - if (bitmap->getSize() >= 32 * 65536) { + if (bitmap->getSize() >= 32 * 1024) { pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize); } else { pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize); @@ -520,7 +520,10 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, */ AutoFDSeek as(descriptor); - return doDecode(env, stream, padding, bitmapFactoryOptions, true); + /* Allow purgeable iff we own the FD, i.e., in the puregeable and + shareable case. + */ + return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD); } /* make a deep copy of the asset, and return it as a stream, or NULL if there diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 76e6f02..d1fe83e 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -69,6 +69,8 @@ public: static void reset(JNIEnv* env, jobject clazz, SkPaint* obj) { obj->reset(); + // utf16 is required for java + obj->setTextEncoding(SkPaint::kUTF16_TextEncoding); } static void assign(JNIEnv* env, jobject clazz, SkPaint* dst, const SkPaint* src) { diff --git a/core/jni/android_backup_BackupDataInput.cpp b/core/jni/android_backup_BackupDataInput.cpp new file mode 100644 index 0000000..cf8a8e8 --- /dev/null +++ b/core/jni/android_backup_BackupDataInput.cpp @@ -0,0 +1,164 @@ +/* + * 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; + +// android.backup.BackupDataInput$EntityHeader +static jfieldID s_keyField = 0; +static jfieldID s_dataSizeField = 0; + +static int +ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor) +{ + int err; + + int fd = env->GetIntField(fileDescriptor, s_descriptorField); + if (fd == -1) { + return NULL; + } + + return (int)new BackupDataReader(fd); +} + +static void +dtor_native(JNIEnv* env, jobject clazz, int r) +{ + delete (BackupDataReader*)r; +} + +static jint +readNextHeader_native(JNIEnv* env, jobject clazz, int r, jobject entity) +{ + int err; + bool done; + BackupDataReader* reader = (BackupDataReader*)r; + + int type = 0; + + err = reader->ReadNextHeader(&done, &type); + if (done) { + return 1; + } + + if (err != 0) { + return err < 0 ? err : -1; + } + + switch (type) { + case BACKUP_HEADER_ENTITY_V1: + { + String8 key; + size_t dataSize; + err = reader->ReadEntityHeader(&key, &dataSize); + if (err != 0) { + return err < 0 ? err : -1; + } + // TODO: Set the fields in the entity object + jstring keyStr = env->NewStringUTF(key.string()); + env->SetObjectField(entity, s_keyField, keyStr); + env->SetIntField(entity, s_dataSizeField, dataSize); + return 0; + } + default: + LOGD("Unknown header type: 0x%08x\n", type); + return -1; + } + + // done + return 1; +} + +static jint +readEntityData_native(JNIEnv* env, jobject clazz, int r, jbyteArray data, int offset, int size) +{ + int err; + BackupDataReader* reader = (BackupDataReader*)r; + + if (env->GetArrayLength(data) < (size+offset)) { + // size mismatch + return -1; + } + + jbyte* dataBytes = env->GetByteArrayElements(data, NULL); + if (dataBytes == NULL) { + return -2; + } + + err = reader->ReadEntityData(dataBytes+offset, size); + + env->ReleaseByteArrayElements(data, dataBytes, 0); + + return err; +} + +static jint +skipEntityData_native(JNIEnv* env, jobject clazz, int r) +{ + int err; + BackupDataReader* reader = (BackupDataReader*)r; + + err = reader->SkipEntityData(); + + return err; +} + +static const JNINativeMethod g_methods[] = { + { "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native }, + { "dtor", "(I)V", (void*)dtor_native }, + { "readNextHeader_native", "(ILandroid/backup/BackupDataInput$EntityHeader;)I", + (void*)readNextHeader_native }, + { "readEntityData_native", "(I[BII)I", (void*)readEntityData_native }, + { "skipEntityData_native", "(I)I", (void*)skipEntityData_native }, +}; + +int register_android_backup_BackupDataInput(JNIEnv* env) +{ + //LOGD("register_android_backup_BackupDataInput"); + + 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"); + + clazz = env->FindClass("android/backup/BackupDataInput$EntityHeader"); + LOG_FATAL_IF(clazz == NULL, "Unable to find class android.backup.BackupDataInput.EntityHeader"); + s_keyField = env->GetFieldID(clazz, "key", "Ljava/lang/String;"); + LOG_FATAL_IF(s_keyField == NULL, + "Unable to find key field in android.backup.BackupDataInput.EntityHeader"); + s_dataSizeField = env->GetFieldID(clazz, "dataSize", "I"); + LOG_FATAL_IF(s_dataSizeField == NULL, + "Unable to find dataSize field in android.backup.BackupDataInput.EntityHeader"); + + return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupDataInput", + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp new file mode 100644 index 0000000..d02590e --- /dev/null +++ b/core/jni/android_backup_BackupDataOutput.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "FileBackupHelper_native" +#include <utils/Log.h> + +#include "JNIHelp.h" +#include <android_runtime/AndroidRuntime.h> + +#include <utils/BackupHelpers.h> + +namespace android +{ + +static jfieldID s_descriptorField = 0; + +static int +ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor) +{ + int err; + + int fd = env->GetIntField(fileDescriptor, s_descriptorField); + if (fd == -1) { + return NULL; + } + + return (int)new BackupDataWriter(fd); +} + +static void +dtor_native(JNIEnv* env, jobject clazz, int w) +{ + delete (BackupDataWriter*)w; +} + +static jint +writeEntityHeader_native(JNIEnv* env, jobject clazz, int w, jstring key, int dataSize) +{ + int err; + BackupDataWriter* writer = (BackupDataWriter*)w; + + const char* keyUTF = env->GetStringUTFChars(key, NULL); + if (keyUTF == NULL) { + return -1; + } + + err = writer->WriteEntityHeader(String8(keyUTF), dataSize); + + env->ReleaseStringUTFChars(key, keyUTF); + + return err; +} + +static jint +writeEntityData_native(JNIEnv* env, jobject clazz, int w, jbyteArray data, int size) +{ + int err; + BackupDataWriter* writer = (BackupDataWriter*)w; + + if (env->GetArrayLength(data) > size) { + // size mismatch + return -1; + } + + jbyte* dataBytes = env->GetByteArrayElements(data, NULL); + if (dataBytes == NULL) { + return -1; + } + + err = writer->WriteEntityData(dataBytes, size); + + env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT); + + 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) +{ + //LOGD("register_android_backup_BackupDataOutput"); + + jclass clazz; + + clazz = env->FindClass("java/io/FileDescriptor"); + LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); + s_descriptorField = env->GetFieldID(clazz, "descriptor", "I"); + LOG_FATAL_IF(s_descriptorField == NULL, + "Unable to find descriptor field in java.io.FileDescriptor"); + + return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupDataOutput", + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_backup_BackupHelperDispatcher.cpp b/core/jni/android_backup_BackupHelperDispatcher.cpp new file mode 100644 index 0000000..2e3f0b9 --- /dev/null +++ b/core/jni/android_backup_BackupHelperDispatcher.cpp @@ -0,0 +1,259 @@ +/* + * 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 "BackupHelperDispatcher_native" +#include <utils/Log.h> + +#include "JNIHelp.h" +#include <android_runtime/AndroidRuntime.h> + +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> + + +#define VERSION_1_HEADER 0x01706c48 // 'Hlp'1 little endian + +namespace android +{ + +struct chunk_header_v1 { + int headerSize; + int version; + int dataSize; // corresponds to Header.chunkSize + int nameLength; // not including the NULL terminator, which is not written to the file +}; + +// java.io.FileDescriptor +static jfieldID s_descriptorField = 0; +static jfieldID s_chunkSizeField = 0; +static jfieldID s_keyPrefixField = 0; + +static int +readHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj) +{ + chunk_header_v1 flattenedHeader; + int fd; + ssize_t amt; + String8 keyPrefix; + char* buf; + + fd = env->GetIntField(fdObj, s_descriptorField); + + amt = read(fd, &flattenedHeader.headerSize, sizeof(flattenedHeader.headerSize)); + if (amt != sizeof(flattenedHeader.headerSize)) { + return -1; + } + + int remainingHeader = flattenedHeader.headerSize - sizeof(flattenedHeader.headerSize); + + if (flattenedHeader.headerSize < (int)sizeof(chunk_header_v1)) { + LOGW("Skipping unknown header: %d bytes", flattenedHeader.headerSize); + if (remainingHeader > 0) { + lseek(fd, remainingHeader, SEEK_CUR); + // >0 means skip this chunk + return 1; + } + } + + amt = read(fd, &flattenedHeader.version, + sizeof(chunk_header_v1)-sizeof(flattenedHeader.headerSize)); + if (amt <= 0) { + LOGW("Failed reading chunk header"); + return -1; + } + remainingHeader -= sizeof(chunk_header_v1)-sizeof(flattenedHeader.headerSize); + + if (flattenedHeader.version != VERSION_1_HEADER) { + LOGW("Skipping unknown header version: 0x%08x, %d bytes", flattenedHeader.version, + flattenedHeader.headerSize); + if (remainingHeader > 0) { + lseek(fd, remainingHeader, SEEK_CUR); + // >0 means skip this chunk + return 1; + } + } + +#if 0 + LOGD("chunk header:"); + LOGD(" headerSize=%d", flattenedHeader.headerSize); + LOGD(" version=0x%08x", flattenedHeader.version); + LOGD(" dataSize=%d", flattenedHeader.dataSize); + LOGD(" nameLength=%d", flattenedHeader.nameLength); +#endif + + if (flattenedHeader.dataSize < 0 || flattenedHeader.nameLength < 0 || + remainingHeader < flattenedHeader.nameLength) { + LOGW("Malformed V1 header remainingHeader=%d dataSize=%d nameLength=%d", remainingHeader, + flattenedHeader.dataSize, flattenedHeader.nameLength); + return -1; + } + + buf = keyPrefix.lockBuffer(flattenedHeader.nameLength); + if (buf == NULL) { + LOGW("unable to allocate %d bytes", flattenedHeader.nameLength); + return -1; + } + + amt = read(fd, buf, flattenedHeader.nameLength); + buf[flattenedHeader.nameLength] = 0; + + keyPrefix.unlockBuffer(flattenedHeader.nameLength); + + remainingHeader -= flattenedHeader.nameLength; + + if (remainingHeader > 0) { + lseek(fd, remainingHeader, SEEK_CUR); + } + + env->SetIntField(headerObj, s_chunkSizeField, flattenedHeader.dataSize); + env->SetObjectField(headerObj, s_keyPrefixField, env->NewStringUTF(keyPrefix.string())); + + return 0; +} + +static int +skipChunk_native(JNIEnv* env, jobject clazz, jobject fdObj, jint bytesToSkip) +{ + int fd; + + fd = env->GetIntField(fdObj, s_descriptorField); + + lseek(fd, bytesToSkip, SEEK_CUR); + + return 0; +} + +static int +padding_len(int len) +{ + len = len % 4; + return len == 0 ? len : 4 - len; +} + +static int +allocateHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj) +{ + int pos; + jstring nameObj; + int nameLength; + int namePadding; + int headerSize; + int fd; + + fd = env->GetIntField(fdObj, s_descriptorField); + + nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField); + + nameLength = env->GetStringUTFLength(nameObj); + namePadding = padding_len(nameLength); + + headerSize = sizeof(chunk_header_v1) + nameLength + namePadding; + + pos = lseek(fd, 0, SEEK_CUR); + + lseek(fd, headerSize, SEEK_CUR); + + return pos; +} + +static int +writeHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj, jint pos) +{ + int err; + chunk_header_v1 header; + int fd; + int namePadding; + int prevPos; + jstring nameObj; + const char* buf; + + fd = env->GetIntField(fdObj, s_descriptorField); + prevPos = lseek(fd, 0, SEEK_CUR); + + nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField); + header.nameLength = env->GetStringUTFLength(nameObj); + namePadding = padding_len(header.nameLength); + + header.headerSize = sizeof(chunk_header_v1) + header.nameLength + namePadding; + header.version = VERSION_1_HEADER; + header.dataSize = prevPos - (pos + header.headerSize); + + lseek(fd, pos, SEEK_SET); + err = write(fd, &header, sizeof(chunk_header_v1)); + if (err != sizeof(chunk_header_v1)) { + return errno; + } + + buf = env->GetStringUTFChars(nameObj, NULL); + err = write(fd, buf, header.nameLength); + env->ReleaseStringUTFChars(nameObj, buf); + if (err != header.nameLength) { + return errno; + } + + if (namePadding != 0) { + int zero = 0; + err = write(fd, &zero, namePadding); + if (err != namePadding) { + return errno; + } + } + + lseek(fd, prevPos, SEEK_SET); + return 0; +} + +static const JNINativeMethod g_methods[] = { + { "readHeader_native", + "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;)I", + (void*)readHeader_native }, + { "skipChunk_native", + "(Ljava/io/FileDescriptor;I)I", + (void*)skipChunk_native }, + { "allocateHeader_native", + "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;)I", + (void*)allocateHeader_native }, + { "writeHeader_native", + "(Landroid/backup/BackupHelperDispatcher$Header;Ljava/io/FileDescriptor;I)I", + (void*)writeHeader_native }, +}; + +int register_android_backup_BackupHelperDispatcher(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"); + + clazz = env->FindClass("android/backup/BackupHelperDispatcher$Header"); + LOG_FATAL_IF(clazz == NULL, + "Unable to find class android.backup.BackupHelperDispatcher.Header"); + s_chunkSizeField = env->GetFieldID(clazz, "chunkSize", "I"); + LOG_FATAL_IF(s_chunkSizeField == NULL, + "Unable to find chunkSize field in android.backup.BackupHelperDispatcher.Header"); + s_keyPrefixField = env->GetFieldID(clazz, "keyPrefix", "Ljava/lang/String;"); + LOG_FATAL_IF(s_keyPrefixField == NULL, + "Unable to find keyPrefix field in android.backup.BackupHelperDispatcher.Header"); + + return AndroidRuntime::registerNativeMethods(env, "android/backup/BackupHelperDispatcher", + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp deleted file mode 100644 index c6de3a5..0000000 --- a/core/jni/android_backup_FileBackupHelper.cpp +++ /dev/null @@ -1,84 +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/backup_helpers.h> - -namespace android -{ - -static jfieldID s_descriptorField = 0; - -static int -performBackup_native(JNIEnv* env, jobject clazz, jstring basePath, jobject oldState, jobject data, - jobject newState, jobjectArray files) -{ - int err; - - // all parameters have already been checked against null - LOGD("oldState=%p newState=%p data=%p\n", oldState, newState, data); - int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1; - int newStateFD = env->GetIntField(newState, s_descriptorField); - int dataFD = env->GetIntField(data, s_descriptorField); - - char const* basePathUTF = env->GetStringUTFChars(basePath, NULL); - LOGD("basePathUTF=\"%s\"\n", basePathUTF); - const int fileCount = env->GetArrayLength(files); - char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount); - for (int i=0; i<fileCount; i++) { - filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL); - } - - err = back_up_files(oldStateFD, dataFD, newStateFD, basePathUTF, filesUTF, fileCount); - - for (int i=0; i<fileCount; i++) { - env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]); - } - free(filesUTF); - env->ReleaseStringUTFChars(basePath, basePathUTF); - - return err; -} - -static const JNINativeMethod g_methods[] = { - { "performBackup_native", - "(Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;" - "Ljava/io/FileDescriptor;[Ljava/lang/String;)I", - (void*)performBackup_native }, -}; - -int register_android_backup_FileBackupHelper(JNIEnv* env) -{ - LOGD("register_android_backup_FileBackupHelper"); - - 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/FileBackupHelper", - g_methods, NELEM(g_methods)); -} - -} diff --git a/core/jni/android_backup_FileBackupHelperBase.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp new file mode 100644 index 0000000..8225a36 --- /dev/null +++ b/core/jni/android_backup_FileBackupHelperBase.cpp @@ -0,0 +1,136 @@ +/* + * 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 +performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data, + jobject newState, jobjectArray files, jobjectArray keys) +{ + int err; + + // all parameters have already been checked against null + int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1; + int newStateFD = env->GetIntField(newState, s_descriptorField); + BackupDataWriter* dataStream = (BackupDataWriter*)data; + + const int fileCount = env->GetArrayLength(files); + char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount); + for (int i=0; i<fileCount; i++) { + filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL); + } + + const int keyCount = env->GetArrayLength(keys); + char const** keysUTF = (char const**)malloc(sizeof(char*)*keyCount); + for (int i=0; i<keyCount; i++) { + keysUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), NULL); + } + + err = back_up_files(oldStateFD, dataStream, newStateFD, filesUTF, keysUTF, fileCount); + + for (int i=0; i<fileCount; i++) { + env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]); + } + free(filesUTF); + + for (int i=0; i<keyCount; i++) { + env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(keys, i), keysUTF[i]); + } + free(keysUTF); + + 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_FileBackupHelperBase(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/FileBackupHelperBase", + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_bluetooth_Database.cpp b/core/jni/android_bluetooth_Database.cpp index 136c9a3..73b8efd 100644 --- a/core/jni/android_bluetooth_Database.cpp +++ b/core/jni/android_bluetooth_Database.cpp @@ -53,6 +53,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) { LOGE("Could not get onto the system bus!"); dbus_error_free(&err); } + dbus_connection_set_exit_on_disconnect(conn, FALSE); } #endif } diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp index 59f63a8..7d6e24f 100644 --- a/core/jni/android_emoji_EmojiFactory.cpp +++ b/core/jni/android_emoji_EmojiFactory.cpp @@ -1,7 +1,7 @@ #include "SkTypes.h" #include "SkImageDecoder.h" -#define LOG_TAG "DoCoMoEmojiFactory_jni" +#define LOG_TAG "EmojiFactory_jni" #include <utils/Log.h> #include <utils/String8.h> @@ -13,15 +13,11 @@ namespace android { -// Note: This class is originally developed so that libandroid_runtime does -// not have to depend on libemoji which is optional library. However, we -// cannot use this class, since current (2009-02-16) bionic libc does not allow -// dlopen()-ing inside dlopen(), while not only this class but also libemoji -// uses dlopen(). class EmojiFactoryCaller { public: - EmojiFactoryCaller(); + EmojiFactoryCaller() {} virtual ~EmojiFactoryCaller(); + bool Init(); EmojiFactory *TryCallGetImplementation(const char* name); EmojiFactory *TryCallGetAvailableImplementation(); private: @@ -30,35 +26,45 @@ class EmojiFactoryCaller { EmojiFactory *(*m_get_available_implementation)(); }; -EmojiFactoryCaller::EmojiFactoryCaller() { +bool EmojiFactoryCaller::Init() { + const char* error_msg; m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL); - const char* error_str = dlerror(); - if (error_str) { - LOGI("Failed to load libemoji.so: %s", error_str); - return; + + if (m_handle == NULL) { + error_msg = "Failed to load libemoji.so"; + goto FAIL; } m_get_implementation = reinterpret_cast<EmojiFactory *(*)(const char*)>( dlsym(m_handle, "GetImplementation")); - error_str = dlerror(); - if (error_str) { - LOGE("Failed to get symbol of GetImplementation: %s", error_str); - dlclose(m_handle); - m_handle = NULL; - return; + if (m_get_implementation == NULL) { + error_msg = "Failed to get symbol of GetImplementation"; + goto FAIL; } m_get_available_implementation = reinterpret_cast<EmojiFactory *(*)()>( dlsym(m_handle,"GetAvailableImplementation")); - error_str = dlerror(); - if (error_str) { - LOGE("Failed to get symbol of GetAvailableImplementation: %s", error_str); + if (m_get_available_implementation == NULL) { + error_msg = "Failed to get symbol of GetAvailableImplementation"; + goto FAIL; + } + + return true; + +FAIL: + const char* error_str = dlerror(); + if (error_str == NULL) { + error_str = "unknown reason"; + } + + LOGE("%s: %s", error_msg, error_str); + if (m_handle != NULL) { dlclose(m_handle); m_handle = NULL; - return; } + return false; } EmojiFactoryCaller::~EmojiFactoryCaller() { @@ -82,10 +88,9 @@ EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() { return m_get_available_implementation(); } -// Note: bionic libc's dlopen() does not allow recursive dlopen(). So currently -// we cannot use EmojiFactoryCaller here. -// static EmojiFactoryCaller* gCaller; -// static pthread_once_t g_once = PTHREAD_ONCE_INIT; +static EmojiFactoryCaller* gCaller; +static pthread_once_t g_once = PTHREAD_ONCE_INIT; +static bool lib_emoji_factory_is_ready; static jclass gString_class; @@ -95,9 +100,10 @@ static jmethodID gBitmap_constructorMethodID; static jclass gEmojiFactory_class; static jmethodID gEmojiFactory_constructorMethodID; -// static void InitializeCaller() { -// gCaller = new EmojiFactoryCaller(); -// } +static void InitializeCaller() { + gCaller = new EmojiFactoryCaller(); + lib_emoji_factory_is_ready = gCaller->Init(); +} static jobject create_java_EmojiFactory( JNIEnv* env, EmojiFactory* factory, jstring name) { @@ -116,19 +122,23 @@ static jobject create_java_EmojiFactory( static jobject android_emoji_EmojiFactory_newInstance( JNIEnv* env, jobject clazz, jstring name) { - // pthread_once(&g_once, InitializeCaller); - if (NULL == name) { return NULL; } + pthread_once(&g_once, InitializeCaller); + if (!lib_emoji_factory_is_ready) { + return NULL; + } const jchar* jchars = env->GetStringChars(name, NULL); jsize len = env->GetStringLength(name); String8 str(String16(jchars, len)); - // EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string()); - EmojiFactory *factory = EmojiFactory::GetImplementation(str.string()); - + EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string()); + // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string()); + if (NULL == factory) { + return NULL; + } env->ReleaseStringChars(name, jchars); return create_java_EmojiFactory(env, factory, name); @@ -136,10 +146,13 @@ static jobject android_emoji_EmojiFactory_newInstance( static jobject android_emoji_EmojiFactory_newAvailableInstance( JNIEnv* env, jobject clazz) { - // pthread_once(&g_once, InitializeCaller); + pthread_once(&g_once, InitializeCaller); + if (!lib_emoji_factory_is_ready) { + return NULL; + } - // EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation(); - EmojiFactory *factory = EmojiFactory::GetAvailableImplementation(); + EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation(); + // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation(); if (NULL == factory) { return NULL; } diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index c107993..77a8a72 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -38,12 +38,6 @@ enum CallbackMessageID { kErrorCallback = 5 }; -enum CameraError { - kCameraErrorUnknown = 1, - kCameraErrorMediaServer = 100 -}; - - struct fields_t { jfieldID context; jfieldID surface; @@ -53,19 +47,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 +84,108 @@ 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; - break; - default: - error = kCameraErrorUnknown; - break; + 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(); + env->CallStaticVoidMethod(mCameraJClass, fields.post_event, + mCameraJObjectWeak, msgType, ext1, ext2); +} + +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"); + if (mCameraJObjectWeak == NULL) { + LOGW("callback on dead camera object"); return; } - env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event, - context->mCameraJObjectWeak, kErrorCallback, error, 0, NULL); + + // return data based on callback type + switch(msgType) { + case CAMERA_MSG_VIDEO_FRAME: + // should never happen + break; + // don't return raw data to Java + case CAMERA_MSG_RAW_IMAGE: + LOGV("rawCallback"); + env->CallStaticVoidMethod(mCameraJClass, fields.post_event, + mCameraJObjectWeak, msgType, 0, 0, NULL); + break; + default: + LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); + copyAndPost(env, dataPtr, msgType); + break; + } } // connect to camera service @@ -115,33 +201,24 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj // make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { - jniThrowException(env, "java/io/IOException", "Camera initialization failed"); + jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { - LOGE("Can't find android/hardware/Camera"); - // XXX no idea what to throw here, can this even happen? - jniThrowException(env, "java/lang/Exception", NULL); + jniThrowException(env, "java/lang/RuntimeException", "Can't find android/hardware/Camera"); return; } // 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 @@ -150,11 +227,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); @@ -162,21 +239,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); } } @@ -186,54 +260,15 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return; - sp<Surface> surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); + sp<Surface> surface = NULL; + if (jSurface != NULL) { + surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); + } if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); } } -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"); @@ -241,7 +276,7 @@ static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) if (camera == 0) return; if (camera->startPreview() != NO_ERROR) { - jniThrowException(env, "java/io/IOException", "startPreview failed"); + jniThrowException(env, "java/lang/RuntimeException", "startPreview failed"); return; } } @@ -269,7 +304,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; @@ -279,130 +314,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/io/IOException", "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; + jniThrowException(env, "java/lang/RuntimeException", "autoFocus failed"); } - 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/io/IOException", "takePicture failed"); + jniThrowException(env, "java/lang/RuntimeException", "takePicture failed"); return; } - - return; } static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params) @@ -418,7 +355,7 @@ static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jst env->ReleaseStringCritical(params, str); } if (camera->setParameters(params8) != NO_ERROR) { - jniThrowException(env, "java/lang/IllegalArgumentException", "setParameters failed"); + jniThrowException(env, "java/lang/RuntimeException", "setParameters failed"); return; } } diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 75aa458..3e27978 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -14,9 +14,13 @@ * limitations under the License. */ -#define LOG_TAG "Sensors" +#define LOG_TAG "SensorManager" + +#define LOG_NDEBUG 0 +#include "utils/Log.h" #include <hardware/sensors.h> +#include <cutils/native_handle.h> #include "jni.h" #include "JNIHelp.h" @@ -106,12 +110,33 @@ sensors_data_uninit(JNIEnv *env, jclass clazz) } static jint -sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo) +sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray) { jclass FileDescriptor = env->FindClass("java/io/FileDescriptor"); - jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I"); - int fd = env->GetIntField(fdo, offset); - return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd + jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I"); + int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0); + int numInts = (intArray ? env->GetArrayLength(intArray) : 0); + native_handle_t* handle = native_handle_create(numFds, numInts); + int offset = 0; + + for (int i = 0; i < numFds; i++) { + jobject fdo = env->GetObjectArrayElement(fdArray, i); + if (fdo) { + handle->data[offset++] = env->GetIntField(fdo, fieldOffset); + } else { + handle->data[offset++] = -1; + } + } + if (numInts > 0) { + jint* ints = env->GetIntArrayElements(intArray, 0); + for (int i = 0; i < numInts; i++) { + handle->data[offset++] = ints[i]; + } + env->ReleaseIntArrayElements(intArray, ints, 0); + } + + // doesn't take ownership of the native handle + return sSensorDevice->data_open(sSensorDevice, handle); } static jint @@ -157,7 +182,7 @@ static JNINativeMethod gMethods[] = { (void*)sensors_module_get_next_sensor }, {"sensors_data_init", "()I", (void*)sensors_data_init }, {"sensors_data_uninit", "()I", (void*)sensors_data_uninit }, - {"sensors_data_open", "(Ljava/io/FileDescriptor;)I", (void*)sensors_data_open }, + {"sensors_data_open", "([Ljava/io/FileDescriptor;[I)I", (void*)sensors_data_open }, {"sensors_data_close", "()I", (void*)sensors_data_close }, {"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll }, }; diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index 004b0e3..bf0bd65 100644..100755 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -176,7 +176,7 @@ static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject { int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency)); if (result) { - return result; + return false; } return (sGpsInterface->start() == 0); @@ -270,6 +270,12 @@ static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobjec sGpsInterface->inject_time(time, timeReference, uncertainty); } +static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj, + jdouble latitude, jdouble longitude, jfloat accuracy) +{ + sGpsInterface->inject_location(latitude, longitude, accuracy); +} + static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj) { if (!sGpsXtraInterface) { @@ -330,13 +336,15 @@ static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* e } static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj, - jint type, jint addr, jint port) + jint type, jstring hostname, jint port) { if (!sAGpsInterface) { sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); } if (sAGpsInterface) { - sAGpsInterface->set_server(type, addr, port); + const char *c_hostname = env->GetStringUTFChars(hostname, NULL); + sAGpsInterface->set_server(type, c_hostname, port); + env->ReleaseStringUTFChars(hostname, c_hostname); } } @@ -353,12 +361,13 @@ static JNINativeMethod sMethods[] = { {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event}, {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, + {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open}, {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, - {"native_set_agps_server", "(III)V", (void*)android_location_GpsLocationProvider_set_agps_server}, + {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server}, }; int register_android_location_GpsLocationProvider(JNIEnv* env) diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 288433a..e71e348 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -45,8 +45,6 @@ struct fields_t { jmethodID postNativeEventInJava; //... event post callback method int PCM16; //... format constants int PCM8; //... format constants - int SOURCE_DEFAULT; //... record source constants - int SOURCE_MIC; //... record source constants jfieldID nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data }; @@ -66,7 +64,7 @@ struct audiorecord_callback_cookie { #define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT -16 #define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT -17 #define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT -18 -#define AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE -19 +#define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE -19 #define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED -20 jint android_media_translateRecorderErrorCode(int code) { @@ -154,17 +152,16 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, int frameSize = nbChannels * bytesPerSample; size_t frameCount = buffSizeInBytes / frameSize; - // compare the source against the Java constants - AudioRecord::stream_type arSource; - if (source == javaAudioRecordFields.SOURCE_DEFAULT) { - arSource = AudioRecord::DEFAULT_INPUT; - } else if (source == javaAudioRecordFields.SOURCE_MIC) { - arSource = AudioRecord::MIC_INPUT; - } else { + // convert and check input source value + // input_source values defined in AudioRecord.h are equal to + // JAVA MediaRecord.AudioSource values minus 1. + AudioRecord::input_source arSource = (AudioRecord::input_source)(source - 1); + if (arSource < AudioRecord::DEFAULT_INPUT || + arSource >= AudioRecord::NUM_INPUT_SOURCES) { LOGE("Error creating AudioRecord: unknown source."); - return AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE; + return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE; } - + audiorecord_callback_cookie *lpCallbackData = NULL; AudioRecord* lpRecorder = NULL; @@ -511,8 +508,6 @@ static JNINativeMethod gMethods[] = { #define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative" #define JAVA_CONST_PCM16_NAME "ENCODING_PCM_16BIT" #define JAVA_CONST_PCM8_NAME "ENCODING_PCM_8BIT" -#define JAVA_CONST_SOURCEDEFAULT_NAME "SOURCE_DEFAULT" -#define JAVA_CONST_SOURCEMIC_NAME "SOURCE_MIC" #define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME "mNativeRecorderInJavaObj" #define JAVA_NATIVECALLBACKINFO_FIELD_NAME "mNativeCallbackCookie" @@ -583,17 +578,6 @@ int register_android_media_AudioRecord(JNIEnv *env) return -1; } - // Get the recording source constants from the AudioRecord class - if ( !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass, - kClassPathName, - JAVA_CONST_SOURCEDEFAULT_NAME, &(javaAudioRecordFields.SOURCE_DEFAULT)) - || !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass, - kClassPathName, - JAVA_CONST_SOURCEMIC_NAME, &(javaAudioRecordFields.SOURCE_MIC)) ) { - // error log performed in getIntConstantFromClass() - return -1; - } - return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 42ada54..e7d4694 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -539,16 +539,17 @@ static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobjec // ---------------------------------------------------------------------------- -static void android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz, +static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz, jint sampleRateInHz) { AudioTrack *lpTrack = (AudioTrack *)env->GetIntField( thiz, javaAudioTrackFields.nativeTrackInJavaObj); if (lpTrack) { - lpTrack->setSampleRate(sampleRateInHz); + return android_media_translateErrorCode(lpTrack->setSampleRate(sampleRateInHz)); } else { jniThrowException(env, "java/lang/IllegalStateException", "Unable to retrieve AudioTrack pointer for setSampleRate()"); + return AUDIOTRACK_ERROR; } } @@ -788,7 +789,7 @@ static JNINativeMethod gMethods[] = { {"native_get_native_frame_count", "()I", (void *)android_media_AudioTrack_get_native_frame_count}, {"native_set_playback_rate", - "(I)V", (void *)android_media_AudioTrack_set_playback_rate}, + "(I)I", (void *)android_media_AudioTrack_set_playback_rate}, {"native_get_playback_rate", "()I", (void *)android_media_AudioTrack_get_playback_rate}, {"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos}, diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index 25670df..9f93e2f 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -317,8 +317,13 @@ static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject clazz) } // reply comes back in the form "<SSID> rssi XX" where XX is the // number we're interested in. if we're associating, it returns "OK". + // beware - <SSID> can contain spaces. if (strcmp(reply, "OK") != 0) { - sscanf(reply, "%*s %*s %d", &rssi); + char* lastSpace = strrchr(reply, ' '); + // lastSpace should be preceded by "rssi" and followed by the value + if (lastSpace && !strncmp(lastSpace - 4, "rssi", 4)) { + sscanf(lastSpace + 1, "%d", &rssi); + } } return (jint)rssi; } diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp index 482d8eb..2685d75 100644 --- a/core/jni/android_opengl_GLES10.cpp +++ b/core/jni/android_opengl_GLES10.cpp @@ -133,6 +133,19 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) commit ? 0 : JNI_ABORT); } +static void * +getDirectBufferPointer(JNIEnv *_env, jobject buffer) { + char* buf = (char*) _env->GetDirectBufferAddress(buffer); + if (buf) { + jint position = _env->GetIntField(buffer, positionID); + jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID); + buf += position << elementSizeShift; + } else { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + } + return (void*) buf; +} + static int getNumCompressedTextureFormats() { int numCompressedTextureFormats = 0; @@ -305,9 +318,8 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -2779,9 +2791,8 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -3034,9 +3045,8 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -3392,9 +3402,8 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } diff --git a/core/jni/android_os_MemoryFile.cpp b/core/jni/android_os_MemoryFile.cpp index edf7dc4..8643393 100644 --- a/core/jni/android_os_MemoryFile.cpp +++ b/core/jni/android_os_MemoryFile.cpp @@ -26,7 +26,7 @@ namespace android { -static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) +static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) { const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL); @@ -37,37 +37,52 @@ static jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, if (name) env->ReleaseStringUTFChars(name, namestr); - if (result < 0) + if (result < 0) { jniThrowException(env, "java/io/IOException", "ashmem_create_region failed"); - return result; + return NULL; + } + + return jniCreateFileDescriptor(env, result); } -static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jint fd, jint length) +static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor, + jint length, jint prot) { - jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); + jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0); if (!result) jniThrowException(env, "java/io/IOException", "mmap failed"); return result; } -static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jint fd) +static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length) +{ + int result = munmap((void *)addr, length); + if (result < 0) + jniThrowException(env, "java/io/IOException", "munmap failed"); +} + +static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor) { - close(fd); + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); + if (fd >= 0) { + jniSetFileDescriptorOfFD(env, fileDescriptor, -1); + close(fd); + } } static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, - jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, + jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, jint count, jboolean unpinned) { + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { ashmem_unpin_region(fd, 0, 0); jniThrowException(env, "java/io/IOException", "ashmem region was purged"); return -1; } - jbyte* bytes = env->GetByteArrayElements(buffer, 0); - memcpy(bytes + destOffset, (const char *)address + srcOffset, count); - env->ReleaseByteArrayElements(buffer, bytes, 0); + env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset); if (unpinned) { ashmem_unpin_region(fd, 0, 0); @@ -76,18 +91,17 @@ static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, } static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, - jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, + jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, jint count, jboolean unpinned) { + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { ashmem_unpin_region(fd, 0, 0); jniThrowException(env, "java/io/IOException", "ashmem region was purged"); return -1; } - jbyte* bytes = env->GetByteArrayElements(buffer, 0); - memcpy((char *)address + destOffset, bytes + srcOffset, count); - env->ReleaseByteArrayElements(buffer, bytes, 0); + env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset); if (unpinned) { ashmem_unpin_region(fd, 0, 0); @@ -95,21 +109,45 @@ static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, return count; } -static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jboolean pin) +static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin) { + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0)); if (result < 0) { jniThrowException(env, "java/io/IOException", NULL); } } +static jboolean android_os_MemoryFile_is_ashmem_region(JNIEnv* env, jobject clazz, + jobject fileDescriptor) { + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); + // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region. + // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel + // should return ENOTTY for all other valid file descriptors + int result = ashmem_get_size_region(fd); + if (result < 0) { + if (errno == ENOTTY) { + // ENOTTY means that the ioctl does not apply to this object, + // i.e., it is not an ashmem region. + return JNI_FALSE; + } + // Some other error, throw exception + jniThrowIOException(env, errno); + return JNI_FALSE; + } + return JNI_TRUE; +} + static const JNINativeMethod methods[] = { - {"native_open", "(Ljava/lang/String;I)I", (void*)android_os_MemoryFile_open}, - {"native_mmap", "(II)I", (void*)android_os_MemoryFile_mmap}, - {"native_close", "(I)V", (void*)android_os_MemoryFile_close}, - {"native_read", "(II[BIIIZ)I", (void*)android_os_MemoryFile_read}, - {"native_write", "(II[BIIIZ)V", (void*)android_os_MemoryFile_write}, - {"native_pin", "(IZ)V", (void*)android_os_MemoryFile_pin}, + {"native_open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open}, + {"native_mmap", "(Ljava/io/FileDescriptor;II)I", (void*)android_os_MemoryFile_mmap}, + {"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap}, + {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close}, + {"native_read", "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read}, + {"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write}, + {"native_pin", "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin}, + {"native_is_ashmem_region", "(Ljava/io/FileDescriptor;)Z", + (void*)android_os_MemoryFile_is_ashmem_region} }; static const char* const kClassPathName = "android/os/MemoryFile"; diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp index fe94642..91a8e8e 100644 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ b/core/jni/android_server_BluetoothA2dpService.cpp @@ -84,6 +84,7 @@ static bool initNative(JNIEnv* env, jobject object) { dbus_error_free(&err); return false; } + dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); #endif /*HAVE_BLUETOOTH*/ return true; } diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp index b6e9798..58ae4f6 100644 --- a/core/jni/android_server_BluetoothDeviceService.cpp +++ b/core/jni/android_server_BluetoothDeviceService.cpp @@ -109,6 +109,7 @@ static bool initializeNativeDataNative(JNIEnv* env, jobject object) { dbus_error_free(&err); return false; } + dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); nat->adapter = BLUEZ_ADAPTER_OBJECT_NAME; #endif /*HAVE_BLUETOOTH*/ diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp index 7c5da5b..ad24136 100644 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -132,6 +132,7 @@ static void initializeNativeDataNative(JNIEnv* env, jobject object) { LOGE("%s: Could not get onto the system bus!", __FUNCTION__); dbus_error_free(&err); } + dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); } #endif } @@ -161,6 +162,19 @@ static const DBusObjectPathVTable agent_vtable = { NULL, agent_event_filter, NULL, NULL, NULL, NULL }; +static unsigned int unix_events_to_dbus_flags(short events) { + return (events & DBUS_WATCH_READABLE ? POLLIN : 0) | + (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) | + (events & DBUS_WATCH_ERROR ? POLLERR : 0) | + (events & DBUS_WATCH_HANGUP ? POLLHUP : 0); +} + +static short dbus_flags_to_unix_events(unsigned int flags) { + return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) | + (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) | + (flags & POLLERR ? DBUS_WATCH_ERROR : 0) | + (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0); +} static jboolean setUpEventLoop(native_data_t *nat) { LOGV(__FUNCTION__); @@ -384,8 +398,7 @@ static void handleWatchAdd(native_data_t *nat) { read(nat->controlFdR, &newFD, sizeof(int)); read(nat->controlFdR, &flags, sizeof(unsigned int)); read(nat->controlFdR, &watch, sizeof(DBusWatch *)); - int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0) - | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0); + short events = dbus_flags_to_unix_events(flags); for (int y = 0; y<nat->pollMemberCount; y++) { if ((nat->pollData[y].fd == newFD) && @@ -429,8 +442,7 @@ static void handleWatchRemove(native_data_t *nat) { read(nat->controlFdR, &removeFD, sizeof(int)); read(nat->controlFdR, &flags, sizeof(unsigned int)); - int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0) - | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0); + short events = dbus_flags_to_unix_events(flags); for (int y = 0; y < nat->pollMemberCount; y++) { if ((nat->pollData[y].fd == removeFD) && @@ -494,13 +506,12 @@ static void *eventLoopMain(void *ptr) { } } } else { - int event = nat->pollData[i].revents; - int flags = (event & POLLIN ? DBUS_WATCH_READABLE : 0) | - (event & POLLOUT ? DBUS_WATCH_WRITABLE : 0); - dbus_watch_handle(nat->watchData[i], event); - nat->pollData[i].revents = 0; - // can only do one - it may have caused a 'remove' - break; + short events = nat->pollData[i].revents; + unsigned int flags = unix_events_to_dbus_flags(events); + dbus_watch_handle(nat->watchData[i], flags); + nat->pollData[i].revents = 0; + // can only do one - it may have caused a 'remove' + break; } } while (dbus_connection_dispatch(nat->conn) == diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp index 923e1aa..98f4e03 100644 --- a/core/jni/android_text_format_Time.cpp +++ b/core/jni/android_text_format_Time.cpp @@ -23,7 +23,7 @@ #include "jni.h" #include "utils/misc.h" #include "android_runtime/AndroidRuntime.h" -#include <utils/TimeUtils.h> +#include "TimeUtils.h" #include <nativehelper/JNIHelp.h> #include <cutils/tztime.h> @@ -44,6 +44,7 @@ static jfieldID g_timezoneField = 0; static jfieldID g_shortMonthsField = 0; static jfieldID g_longMonthsField = 0; +static jfieldID g_longStandaloneMonthsField = 0; static jfieldID g_shortWeekdaysField = 0; static jfieldID g_longWeekdaysField = 0; static jfieldID g_timeOnlyFormatField = 0; @@ -193,6 +194,7 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This, static jobject js_locale_previous = NULL; static struct strftime_locale locale; static jstring js_mon[12], js_month[12], js_wday[7], js_weekday[7]; + static jstring js_standalone_month[12]; static jstring js_X_fmt, js_x_fmt, js_c_fmt, js_am, js_pm, js_date_fmt; Time t; @@ -206,8 +208,10 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This, for (int i = 0; i < 12; i++) { env->ReleaseStringUTFChars(js_mon[i], locale.mon[i]); env->ReleaseStringUTFChars(js_month[i], locale.month[i]); + env->ReleaseStringUTFChars(js_standalone_month[i], locale.standalone_month[i]); env->DeleteGlobalRef(js_mon[i]); env->DeleteGlobalRef(js_month[i]); + env->DeleteGlobalRef(js_standalone_month[i]); } for (int i = 0; i < 7; i++) { @@ -245,6 +249,12 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This, locale.month[i] = env->GetStringUTFChars(js_month[i], NULL); } + ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField); + for (int i = 0; i < 12; i++) { + js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i)); + locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL); + } + ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField); for (int i = 0; i < 7; i++) { js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i)); @@ -639,6 +649,7 @@ int register_android_text_format_Time(JNIEnv* env) g_shortMonthsField = env->GetStaticFieldID(timeClass, "sShortMonths", "[Ljava/lang/String;"); g_longMonthsField = env->GetStaticFieldID(timeClass, "sLongMonths", "[Ljava/lang/String;"); + g_longStandaloneMonthsField = env->GetStaticFieldID(timeClass, "sLongStandaloneMonths", "[Ljava/lang/String;"); g_shortWeekdaysField = env->GetStaticFieldID(timeClass, "sShortWeekdays", "[Ljava/lang/String;"); g_longWeekdaysField = env->GetStaticFieldID(timeClass, "sLongWeekdays", "[Ljava/lang/String;"); g_timeOnlyFormatField = env->GetStaticFieldID(timeClass, "sTimeOnlyFormat", "Ljava/lang/String;"); diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index d147bcc..2d90ba4 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -535,7 +535,7 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c jint keyboard, jint keyboardHidden, jint navigation, jint screenWidth, jint screenHeight, - jint sdkVersion) + jint screenLayout, jint sdkVersion) { AssetManager* am = assetManagerForJavaObject(env, clazz); if (am == NULL) { @@ -557,6 +557,7 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c config.navigation = (uint8_t)navigation; config.screenWidth = (uint16_t)screenWidth; config.screenHeight = (uint16_t)screenHeight; + config.screenLayout = (uint8_t)screenLayout; config.sdkVersion = (uint16_t)sdkVersion; config.minorVersion = 0; am->setConfiguration(config, locale8); @@ -1567,7 +1568,7 @@ static JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_setLocale }, { "getLocales", "()[Ljava/lang/String;", (void*) android_content_AssetManager_getLocales }, - { "setConfiguration", "(IILjava/lang/String;IIIIIIIII)V", + { "setConfiguration", "(IILjava/lang/String;IIIIIIIIII)V", (void*) android_content_AssetManager_setConfiguration }, { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void*) android_content_AssetManager_getResourceIdentifier }, diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index d760feb..aee0ed7 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -50,8 +50,6 @@ pid_t gettid() { return syscall(__NR_gettid);} #undef __KERNEL__ #endif -#define ENABLE_CGROUP_ERR_LOGGING 0 - /* * List of cgroup names which map to ANDROID_TGROUP_ values in Thread.h * and Process.java @@ -198,50 +196,82 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name) static int add_pid_to_cgroup(int pid, int grp) { - FILE *fp; + int fd; char path[255]; - int rc; + char text[64]; - sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup_names[grp] ? cgroup_names[grp] : "")); + sprintf(path, "/dev/cpuctl/%s/tasks", + (cgroup_names[grp] ? cgroup_names[grp] : "")); - if (!(fp = fopen(path, "w"))) { -#if ENABLE_CGROUP_ERR_LOGGING - LOGW("Unable to open %s (%s)\n", path, strerror(errno)); -#endif - return -errno; + if ((fd = open(path, O_WRONLY)) < 0) + return -1; + + sprintf(text, "%d", pid); + if (write(fd, text, strlen(text)) < 0) { + close(fd); + return -1; } - rc = fprintf(fp, "%d", pid); - fclose(fp); + close(fd); + return 0; +} - if (rc < 0) { -#if ENABLE_CGROUP_ERR_LOGGING - LOGW("Unable to move pid %d to cgroup %s (%s)\n", pid, - (cgroup_names[grp] ? cgroup_names[grp] : "<default>"), - strerror(errno)); -#endif +void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp) +{ + if (grp > ANDROID_TGROUP_MAX || grp < 0) { + signalExceptionForGroupError(env, clazz, EINVAL); + return; } - return (rc < 0) ? errno : 0; + if (add_pid_to_cgroup(pid, grp)) { + // If the thread exited on us, don't generate an exception + if (errno != ESRCH && errno != ENOENT) + signalExceptionForGroupError(env, clazz, errno); + } } -void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp) +void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) { + DIR *d; + FILE *fp; + char proc_path[255]; + struct dirent *de; + if (grp > ANDROID_TGROUP_MAX || grp < 0) { signalExceptionForGroupError(env, clazz, EINVAL); return; } - if (add_pid_to_cgroup(pid, grp)) - signalExceptionForGroupError(env, clazz, errno); + sprintf(proc_path, "/proc/%d/task", pid); + if (!(d = opendir(proc_path))) { + // If the process exited on us, don't generate an exception + if (errno != ENOENT) + signalExceptionForGroupError(env, clazz, errno); + return; + } + + while ((de = readdir(d))) { + if (de->d_name[0] == '.') + continue; + + if (add_pid_to_cgroup(atoi(de->d_name), grp)) { + // If the thread exited on us, ignore it and keep going + if (errno != ESRCH && errno != ENOENT) { + signalExceptionForGroupError(env, clazz, errno); + closedir(d); + return; + } + } + } + closedir(d); } void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, jint pid, jint pri) { - if (pri == ANDROID_PRIORITY_BACKGROUND) { + if (pri >= ANDROID_PRIORITY_BACKGROUND) { add_pid_to_cgroup(pid, ANDROID_TGROUP_BG_NONINTERACT); - } else if (getpriority(PRIO_PROCESS, pid) == ANDROID_PRIORITY_BACKGROUND) { + } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) { add_pid_to_cgroup(pid, ANDROID_TGROUP_DEFAULT); } @@ -466,7 +496,7 @@ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileSt const String8& field = fields[i]; if (strncmp(p, field.string(), field.length()) == 0) { p += field.length(); - while (*p == ' ') p++; + while (*p == ' ' || *p == '\t') p++; char* num = p; while (*p >= '0' && *p <= '9') p++; skipToEol = *p != '\n'; @@ -820,6 +850,7 @@ static const JNINativeMethod methods[] = { {"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority}, {"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority}, {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, + {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, {"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj}, {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0}, {"setUid", "(I)I", (void*)android_os_Process_setUid}, diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp index 11822e0..89b1f96 100644 --- a/core/jni/com_google_android_gles_jni_GLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp @@ -45,9 +45,11 @@ static jclass OOMEClass; static jclass UOEClass; static jclass IAEClass; static jclass AIOOBEClass; +static jclass G11ImplClass; static jmethodID getBasePointerID; static jmethodID getBaseArrayID; static jmethodID getBaseArrayOffsetID; +static jmethodID allowIndirectBuffersID; static jfieldID positionID; static jfieldID limitID; static jfieldID elementSizeShiftID; @@ -63,13 +65,17 @@ nativeClassInitBuffer(JNIEnv *_env) jclass bufferClassLocal = _env->FindClass("java/nio/Buffer"); bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal); + jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl"); + G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal); + getBasePointerID = _env->GetStaticMethodID(nioAccessClass, "getBasePointer", "(Ljava/nio/Buffer;)J"); getBaseArrayID = _env->GetStaticMethodID(nioAccessClass, "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;"); getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass, "getBaseArrayOffset", "(Ljava/nio/Buffer;)I"); - + allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal, + "allowIndirectBuffers", "(Ljava/lang/String;)Z"); positionID = _env->GetFieldID(bufferClass, "position", "I"); limitID = _env->GetFieldID(bufferClass, "limit", "I"); elementSizeShiftID = @@ -119,6 +125,9 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining) *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass, getBaseArrayID, buffer); + if (*array == NULL) { + return (void*) NULL; + } offset = _env->CallStaticIntMethod(nioAccessClass, getBaseArrayOffsetID, buffer); data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0); @@ -133,6 +142,45 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) commit ? 0 : JNI_ABORT); } +extern "C" { +extern char* __progname; +} + +static bool +allowIndirectBuffers(JNIEnv *_env) { + static jint sIndirectBufferCompatability; + if (sIndirectBufferCompatability == 0) { + jobject appName = _env->NewStringUTF(::__progname); + sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1; + } + return sIndirectBufferCompatability == 2; +} + +static void * +getDirectBufferPointer(JNIEnv *_env, jobject buffer) { + if (!buffer) { + return NULL; + } + void* buf = _env->GetDirectBufferAddress(buffer); + if (buf) { + jint position = _env->GetIntField(buffer, positionID); + jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID); + buf = ((char*) buf) + (position << elementSizeShift); + } else { + if (allowIndirectBuffers(_env)) { + jarray array = 0; + jint remaining; + buf = getPointer(_env, buffer, &array, &remaining); + if (array) { + releasePointer(_env, array, buf, 0); + } + } else { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + } + } + return buf; +} + static int getNumCompressedTextureFormats() { int numCompressedTextureFormats = 0; @@ -305,9 +353,8 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -2779,9 +2826,8 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -3034,9 +3080,8 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } @@ -3392,9 +3437,8 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I GLvoid *pointer = (GLvoid *) 0; if (pointer_buf) { - pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + pointer = (GLvoid *) getDirectBufferPointer(_env, pointer_buf); if ( ! pointer ) { - _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); return; } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index bff6b9d..599360f 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 --> <!-- ======================================= --> @@ -220,12 +236,6 @@ android:label="@string/permlab_installLocationProvider" android:description="@string/permdesc_installLocationProvider" /> - <!-- Allows an application to install a location collector into the Location Manager --> - <permission android:name="android.permission.INSTALL_LOCATION_COLLECTOR" - android:protectionLevel="signatureOrSystem" - android:label="@string/permlab_installLocationCollector" - android:description="@string/permdesc_installLocationCollector" /> - <!-- ======================================= --> <!-- Permissions for accessing networks --> <!-- ======================================= --> @@ -388,12 +398,12 @@ android:label="@string/permgrouplab_storage" android:description="@string/permgroupdesc_storage" /> - <!-- Allows an application to write to the SD card --> - <permission android:name="android.permission.SDCARD_WRITE" + <!-- Allows an application to write to external storage --> + <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:permissionGroup="android.permission-group.STORAGE" android:label="@string/permlab_sdcardWrite" android:description="@string/permdesc_sdcardWrite" - android:protectionLevel="normal" /> + android:protectionLevel="dangerous" /> <!-- ============================================ --> <!-- Permissions for low-level system interaction --> @@ -650,6 +660,13 @@ android:description="@string/permdesc_changeWifiState" android:label="@string/permlab_changeWifiState" /> + <!-- Allows applications to enter Wi-Fi Multicast mode --> + <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="dangerous" + android:description="@string/permdesc_changeWifiMulticastState" + android:label="@string/permlab_changeWifiMulticastState" /> + <!-- Allows applications to discover and pair bluetooth devices --> <permission android:name="android.permission.BLUETOOTH_ADMIN" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" @@ -737,13 +754,6 @@ android:description="@string/permdesc_statusBar" android:protectionLevel="signatureOrSystem" /> - <!-- Allows an application to force any currently running process to be - in the foreground. --> - <permission android:name="android.permission.SET_PROCESS_FOREGROUND" - android:label="@string/permlab_setProcessForeground" - android:description="@string/permdesc_setProcessForeground" - android:protectionLevel="signature" /> - <!-- Allows an application to force a BACK operation on whatever is the top activity. --> <permission android:name="android.permission.FORCE_BACK" @@ -751,19 +761,6 @@ android:description="@string/permdesc_forceBack" android:protectionLevel="signature" /> - <!-- Allows an application to publish system-level services. Such services - can only be published from processes that never go away, so this is - not something that any normal application can do. --> - <permission android:name="android.permission.ADD_SYSTEM_SERVICE" - android:label="@string/permlab_addSystemService" - android:description="@string/permdesc_addSystemService" - android:protectionLevel="signature" /> - - <permission android:name="android.permission.FOTA_UPDATE" - android:label="@string/permlab_fotaUpdate" - android:description="@string/permdesc_fotaUpdate" - android:protectionLevel="signature" /> - <!-- Allows an application to update device statistics. Not for use by third party apps. --> <permission android:name="android.permission.UPDATE_DEVICE_STATS" @@ -803,14 +800,22 @@ android:description="@string/permdesc_runSetActivityWatcher" android:protectionLevel="signature" /> - <!-- Allows an application to watch and control how activities are - started globally in the system. Only for is in debugging - (usually the monkey command). --> + <!-- Allows an application to call the activity manager shutdown() API + to put the higher-level system there into a shutdown state. --> <permission android:name="android.permission.SHUTDOWN" android:label="@string/permlab_shutdown" android:description="@string/permdesc_shutdown" android:protectionLevel="signature" /> + <!-- Allows an application to tell the activity manager to temporarily + stop application switches, putting it into a special mode that + prevents applications from immediately switching away from some + critical UI such as the home screen. --> + <permission android:name="android.permission.STOP_APP_SWITCHES" + android:label="@string/permlab_stopAppSwitches" + android:description="@string/permdesc_stopAppSwitches" + android:protectionLevel="signature" /> + <!-- Allows an application to retrieve the current state of keys and switches. This is only for use by the system.--> <permission android:name="android.permission.READ_INPUT_STATE" @@ -963,6 +968,13 @@ android:description="@string/permdesc_batteryStats" android:protectionLevel="normal" /> + <!-- Allows an application to control the backup and restore process + @hide pending API council --> + <permission android:name="android.permission.BACKUP" + android:label="@string/permlab_backup" + android:description="@string/permdesc_backup" + android:protectionLevel="signatureOrSystem" /> + <!-- Allows an application to tell the AppWidget service which application can access AppWidget's data. The normal user flow is that a user picks an AppWidget to go into a particular host, thereby giving that @@ -973,7 +985,7 @@ android:permissionGroup="android.permission-group.PERSONAL_INFO" android:label="@string/permlab_bindGadget" android:description="@string/permdesc_bindGadget" - android:protectionLevel="signature" /> + android:protectionLevel="signatureOrSystem" /> <!-- Allows applications to change the background data setting @hide pending API council --> @@ -988,6 +1000,7 @@ android:hasCode="false" android:label="@string/android_system_label" android:allowClearUserData="false" + android:backupAgent="com.android.internal.backup.SystemBackupAgent" android:icon="@drawable/ic_launcher_android"> <activity android:name="com.android.internal.app.ChooserActivity" android:theme="@style/Theme.Dialog.Alert" diff --git a/core/res/res/anim/slide_in_up.xml b/core/res/res/anim/slide_in_up.xml new file mode 100644 index 0000000..bf471c3 --- /dev/null +++ b/core/res/res/anim/slide_in_up.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<translate + xmlns:android="http://schemas.android.com/apk/res/android" + + android:fromYDelta="100%p" + android:toYDelta="0" + + android:duration="@android:integer/config_longAnimTime" /> diff --git a/core/res/res/anim/slide_out_down.xml b/core/res/res/anim/slide_out_down.xml new file mode 100644 index 0000000..9b8d5b7 --- /dev/null +++ b/core/res/res/anim/slide_out_down.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<translate + xmlns:android="http://schemas.android.com/apk/res/android" + + android:fromYDelta="0" + android:toYDelta="100%p" + + android:duration="@android:integer/config_longAnimTime" /> diff --git a/core/res/res/drawable/call_contact.png b/core/res/res/drawable/call_contact.png Binary files differnew file mode 100644 index 0000000..1abeb5d --- /dev/null +++ b/core/res/res/drawable/call_contact.png diff --git a/core/res/res/drawable/create_contact.png b/core/res/res/drawable/create_contact.png Binary files differnew file mode 100644 index 0000000..5c5718b --- /dev/null +++ b/core/res/res/drawable/create_contact.png diff --git a/core/res/res/drawable/progress.xml b/core/res/res/drawable/progress.xml deleted file mode 100644 index d270520..0000000 --- a/core/res/res/drawable/progress.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/res/drawable/progress.xml -** -** Copyright 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. -*/ ---> - -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:drawable="@android:drawable/progress_circular_background" /> - <item> - <shape android:shape="ring" - android:innerRadiusRatio="3.4" - android:thicknessRatio="6.0"> - <gradient - android:useLevel="true" - android:type="sweep" - android:startColor="#ff000000" - android:endColor="#ffffffff" /> - </shape> - </item> - <item> - <rotate - android:pivotX="50%" android:pivotY="50%" - android:fromDegrees="0" android:toDegrees="360" - android:drawable="@android:drawable/progress_particle" /> - </item> -</layer-list> diff --git a/core/res/res/drawable/progress_circular_background.png b/core/res/res/drawable/progress_circular_background.png Binary files differdeleted file mode 100644 index 7c637fd..0000000 --- a/core/res/res/drawable/progress_circular_background.png +++ /dev/null diff --git a/core/res/res/drawable/progress_circular_background_small.png b/core/res/res/drawable/progress_circular_background_small.png Binary files differdeleted file mode 100644 index 6b8ba9b..0000000 --- a/core/res/res/drawable/progress_circular_background_small.png +++ /dev/null diff --git a/core/res/res/drawable/progress_circular_indeterminate.png b/core/res/res/drawable/progress_circular_indeterminate.png Binary files differdeleted file mode 100644 index 125a264..0000000 --- a/core/res/res/drawable/progress_circular_indeterminate.png +++ /dev/null diff --git a/core/res/res/drawable/progress_large.xml b/core/res/res/drawable/progress_large.xml index 4669104..4f016bc 100644 --- a/core/res/res/drawable/progress_large.xml +++ b/core/res/res/drawable/progress_large.xml @@ -1,45 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- 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. +<!-- +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ --> - - -<rotate xmlns:android="http://schemas.android.com/apk/res/android" - android:pivotX="50%" android:pivotY="50%" - android:fromDegrees="0" android:toDegrees="360"> - - <shape - android:shape="ring" - android:innerRadiusRatio="3" - android:thicknessRatio="8" - android:useLevel="false"> - - <size - android:width="76dip" - android:height="76dip" - /> - - <gradient - android:type="sweep" - android:useLevel="false" - android:startColor="#4c737373" - android:centerColor="#4c737373" - android:centerY="0.50" - android:endColor="#ffffd300" - /> - - </shape> - -</rotate> - +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_black_76" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/java/android/app/IIntentSender.aidl b/core/res/res/drawable/progress_large_white.xml index 53e135a..c690ed4 100644 --- a/core/java/android/app/IIntentSender.aidl +++ b/core/res/res/drawable/progress_large_white.xml @@ -1,6 +1,8 @@ -/* //device/java/android/android/app/IActivityPendingResult.aidl +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* ** -** Copyright 2007, The Android Open Source Project +** Copyright 2009, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -14,14 +16,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ - -package android.app; - -import android.app.IIntentReceiver; -import android.content.Intent; - -/** @hide */ -interface IIntentSender { - int send(int code, in Intent intent, String resolvedType, - IIntentReceiver finishedReceiver); -} +--> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_white_76" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/progress_medium.xml b/core/res/res/drawable/progress_medium.xml index 92aebb5..eb1bd50 100644 --- a/core/res/res/drawable/progress_medium.xml +++ b/core/res/res/drawable/progress_medium.xml @@ -1,43 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- 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. +<!-- +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ --> - -<rotate xmlns:android="http://schemas.android.com/apk/res/android" - android:pivotX="50%" android:pivotY="50%" - android:fromDegrees="0" android:toDegrees="360"> - - <shape - android:shape="ring" - android:innerRadiusRatio="3" - android:thicknessRatio="8" - android:useLevel="false"> - - <size - android:width="48dip" - android:height="48dip" - /> - - <gradient - android:type="sweep" - android:useLevel="false" - android:startColor="#4c737373" - android:centerColor="#4c737373" - android:centerY="0.50" - android:endColor="#ffffd300" - /> - - </shape> - -</rotate> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_black_48" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/progress_indeterminate.xml b/core/res/res/drawable/progress_medium_white.xml index 1bf715e..b4f9b31 100644 --- a/core/res/res/drawable/progress_indeterminate.xml +++ b/core/res/res/drawable/progress_medium_white.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -/* //device/apps/common/res/drawable/progress.xml +/* ** -** Copyright 2007, The Android Open Source Project +** Copyright 2009, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -17,16 +17,9 @@ ** limitations under the License. */ --> - -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item - android:drawable="@android:drawable/progress_circular_background" /> - - <item><rotate - android:pivotX="50%" - android:pivotY="50%" - android:fromDegrees="0" - android:toDegrees="360" - android:drawable="@android:drawable/progress_circular_indeterminate" /> - </item> -</layer-list> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_white_48" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/progress_small.xml b/core/res/res/drawable/progress_small.xml index e5b0021..e0ee5e4 100644 --- a/core/res/res/drawable/progress_small.xml +++ b/core/res/res/drawable/progress_small.xml @@ -1,45 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- 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. +<!-- +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ --> - - -<rotate xmlns:android="http://schemas.android.com/apk/res/android" - android:pivotX="50%" android:pivotY="50%" - android:fromDegrees="0" android:toDegrees="360"> - - <!-- An extra pixel is added on both ratios for stroke --> - <shape - android:shape="ring" - android:innerRadiusRatio="3.2" - android:thicknessRatio="5.333" - android:useLevel="false"> - - <size - android:width="16dip" - android:height="16dip" - /> - - <gradient - android:type="sweep" - android:useLevel="false" - android:startColor="#4c737373" - android:centerColor="#4c737373" - android:centerY="0.50" - android:endColor="#ffffd300" - /> - - </shape> - -</rotate> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_black_16" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/progress_small_titlebar.xml b/core/res/res/drawable/progress_small_titlebar.xml index cf8e41c..8cfba86 100644 --- a/core/res/res/drawable/progress_small_titlebar.xml +++ b/core/res/res/drawable/progress_small_titlebar.xml @@ -1,45 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- 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. +<!-- +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ --> - - -<rotate xmlns:android="http://schemas.android.com/apk/res/android" - android:pivotX="50%" android:pivotY="50%" - android:fromDegrees="0" android:toDegrees="360"> - - <!-- An extra pixel is added on both ratios for stroke --> - <shape - android:shape="ring" - android:innerRadiusRatio="3.2" - android:thicknessRatio="5.333" - android:useLevel="false"> - - <size - android:width="16dip" - android:height="16dip" - /> - - <gradient - android:type="sweep" - android:useLevel="false" - android:startColor="#ff666666" - android:centerColor="#ff666666" - android:centerY="0.50" - android:endColor="#ffffd300" - /> - - </shape> - -</rotate> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_white_16" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/java/android/app/IIntentReceiver.aidl b/core/res/res/drawable/progress_small_white.xml index 5f5d0eb..8cfba86 100755..100644 --- a/core/java/android/app/IIntentReceiver.aidl +++ b/core/res/res/drawable/progress_small_white.xml @@ -1,6 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- /* ** -** Copyright 2006, The Android Open Source Project +** Copyright 2009, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -14,20 +16,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -package android.app; - -import android.content.Intent; -import android.os.Bundle; - -/** - * System private API for dispatching intent broadcasts. This is given to the - * activity manager as part of registering for an intent broadcasts, and is - * called when it receives intents. - * - * {@hide} - */ -oneway interface IIntentReceiver { - void performReceive(in Intent intent, int resultCode, - String data, in Bundle extras, boolean ordered); -} - +--> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_white_16" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/rate_star_big_half.png b/core/res/res/drawable/rate_star_big_half.png Binary files differindex e73ca79..9762292 100644 --- a/core/res/res/drawable/rate_star_big_half.png +++ b/core/res/res/drawable/rate_star_big_half.png diff --git a/core/res/res/drawable/rate_star_big_off.png b/core/res/res/drawable/rate_star_big_off.png Binary files differindex b4dfa9d..6b5039f 100644 --- a/core/res/res/drawable/rate_star_big_off.png +++ b/core/res/res/drawable/rate_star_big_off.png diff --git a/core/res/res/drawable/rate_star_big_on.png b/core/res/res/drawable/rate_star_big_on.png Binary files differindex 7442c93..a972db2 100644 --- a/core/res/res/drawable/rate_star_big_on.png +++ b/core/res/res/drawable/rate_star_big_on.png 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 56b697d..0000000 --- a/core/res/res/drawable/search_dropdown_background_apps.9.png +++ /dev/null diff --git a/core/res/res/drawable/search_spinner.xml b/core/res/res/drawable/search_spinner.xml new file mode 100644 index 0000000..31a77c3 --- /dev/null +++ b/core/res/res/drawable/search_spinner.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/spinner_black_20" + android:pivotX="50%" + android:pivotY="50%" + android:framesCount="12" + android:frameDuration="100" /> diff --git a/core/res/res/drawable/spinner_black_16.png b/core/res/res/drawable/spinner_black_16.png Binary files differnew file mode 100644 index 0000000..5ee33ce --- /dev/null +++ b/core/res/res/drawable/spinner_black_16.png diff --git a/core/res/res/drawable/spinner_black_20.png b/core/res/res/drawable/spinner_black_20.png Binary files differnew file mode 100755 index 0000000..e55b60d --- /dev/null +++ b/core/res/res/drawable/spinner_black_20.png diff --git a/core/res/res/drawable/spinner_black_48.png b/core/res/res/drawable/spinner_black_48.png Binary files differnew file mode 100644 index 0000000..3a68192 --- /dev/null +++ b/core/res/res/drawable/spinner_black_48.png diff --git a/core/res/res/drawable/spinner_black_76.png b/core/res/res/drawable/spinner_black_76.png Binary files differnew file mode 100644 index 0000000..ec57460 --- /dev/null +++ b/core/res/res/drawable/spinner_black_76.png diff --git a/core/res/res/drawable/progress_particle.png b/core/res/res/drawable/spinner_white_16.png Binary files differindex 9160108..dd2e1fd 100644 --- a/core/res/res/drawable/progress_particle.png +++ b/core/res/res/drawable/spinner_white_16.png diff --git a/core/res/res/drawable/spinner_white_48.png b/core/res/res/drawable/spinner_white_48.png Binary files differnew file mode 100644 index 0000000..d25a33e --- /dev/null +++ b/core/res/res/drawable/spinner_white_48.png diff --git a/core/res/res/drawable/spinner_white_76.png b/core/res/res/drawable/spinner_white_76.png Binary files differnew file mode 100644 index 0000000..f53e8ff --- /dev/null +++ b/core/res/res/drawable/spinner_white_76.png diff --git a/core/res/res/drawable/stat_ecb_mode.png b/core/res/res/drawable/stat_ecb_mode.png Binary files differnew file mode 100644 index 0000000..a948770 --- /dev/null +++ b/core/res/res/drawable/stat_ecb_mode.png diff --git a/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png Binary files differnew file mode 100755 index 0000000..11c2eae --- /dev/null +++ b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png diff --git a/core/res/res/drawable/stat_sys_data_dormant_evdo.png b/core/res/res/drawable/stat_sys_data_dormant_evdo.png Binary files differnew file mode 100755 index 0000000..811fcb5 --- /dev/null +++ b/core/res/res/drawable/stat_sys_data_dormant_evdo.png diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_0.png b/core/res/res/drawable/stat_sys_roaming_cdma_0.png Binary files differnew file mode 100755 index 0000000..c61cce7 --- /dev/null +++ b/core/res/res/drawable/stat_sys_roaming_cdma_0.png diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml new file mode 100644 index 0000000..07dc446 --- /dev/null +++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/drawable/stat_sys_battery.xml +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim0" android:duration="800" /> + <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim1" android:duration="1200" /> +</animation-list> diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png Binary files differnew file mode 100755 index 0000000..d62502d --- /dev/null +++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png Binary files differnew file mode 100755 index 0000000..c61cce7 --- /dev/null +++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png diff --git a/core/res/res/drawable/stat_sys_signal_cdma_0.png b/core/res/res/drawable/stat_sys_signal_cdma_0.png Binary files differnew file mode 100755 index 0000000..0ef7d53 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_cdma_0.png diff --git a/core/res/res/drawable/stat_sys_signal_cdma_1.png b/core/res/res/drawable/stat_sys_signal_cdma_1.png Binary files differnew file mode 100755 index 0000000..f4839d4 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_cdma_1.png diff --git a/core/res/res/drawable/stat_sys_signal_cdma_2.png b/core/res/res/drawable/stat_sys_signal_cdma_2.png Binary files differnew file mode 100755 index 0000000..e25a99c --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_cdma_2.png diff --git a/core/res/res/drawable/stat_sys_signal_cdma_3.png b/core/res/res/drawable/stat_sys_signal_cdma_3.png Binary files differnew file mode 100755 index 0000000..d828d99 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_cdma_3.png diff --git a/core/res/res/drawable/stat_sys_signal_cdma_4.png b/core/res/res/drawable/stat_sys_signal_cdma_4.png Binary files differnew file mode 100755 index 0000000..53a31ea --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_cdma_4.png diff --git a/core/res/res/drawable/stat_sys_signal_evdo_0.png b/core/res/res/drawable/stat_sys_signal_evdo_0.png Binary files differnew file mode 100755 index 0000000..1b8aec7 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_evdo_0.png diff --git a/core/res/res/drawable/stat_sys_signal_evdo_1.png b/core/res/res/drawable/stat_sys_signal_evdo_1.png Binary files differnew file mode 100755 index 0000000..7ce01fd --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_evdo_1.png diff --git a/core/res/res/drawable/stat_sys_signal_evdo_2.png b/core/res/res/drawable/stat_sys_signal_evdo_2.png Binary files differnew file mode 100755 index 0000000..890cd59 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_evdo_2.png diff --git a/core/res/res/drawable/stat_sys_signal_evdo_3.png b/core/res/res/drawable/stat_sys_signal_evdo_3.png Binary files differnew file mode 100755 index 0000000..712c640 --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_evdo_3.png diff --git a/core/res/res/drawable/stat_sys_signal_evdo_4.png b/core/res/res/drawable/stat_sys_signal_evdo_4.png Binary files differnew file mode 100755 index 0000000..f0537dd --- /dev/null +++ b/core/res/res/drawable/stat_sys_signal_evdo_4.png diff --git a/core/res/res/drawable/stat_sys_vp_phone_call_bluetooth.png b/core/res/res/drawable/stat_sys_vp_phone_call_bluetooth.png Binary files differnew file mode 100644 index 0000000..7abfd19 --- /dev/null +++ b/core/res/res/drawable/stat_sys_vp_phone_call_bluetooth.png diff --git a/core/res/res/layout/character_picker.xml b/core/res/res/layout/character_picker.xml index bb4955a..0344849 100644 --- a/core/res/res/layout/character_picker.xml +++ b/core/res/res/layout/character_picker.xml @@ -23,8 +23,8 @@ android:id="@+id/characterPicker" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="12dp" - android:verticalSpacing="8dp" + android:padding="4dp" + android:verticalSpacing="4dp" android:horizontalSpacing="8dp" android:stretchMode="spacingWidth" android:gravity="left" diff --git a/core/res/res/layout/google_web_content_helper_layout.xml b/core/res/res/layout/google_web_content_helper_layout.xml index 40f84bf..546c458 100644 --- a/core/res/res/layout/google_web_content_helper_layout.xml +++ b/core/res/res/layout/google_web_content_helper_layout.xml @@ -18,10 +18,28 @@ android:foregroundGravity="center" android:measureAllChildren="false"> - <!-- Include the indeterminate progress dialog's layout. --> - <include - android:id="@+id/progressContainer" - layout="@android:layout/progress_dialog" /> + <LinearLayout android:id="@+id/progressContainer" + android:orientation="horizontal" + android:layout_gravity="center" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:baselineAligned="false" + android:paddingLeft="8dip" + android:paddingTop="10dip" + android:paddingRight="8dip" + android:paddingBottom="10dip"> + + <ProgressBar android:id="@android:id/progress" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:max="10000" + android:layout_marginRight="12dip" /> + + <TextView android:id="@+id/message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> + </LinearLayout> <WebView android:id="@+id/web" diff --git a/core/res/res/layout/list_gestures_overlay.xml b/core/res/res/layout/list_gestures_overlay.xml new file mode 100644 index 0000000..54d72c8 --- /dev/null +++ b/core/res/res/layout/list_gestures_overlay.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> diff --git a/core/res/res/layout/progress_dialog.xml b/core/res/res/layout/progress_dialog.xml index 2d7afd6..8f66451 100644 --- a/core/res/res/layout/progress_dialog.xml +++ b/core/res/res/layout/progress_dialog.xml @@ -33,6 +33,7 @@ android:paddingBottom="10dip"> <ProgressBar android:id="@android:id/progress" + style="@android:style/Widget.ProgressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:max="10000" diff --git a/core/res/res/layout/recent_apps_dialog.xml b/core/res/res/layout/recent_apps_dialog.xml index 852b2f1..c4ee95d 100644 --- a/core/res/res/layout/recent_apps_dialog.xml +++ b/core/res/res/layout/recent_apps_dialog.xml @@ -17,67 +17,63 @@ */ --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" - android:layout_height="wrap_content"> - + android:layout_height="wrap_content" + android:padding="3dip" + android:orientation="vertical"> + + <!-- This is only intended to be visible when all buttons (below) are invisible --> + <TextView + android:id="@+id/no_applications_message" + android:layout_width="285dip" + android:layout_height="wrap_content" + android:layout_marginTop="15dip" + android:layout_marginBottom="15dip" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="@android:string/no_recent_tasks" /> + + <!-- The first row has a fixed-width because the UI spec requires the box + to display with full-width no matter how many icons are visible, but to + adjust height based on number of rows. --> + <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs --> + <LinearLayout + android:layout_width="285dip" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button1" /> + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button2" /> + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button3" /> + + </LinearLayout> + <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="3dip" - android:orientation="vertical"> - - <!-- This is only intended to be visible when all buttons (below) are invisible --> - <TextView - android:id="@+id/no_applications_message" - android:layout_width="285dip" - android:layout_height="wrap_content" - android:layout_marginTop="15dip" - android:layout_marginBottom="15dip" - android:gravity="center" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@android:string/no_recent_tasks" /> - - <!-- The first row has a fixed-width because the UI spec requires the box - to display with full-width no matter how many icons are visible, but to - adjust height based on number of rows. --> - <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs --> - <LinearLayout - android:layout_width="285dip" - android:layout_height="wrap_content" - android:orientation="horizontal" > + android:orientation="horizontal" > + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button4" /> + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button5" /> + + <include + layout="@android:layout/recent_apps_icon" + android:id="@+id/button6" /> - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button1" /> - - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button2" /> - - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button3" /> - - </LinearLayout> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" > - - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button4" /> - - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button5" /> - - <include - layout="@android:layout/recent_apps_icon" - android:id="@+id/button6" /> - - </LinearLayout> </LinearLayout> -</FrameLayout> +</LinearLayout>
\ No newline at end of file diff --git a/core/res/res/layout/recent_apps_icon.xml b/core/res/res/layout/recent_apps_icon.xml index b8cf089..d32643c 100644 --- a/core/res/res/layout/recent_apps_icon.xml +++ b/core/res/res/layout/recent_apps_icon.xml @@ -18,27 +18,22 @@ --> <!-- This is not a standalone element - it is imported into recent_apps_dialog.xml --> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/label" + style="?android:attr/buttonStyle" + android:background="@drawable/btn_application_selector" android:layout_width="87dip" - android:layout_height="78dip" + android:layout_height="88dip" android:layout_margin="3dip" - android:orientation="vertical" - android:gravity="center_vertical" - style="?android:attr/buttonStyle" - android:background="@drawable/btn_application_selector"> - <ImageView android:id="@+id/icon" - android:layout_width="@android:dimen/app_icon_size" - android:layout_height="@android:dimen/app_icon_size" - android:layout_gravity="center_horizontal" - android:scaleType="fitCenter" /> - <TextView android:id="@+id/label" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textSize="12dip" - android:maxLines="1" - android:ellipsize="end" - android:duplicateParentState="true" - android:textColor="@color/primary_text_dark_focused" - android:gravity="center_horizontal" /> -</LinearLayout> + android:textColor="@color/primary_text_dark_focused" + + android:paddingTop="5dip" + android:paddingBottom="2dip" + android:drawablePadding="0dip" + + android:textSize="13dip" + android:maxLines="2" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:gravity="top|center_horizontal" /> diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml index b512490..13e66aa 100644 --- a/core/res/res/layout/search_bar.xml +++ b/core/res/res/layout/search_bar.xml @@ -71,9 +71,12 @@ android:layout_weight="1.0" android:paddingLeft="8dip" 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/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml index 0d07490..2710b3b 100644 --- a/core/res/res/layout/search_dropdown_item_icons_2line.xml +++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml @@ -67,13 +67,10 @@ android:textAppearance="?android:attr/textAppearanceSearchResultTitle" android:singleLine="true" android:layout_width="fill_parent" - android:layout_height="29dip" - android:paddingTop="4dip" - android:gravity="center_vertical" - android:layout_alignParentTop="true" + android:layout_height="wrap_content" + android:layout_centerVertical="true" android:layout_toRightOf="@android:id/icon1" android:layout_toLeftOf="@android:id/icon2" - android:layout_above="@android:id/text2" - android:layout_alignWithParentIfMissing="true" /> + android:layout_above="@android:id/text2" /> </RelativeLayout> diff --git a/core/res/res/values-ar-rEG/donottranslate-cldr.xml b/core/res/res/values-ar-rEG/donottranslate-cldr.xml new file mode 100644 index 0000000..2c20ffc --- /dev/null +++ b/core/res/res/values-ar-rEG/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">يناير</string> + <string name="month_long_standalone_february">فبراير</string> + <string name="month_long_standalone_march">مارس</string> + <string name="month_long_standalone_april">أبريل</string> + <string name="month_long_standalone_may">مايو</string> + <string name="month_long_standalone_june">يونيو</string> + <string name="month_long_standalone_july">يوليو</string> + <string name="month_long_standalone_august">أغسطس</string> + <string name="month_long_standalone_september">سبتمبر</string> + <string name="month_long_standalone_october">أكتوبر</string> + <string name="month_long_standalone_november">نوفمبر</string> + <string name="month_long_standalone_december">ديسمبر</string> + + <string name="month_long_january">يناير</string> + <string name="month_long_february">فبراير</string> + <string name="month_long_march">مارس</string> + <string name="month_long_april">أبريل</string> + <string name="month_long_may">مايو</string> + <string name="month_long_june">يونيو</string> + <string name="month_long_july">يوليو</string> + <string name="month_long_august">أغسطس</string> + <string name="month_long_september">سبتمبر</string> + <string name="month_long_october">أكتوبر</string> + <string name="month_long_november">نوفمبر</string> + <string name="month_long_december">ديسمبر</string> + + <string name="month_medium_january">يناير</string> + <string name="month_medium_february">فبراير</string> + <string name="month_medium_march">مارس</string> + <string name="month_medium_april">أبريل</string> + <string name="month_medium_may">مايو</string> + <string name="month_medium_june">يونيو</string> + <string name="month_medium_july">يوليو</string> + <string name="month_medium_august">أغسطس</string> + <string name="month_medium_september">سبتمبر</string> + <string name="month_medium_october">أكتوبر</string> + <string name="month_medium_november">نوفمبر</string> + <string name="month_medium_december">ديسمبر</string> + + <string name="month_shortest_january">ي</string> + <string name="month_shortest_february">ف</string> + <string name="month_shortest_march">م</string> + <string name="month_shortest_april">أ</string> + <string name="month_shortest_may">و</string> + <string name="month_shortest_june">ن</string> + <string name="month_shortest_july">ل</string> + <string name="month_shortest_august">غ</string> + <string name="month_shortest_september">س</string> + <string name="month_shortest_october">ك</string> + <string name="month_shortest_november">ب</string> + <string name="month_shortest_december">د</string> + + <string name="day_of_week_long_sunday">الأحد</string> + <string name="day_of_week_long_monday">الإثنين</string> + <string name="day_of_week_long_tuesday">الثلاثاء</string> + <string name="day_of_week_long_wednesday">الأربعاء</string> + <string name="day_of_week_long_thursday">الخميس</string> + <string name="day_of_week_long_friday">الجمعة</string> + <string name="day_of_week_long_saturday">السبت</string> + + <string name="day_of_week_medium_sunday">أحد</string> + <string name="day_of_week_medium_monday">إثنين</string> + <string name="day_of_week_medium_tuesday">ثلاثاء</string> + <string name="day_of_week_medium_wednesday">أربعاء</string> + <string name="day_of_week_medium_thursday">خميس</string> + <string name="day_of_week_medium_friday">جمعة</string> + <string name="day_of_week_medium_saturday">سبت</string> + + <string name="day_of_week_short_sunday">أحد</string> + <string name="day_of_week_short_monday">إثنين</string> + <string name="day_of_week_short_tuesday">ثلاثاء</string> + <string name="day_of_week_short_wednesday">أربعاء</string> + <string name="day_of_week_short_thursday">خميس</string> + <string name="day_of_week_short_friday">جمعة</string> + <string name="day_of_week_short_saturday">سبت</string> + + <string name="day_of_week_shortest_sunday">ح</string> + <string name="day_of_week_shortest_monday">ن</string> + <string name="day_of_week_shortest_tuesday">ث</string> + <string name="day_of_week_shortest_wednesday">ر</string> + <string name="day_of_week_shortest_thursday">خ</string> + <string name="day_of_week_shortest_friday">ج</string> + <string name="day_of_week_shortest_saturday">س</string> + + <string name="am">ص</string> + <string name="pm">م</string> + <string name="yesterday">أمس</string> + <string name="today">اليوم</string> + <string name="tomorrow">غدًا</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e/%-m/%Y</string> + <string name="numeric_date_format">d/M/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B، %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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، %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml new file mode 100644 index 0000000..b8b50cc --- /dev/null +++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">януари</string> + <string name="month_long_standalone_february">февруари</string> + <string name="month_long_standalone_march">март</string> + <string name="month_long_standalone_april">април</string> + <string name="month_long_standalone_may">май</string> + <string name="month_long_standalone_june">юни</string> + <string name="month_long_standalone_july">юли</string> + <string name="month_long_standalone_august">август</string> + <string name="month_long_standalone_september">септември</string> + <string name="month_long_standalone_october">октомври</string> + <string name="month_long_standalone_november">ноември</string> + <string name="month_long_standalone_december">декември</string> + + <string name="month_long_january">януари</string> + <string name="month_long_february">февруари</string> + <string name="month_long_march">март</string> + <string name="month_long_april">април</string> + <string name="month_long_may">май</string> + <string name="month_long_june">юни</string> + <string name="month_long_july">юли</string> + <string name="month_long_august">август</string> + <string name="month_long_september">септември</string> + <string name="month_long_october">октомври</string> + <string name="month_long_november">ноември</string> + <string name="month_long_december">декември</string> + + <string name="month_medium_january">ян.</string> + <string name="month_medium_february">февр.</string> + <string name="month_medium_march">март</string> + <string name="month_medium_april">апр.</string> + <string name="month_medium_may">май</string> + <string name="month_medium_june">юни</string> + <string name="month_medium_july">юли</string> + <string name="month_medium_august">авг.</string> + <string name="month_medium_september">септ.</string> + <string name="month_medium_october">окт.</string> + <string name="month_medium_november">ноем.</string> + <string name="month_medium_december">дек.</string> + + <string name="month_shortest_january">я</string> + <string name="month_shortest_february">ф</string> + <string name="month_shortest_march">м</string> + <string name="month_shortest_april">а</string> + <string name="month_shortest_may">м</string> + <string name="month_shortest_june">ю</string> + <string name="month_shortest_july">ю</string> + <string name="month_shortest_august">а</string> + <string name="month_shortest_september">с</string> + <string name="month_shortest_october">о</string> + <string name="month_shortest_november">н</string> + <string name="month_shortest_december">д</string> + + <string name="day_of_week_long_sunday">неделя</string> + <string name="day_of_week_long_monday">понеделник</string> + <string name="day_of_week_long_tuesday">вторник</string> + <string name="day_of_week_long_wednesday">сряда</string> + <string name="day_of_week_long_thursday">четвъртък</string> + <string name="day_of_week_long_friday">петък</string> + <string name="day_of_week_long_saturday">събота</string> + + <string name="day_of_week_medium_sunday">нд</string> + <string name="day_of_week_medium_monday">пн</string> + <string name="day_of_week_medium_tuesday">вт</string> + <string name="day_of_week_medium_wednesday">ср</string> + <string name="day_of_week_medium_thursday">чт</string> + <string name="day_of_week_medium_friday">пт</string> + <string name="day_of_week_medium_saturday">сб</string> + + <string name="day_of_week_short_sunday">нд</string> + <string name="day_of_week_short_monday">пн</string> + <string name="day_of_week_short_tuesday">вт</string> + <string name="day_of_week_short_wednesday">ср</string> + <string name="day_of_week_short_thursday">чт</string> + <string name="day_of_week_short_friday">пт</string> + <string name="day_of_week_short_saturday">сб</string> + + <string name="day_of_week_shortest_sunday">н</string> + <string name="day_of_week_shortest_monday">п</string> + <string name="day_of_week_shortest_tuesday">в</string> + <string name="day_of_week_shortest_wednesday">с</string> + <string name="day_of_week_shortest_thursday">ч</string> + <string name="day_of_week_shortest_friday">п</string> + <string name="day_of_week_shortest_saturday">с</string> + + <string name="am">пр. об.</string> + <string name="pm">сл. об.</string> + <string name="yesterday">Вчера</string> + <string name="today">Днес</string> + <string name="tomorrow">Утре</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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">%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 %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> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$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">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$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 %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string> + <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 %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> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s, %1$s - %8$s %7$s y, %6$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ca-rES/donottranslate-cldr.xml b/core/res/res/values-ca-rES/donottranslate-cldr.xml new file mode 100644 index 0000000..d5abeef --- /dev/null +++ b/core/res/res/values-ca-rES/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">gener</string> + <string name="month_long_standalone_february">febrer</string> + <string name="month_long_standalone_march">març</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">maig</string> + <string name="month_long_standalone_june">juny</string> + <string name="month_long_standalone_july">juliol</string> + <string name="month_long_standalone_august">agost</string> + <string name="month_long_standalone_september">setembre</string> + <string name="month_long_standalone_october">octubre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">desembre</string> + + <string name="month_long_january">gener</string> + <string name="month_long_february">febrer</string> + <string name="month_long_march">març</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">maig</string> + <string name="month_long_june">juny</string> + <string name="month_long_july">juliol</string> + <string name="month_long_august">agost</string> + <string name="month_long_september">setembre</string> + <string name="month_long_october">octubre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">desembre</string> + + <string name="month_medium_january">gen.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">març</string> + <string name="month_medium_april">abr.</string> + <string name="month_medium_may">maig</string> + <string name="month_medium_june">juny</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">ag.</string> + <string name="month_medium_september">set.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">des.</string> + + <string name="month_shortest_january">g</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">diumenge</string> + <string name="day_of_week_long_monday">dilluns</string> + <string name="day_of_week_long_tuesday">dimarts</string> + <string name="day_of_week_long_wednesday">dimecres</string> + <string name="day_of_week_long_thursday">dijous</string> + <string name="day_of_week_long_friday">divendres</string> + <string name="day_of_week_long_saturday">dissabte</string> + + <string name="day_of_week_medium_sunday">dg.</string> + <string name="day_of_week_medium_monday">dl.</string> + <string name="day_of_week_medium_tuesday">dt.</string> + <string name="day_of_week_medium_wednesday">dc.</string> + <string name="day_of_week_medium_thursday">dj.</string> + <string name="day_of_week_medium_friday">dv.</string> + <string name="day_of_week_medium_saturday">ds.</string> + + <string name="day_of_week_short_sunday">dg.</string> + <string name="day_of_week_short_monday">dl.</string> + <string name="day_of_week_short_tuesday">dt.</string> + <string name="day_of_week_short_wednesday">dc.</string> + <string name="day_of_week_short_thursday">dj.</string> + <string name="day_of_week_short_friday">dv.</string> + <string name="day_of_week_short_saturday">ds.</string> + + <string name="day_of_week_shortest_sunday">g</string> + <string name="day_of_week_shortest_monday">l</string> + <string name="day_of_week_shortest_tuesday">t</string> + <string name="day_of_week_shortest_wednesday">c</string> + <string name="day_of_week_shortest_thursday">j</string> + <string name="day_of_week_shortest_friday">v</string> + <string name="day_of_week_shortest_saturday">s</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">ahir</string> + <string name="today">avui</string> + <string name="tomorrow">demà</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B del %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %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 de %2$s - %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %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 - %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 de %2$s de %4$s - %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 - %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 - %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 de %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 de %2$s - %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 - %6$s %8$s de %7$s de %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml new file mode 100644 index 0000000..41f5dea --- /dev/null +++ b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">leden</string> + <string name="month_long_standalone_february">únor</string> + <string name="month_long_standalone_march">březen</string> + <string name="month_long_standalone_april">duben</string> + <string name="month_long_standalone_may">květen</string> + <string name="month_long_standalone_june">červen</string> + <string name="month_long_standalone_july">červenec</string> + <string name="month_long_standalone_august">srpen</string> + <string name="month_long_standalone_september">září</string> + <string name="month_long_standalone_october">říjen</string> + <string name="month_long_standalone_november">listopad</string> + <string name="month_long_standalone_december">prosinec</string> + + <string name="month_long_january">ledna</string> + <string name="month_long_february">února</string> + <string name="month_long_march">března</string> + <string name="month_long_april">dubna</string> + <string name="month_long_may">května</string> + <string name="month_long_june">června</string> + <string name="month_long_july">července</string> + <string name="month_long_august">srpna</string> + <string name="month_long_september">září</string> + <string name="month_long_october">října</string> + <string name="month_long_november">listopadu</string> + <string name="month_long_december">prosince</string> + + <string name="month_medium_january">1</string> + <string name="month_medium_february">2</string> + <string name="month_medium_march">3</string> + <string name="month_medium_april">4</string> + <string name="month_medium_may">5</string> + <string name="month_medium_june">6</string> + <string name="month_medium_july">7</string> + <string name="month_medium_august">8</string> + <string name="month_medium_september">9</string> + <string name="month_medium_october">10</string> + <string name="month_medium_november">11</string> + <string name="month_medium_december">12</string> + + <string name="month_shortest_january">l</string> + <string name="month_shortest_february">ú</string> + <string name="month_shortest_march">b</string> + <string name="month_shortest_april">d</string> + <string name="month_shortest_may">k</string> + <string name="month_shortest_june">č</string> + <string name="month_shortest_july">č</string> + <string name="month_shortest_august">s</string> + <string name="month_shortest_september">z</string> + <string name="month_shortest_october">ř</string> + <string name="month_shortest_november">l</string> + <string name="month_shortest_december">p</string> + + <string name="day_of_week_long_sunday">neděle</string> + <string name="day_of_week_long_monday">pondělí</string> + <string name="day_of_week_long_tuesday">úterý</string> + <string name="day_of_week_long_wednesday">středa</string> + <string name="day_of_week_long_thursday">čtvrtek</string> + <string name="day_of_week_long_friday">pátek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ne</string> + <string name="day_of_week_medium_monday">po</string> + <string name="day_of_week_medium_tuesday">út</string> + <string name="day_of_week_medium_wednesday">st</string> + <string name="day_of_week_medium_thursday">čt</string> + <string name="day_of_week_medium_friday">pá</string> + <string name="day_of_week_medium_saturday">so</string> + + <string name="day_of_week_short_sunday">ne</string> + <string name="day_of_week_short_monday">po</string> + <string name="day_of_week_short_tuesday">út</string> + <string name="day_of_week_short_wednesday">st</string> + <string name="day_of_week_short_thursday">čt</string> + <string name="day_of_week_short_friday">pá</string> + <string name="day_of_week_short_saturday">so</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">Ú</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">Č</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">dop.</string> + <string name="pm">odp.</string> + <string name="yesterday">Včera</string> + <string name="today">Dnes</string> + <string name="tomorrow">Zítra</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_year">%-B %Y</string> + <string name="abbrev_month_day">%-e.%-m</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, %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="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">%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_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_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_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> + <string name="short_format_month">%B</string> +</resources> diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml new file mode 100644 index 0000000..41f5dea --- /dev/null +++ b/core/res/res/values-cs/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">leden</string> + <string name="month_long_standalone_february">únor</string> + <string name="month_long_standalone_march">březen</string> + <string name="month_long_standalone_april">duben</string> + <string name="month_long_standalone_may">květen</string> + <string name="month_long_standalone_june">červen</string> + <string name="month_long_standalone_july">červenec</string> + <string name="month_long_standalone_august">srpen</string> + <string name="month_long_standalone_september">září</string> + <string name="month_long_standalone_october">říjen</string> + <string name="month_long_standalone_november">listopad</string> + <string name="month_long_standalone_december">prosinec</string> + + <string name="month_long_january">ledna</string> + <string name="month_long_february">února</string> + <string name="month_long_march">března</string> + <string name="month_long_april">dubna</string> + <string name="month_long_may">května</string> + <string name="month_long_june">června</string> + <string name="month_long_july">července</string> + <string name="month_long_august">srpna</string> + <string name="month_long_september">září</string> + <string name="month_long_october">října</string> + <string name="month_long_november">listopadu</string> + <string name="month_long_december">prosince</string> + + <string name="month_medium_january">1</string> + <string name="month_medium_february">2</string> + <string name="month_medium_march">3</string> + <string name="month_medium_april">4</string> + <string name="month_medium_may">5</string> + <string name="month_medium_june">6</string> + <string name="month_medium_july">7</string> + <string name="month_medium_august">8</string> + <string name="month_medium_september">9</string> + <string name="month_medium_october">10</string> + <string name="month_medium_november">11</string> + <string name="month_medium_december">12</string> + + <string name="month_shortest_january">l</string> + <string name="month_shortest_february">ú</string> + <string name="month_shortest_march">b</string> + <string name="month_shortest_april">d</string> + <string name="month_shortest_may">k</string> + <string name="month_shortest_june">č</string> + <string name="month_shortest_july">č</string> + <string name="month_shortest_august">s</string> + <string name="month_shortest_september">z</string> + <string name="month_shortest_october">ř</string> + <string name="month_shortest_november">l</string> + <string name="month_shortest_december">p</string> + + <string name="day_of_week_long_sunday">neděle</string> + <string name="day_of_week_long_monday">pondělí</string> + <string name="day_of_week_long_tuesday">úterý</string> + <string name="day_of_week_long_wednesday">středa</string> + <string name="day_of_week_long_thursday">čtvrtek</string> + <string name="day_of_week_long_friday">pátek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ne</string> + <string name="day_of_week_medium_monday">po</string> + <string name="day_of_week_medium_tuesday">út</string> + <string name="day_of_week_medium_wednesday">st</string> + <string name="day_of_week_medium_thursday">čt</string> + <string name="day_of_week_medium_friday">pá</string> + <string name="day_of_week_medium_saturday">so</string> + + <string name="day_of_week_short_sunday">ne</string> + <string name="day_of_week_short_monday">po</string> + <string name="day_of_week_short_tuesday">út</string> + <string name="day_of_week_short_wednesday">st</string> + <string name="day_of_week_short_thursday">čt</string> + <string name="day_of_week_short_friday">pá</string> + <string name="day_of_week_short_saturday">so</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">Ú</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">Č</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">dop.</string> + <string name="pm">odp.</string> + <string name="yesterday">Včera</string> + <string name="today">Dnes</string> + <string name="tomorrow">Zítra</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_year">%-B %Y</string> + <string name="abbrev_month_day">%-e.%-m</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, %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="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">%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_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_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_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> + <string name="short_format_month">%B</string> +</resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 35a3f9a..7dbeaeb 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Umožňuje aplikaci změnit aktuální konfiguraci, např. národní prostředí či obecnou velikost písma."</string> <string name="permlab_restartPackages">"restartování ostatních aplikací"</string> <string name="permdesc_restartPackages">"Umožňuje aplikaci vynutit restartování jiných aplikací."</string> - <string name="permlab_setProcessForeground">"zamezení zastavení aplikace"</string> - <string name="permdesc_setProcessForeground">"Umožňuje aplikaci spustit jakýkoli proces v popředí tak, že ho nelze ukončit. Běžné aplikace by toto nastavení nikdy neměly používat."</string> <string name="permlab_forceBack">"vynucení zavření aplikace"</string> <string name="permdesc_forceBack">"Umožňuje aplikaci vynutit zavření a přesunutí libovolné činnosti v popředí na pozadí. Běžné aplikace by toto nastavení neměly nikdy využívat."</string> <string name="permlab_dump">"načtení interního stavu systému"</string> <string name="permdesc_dump">"Umožňuje aplikaci načíst interní stav systému. Škodlivé aplikace mohou načíst řádu soukromých a zabezpečených informací, které by nikdy neměly potřebovat."</string> - <string name="permlab_addSystemService">"zveřejnění nízkoúrovňových služeb"</string> - <string name="permdesc_addSystemService">"Umožňuje aplikaci zveřejnit své vlastní nízkoúrovňové systémové služby. Škodlivé aplikace mohou převzít kontrolu nad systémem a získat či poškodit jakákoli data v něm obsažená."</string> <string name="permlab_runSetActivityWatcher">"sledování a řízení spouštění všech aplikací"</string> <string name="permdesc_runSetActivityWatcher">"Umožňuje aplikaci sledovat a řídit spouštění činností systémem. Škodlivé aplikace mohou zcela ovládnout systém. Toto oprávnění je zapotřebí pouze pro účely vývoje, nikdy pro běžné použití telefonu."</string> <string name="permlab_broadcastPackageRemoved">"odeslání vysílání o odstranění balíčku"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Umožňuje aplikaci řídit maximální počet spuštěných procesů. Běžné aplikace toto nastavení nikdy nevyužívají."</string> <string name="permlab_setAlwaysFinish">"zavření všech aplikací na pozadí"</string> <string name="permdesc_setAlwaysFinish">"Umožňuje aplikaci ovládat, zda jsou činnosti vždy dokončeny po přesunutí do pozadí. Běžné aplikace toto nastavení nikdy nevyužívají."</string> - <string name="permlab_fotaUpdate">"automatická instalace aktualizací systému"</string> - <string name="permdesc_fotaUpdate">"Umožňuje aplikaci přijímat oznámení o čekajících aktualizacích systému a spouštět jejich instalaci. Škodlivé aplikace mohou díky tomuto nastavení poškodit systém pomocí neoprávněných aktualizací nebo celkově narušovat proces aktualizace."</string> <string name="permlab_batteryStats">"změna statistických údajů o baterii"</string> <string name="permdesc_batteryStats">"Umožňuje změnu shromážděných statistických údajů o baterii. Není určeno pro běžné aplikace."</string> <string name="permlab_internalSystemWindow">"zobrazení nepovolených oken"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Heslo"</string> <string name="lockscreen_glogin_submit_button">"Přihlásit se"</string> <string name="lockscreen_glogin_invalid_input">"Neplatné uživatelské jméno nebo heslo."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Vymazat oznámení"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"enter"</string> <string name="menu_delete_shortcut_label">"smazat"</string> <string name="search_go">"Hledat"</string> - <string name="today">"Dnes"</string> - <string name="yesterday">"Včera"</string> - <string name="tomorrow">"Zítra"</string> <string name="oneMonthDurationPast">"před 1 měsícem"</string> <string name="beforeOneMonthDurationPast">"Déle než před 1 měsícem"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"týd."</string> <string name="year">"rokem"</string> <string name="years">"lety"</string> - <string name="sunday">"neděle"</string> - <string name="monday">"pondělí"</string> - <string name="tuesday">"úterý"</string> - <string name="wednesday">"středa"</string> - <string name="thursday">"čtvrtek"</string> - <string name="friday">"pátek"</string> - <string name="saturday">"sobota"</string> <string name="every_weekday">"Každý pracovní den (Po – Pá)"</string> <string name="daily">"Denně"</string> <string name="weekly">"Každý týden v <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Omlouváme se, ale toto video nelze přenášet datovým proudem do tohoto zařízení."</string> <string name="VideoView_error_text_unknown">"Toto video bohužel nelze přehrát."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"dop."</string> - <string name="pm">"odp."</string> - <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"poledne"</string> <string name="Noon">"Poledne"</string> <string name="midnight">"půlnoc"</string> <string name="Midnight">"Půlnoc"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>."</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>. <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>. <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>., <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>., <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"neděle"</string> - <string name="day_of_week_long_monday">"pondělí"</string> - <string name="day_of_week_long_tuesday">"úterý"</string> - <string name="day_of_week_long_wednesday">"středa"</string> - <string name="day_of_week_long_thursday">"čtvrtek"</string> - <string name="day_of_week_long_friday">"pátek"</string> - <string name="day_of_week_long_saturday">"sobota"</string> - <string name="day_of_week_medium_sunday">"Ne"</string> - <string name="day_of_week_medium_monday">"Po"</string> - <string name="day_of_week_medium_tuesday">"Út"</string> - <string name="day_of_week_medium_wednesday">"St"</string> - <string name="day_of_week_medium_thursday">"Čt"</string> - <string name="day_of_week_medium_friday">"Pá"</string> - <string name="day_of_week_medium_saturday">"So"</string> - <string name="day_of_week_short_sunday">"Ne"</string> - <string name="day_of_week_short_monday">"Po"</string> - <string name="day_of_week_short_tuesday">"Út"</string> - <string name="day_of_week_short_wednesday">"St"</string> - <string name="day_of_week_short_thursday">"Čt"</string> - <string name="day_of_week_short_friday">"Pá"</string> - <string name="day_of_week_short_saturday">"So"</string> - <string name="day_of_week_shorter_sunday">"Ne"</string> - <string name="day_of_week_shorter_monday">"Po"</string> - <string name="day_of_week_shorter_tuesday">"Út"</string> - <string name="day_of_week_shorter_wednesday">"St"</string> - <string name="day_of_week_shorter_thursday">"Čt"</string> - <string name="day_of_week_shorter_friday">"Pá"</string> - <string name="day_of_week_shorter_saturday">"So"</string> - <string name="day_of_week_shortest_sunday">"Ne"</string> - <string name="day_of_week_shortest_monday">"Po"</string> - <string name="day_of_week_shortest_tuesday">"Čt"</string> - <string name="day_of_week_shortest_wednesday">"St"</string> - <string name="day_of_week_shortest_thursday">"Čt"</string> - <string name="day_of_week_shortest_friday">"Pá"</string> - <string name="day_of_week_shortest_saturday">"So"</string> - <string name="month_long_january">"leden"</string> - <string name="month_long_february">"únor"</string> - <string name="month_long_march">"březen"</string> - <string name="month_long_april">"duben"</string> - <string name="month_long_may">"květen"</string> - <string name="month_long_june">"červen"</string> - <string name="month_long_july">"červenec"</string> - <string name="month_long_august">"srpen"</string> - <string name="month_long_september">"září"</string> - <string name="month_long_october">"říjen"</string> - <string name="month_long_november">"listopad"</string> - <string name="month_long_december">"prosinec"</string> - <string name="month_medium_january">"leden"</string> - <string name="month_medium_february">"únor"</string> - <string name="month_medium_march">"březen"</string> - <string name="month_medium_april">"duben"</string> - <string name="month_medium_may">"květen"</string> - <string name="month_medium_june">"červen"</string> - <string name="month_medium_july">"červenec"</string> - <string name="month_medium_august">"srpen"</string> - <string name="month_medium_september">"září"</string> - <string name="month_medium_october">"říjen"</string> - <string name="month_medium_november">"listopad"</string> - <string name="month_medium_december">"prosinec"</string> - <string name="month_shortest_january">"1."</string> - <string name="month_shortest_february">"2."</string> - <string name="month_shortest_march">"Po"</string> - <string name="month_shortest_april">"4."</string> - <string name="month_shortest_may">"5."</string> - <string name="month_shortest_june">"6."</string> - <string name="month_shortest_july">"7."</string> - <string name="month_shortest_august">"8."</string> - <string name="month_shortest_september">"9."</string> - <string name="month_shortest_october">"10."</string> - <string name="month_shortest_november">"11."</string> - <string name="month_shortest_december">"12."</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Vybrat vše"</string> diff --git a/core/res/res/values-da-rDK/donottranslate-cldr.xml b/core/res/res/values-da-rDK/donottranslate-cldr.xml new file mode 100644 index 0000000..2d0db93 --- /dev/null +++ b/core/res/res/values-da-rDK/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januar</string> + <string name="month_long_standalone_february">februar</string> + <string name="month_long_standalone_march">marts</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januar</string> + <string name="month_long_february">februar</string> + <string name="month_long_march">marts</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">august</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mar.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun.</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">søndag</string> + <string name="day_of_week_long_monday">mandag</string> + <string name="day_of_week_long_tuesday">tirsdag</string> + <string name="day_of_week_long_wednesday">onsdag</string> + <string name="day_of_week_long_thursday">torsdag</string> + <string name="day_of_week_long_friday">fredag</string> + <string name="day_of_week_long_saturday">lørdag</string> + + <string name="day_of_week_medium_sunday">søn</string> + <string name="day_of_week_medium_monday">man</string> + <string name="day_of_week_medium_tuesday">tir</string> + <string name="day_of_week_medium_wednesday">ons</string> + <string name="day_of_week_medium_thursday">tor</string> + <string name="day_of_week_medium_friday">fre</string> + <string name="day_of_week_medium_saturday">lør</string> + + <string name="day_of_week_short_sunday">søn</string> + <string name="day_of_week_short_monday">man</string> + <string name="day_of_week_short_tuesday">tir</string> + <string name="day_of_week_short_wednesday">ons</string> + <string name="day_of_week_short_thursday">tor</string> + <string name="day_of_week_short_friday">fre</string> + <string name="day_of_week_short_saturday">lør</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">O</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">f.m.</string> + <string name="pm">e.m.</string> + <string name="yesterday">i går</string> + <string name="today">i dag</string> + <string name="tomorrow">i morgen</string> + + <string name="hour_minute_24">%H.%M</string> + <string name="hour_minute_ampm">%-l.%M %p</string> + <string name="hour_minute_cap_ampm">%-l.%M %^p</string> + <string name="twelve_hour_time_format">h.mm a</string> + <string name="twenty_four_hour_time_format">HH.mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e. %b %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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. %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 den %2$s - %6$s %4$s den %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s den %2$s - %4$s den %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 den %3$s</string> + <string name="wday_date">%2$s den %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_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_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_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 den %3$s. %2$s - %6$s den %8$s. %7$s %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-da/donottranslate-cldr.xml b/core/res/res/values-da/donottranslate-cldr.xml new file mode 100644 index 0000000..2d0db93 --- /dev/null +++ b/core/res/res/values-da/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januar</string> + <string name="month_long_standalone_february">februar</string> + <string name="month_long_standalone_march">marts</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januar</string> + <string name="month_long_february">februar</string> + <string name="month_long_march">marts</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">august</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mar.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun.</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">søndag</string> + <string name="day_of_week_long_monday">mandag</string> + <string name="day_of_week_long_tuesday">tirsdag</string> + <string name="day_of_week_long_wednesday">onsdag</string> + <string name="day_of_week_long_thursday">torsdag</string> + <string name="day_of_week_long_friday">fredag</string> + <string name="day_of_week_long_saturday">lørdag</string> + + <string name="day_of_week_medium_sunday">søn</string> + <string name="day_of_week_medium_monday">man</string> + <string name="day_of_week_medium_tuesday">tir</string> + <string name="day_of_week_medium_wednesday">ons</string> + <string name="day_of_week_medium_thursday">tor</string> + <string name="day_of_week_medium_friday">fre</string> + <string name="day_of_week_medium_saturday">lør</string> + + <string name="day_of_week_short_sunday">søn</string> + <string name="day_of_week_short_monday">man</string> + <string name="day_of_week_short_tuesday">tir</string> + <string name="day_of_week_short_wednesday">ons</string> + <string name="day_of_week_short_thursday">tor</string> + <string name="day_of_week_short_friday">fre</string> + <string name="day_of_week_short_saturday">lør</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">O</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">f.m.</string> + <string name="pm">e.m.</string> + <string name="yesterday">i går</string> + <string name="today">i dag</string> + <string name="tomorrow">i morgen</string> + + <string name="hour_minute_24">%H.%M</string> + <string name="hour_minute_ampm">%-l.%M %p</string> + <string name="hour_minute_cap_ampm">%-l.%M %^p</string> + <string name="twelve_hour_time_format">h.mm a</string> + <string name="twenty_four_hour_time_format">HH.mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e. %b %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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. %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 den %2$s - %6$s %4$s den %5$s</string> + <string name="wday1_date1_wday2_date2">%1$s den %2$s - %4$s den %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 den %3$s</string> + <string name="wday_date">%2$s den %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_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_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_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 den %3$s. %2$s - %6$s den %8$s. %7$s %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de-rAT/donottranslate-cldr.xml b/core/res/res/values-de-rAT/donottranslate-cldr.xml new file mode 100644 index 0000000..27624a3 --- /dev/null +++ b/core/res/res/values-de-rAT/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Jänner</string> + <string name="month_long_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> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sonntag</string> + <string name="day_of_week_long_monday">Montag</string> + <string name="day_of_week_long_tuesday">Dienstag</string> + <string name="day_of_week_long_wednesday">Mittwoch</string> + <string name="day_of_week_long_thursday">Donnerstag</string> + <string name="day_of_week_long_friday">Freitag</string> + <string name="day_of_week_long_saturday">Samstag</string> + + <string name="day_of_week_medium_sunday">So.</string> + <string name="day_of_week_medium_monday">Mo.</string> + <string name="day_of_week_medium_tuesday">Di.</string> + <string name="day_of_week_medium_wednesday">Mi.</string> + <string name="day_of_week_medium_thursday">Do.</string> + <string name="day_of_week_medium_friday">Fr.</string> + <string name="day_of_week_medium_saturday">Sa.</string> + + <string name="day_of_week_short_sunday">So.</string> + <string name="day_of_week_short_monday">Mo.</string> + <string name="day_of_week_short_tuesday">Di.</string> + <string name="day_of_week_short_wednesday">Mi.</string> + <string name="day_of_week_short_thursday">Do.</string> + <string name="day_of_week_short_friday">Fr.</string> + <string name="day_of_week_short_saturday">Sa.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">vorm.</string> + <string name="pm">nachm.</string> + <string name="yesterday">Gestern</string> + <string name="today">Heute</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%d. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_year">%B %Y</string> + <string name="abbrev_month_day">%d. %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de-rCH/donottranslate-cldr.xml b/core/res/res/values-de-rCH/donottranslate-cldr.xml new file mode 100644 index 0000000..f32095b --- /dev/null +++ b/core/res/res/values-de-rCH/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januar</string> + <string name="month_long_standalone_february">Februar</string> + <string name="month_long_standalone_march">März</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mai</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Dezember</string> + + <string name="month_long_january">Januar</string> + <string name="month_long_february">Februar</string> + <string name="month_long_march">März</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mai</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Dezember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mär</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mai</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sonntag</string> + <string name="day_of_week_long_monday">Montag</string> + <string name="day_of_week_long_tuesday">Dienstag</string> + <string name="day_of_week_long_wednesday">Mittwoch</string> + <string name="day_of_week_long_thursday">Donnerstag</string> + <string name="day_of_week_long_friday">Freitag</string> + <string name="day_of_week_long_saturday">Samstag</string> + + <string name="day_of_week_medium_sunday">So.</string> + <string name="day_of_week_medium_monday">Mo.</string> + <string name="day_of_week_medium_tuesday">Di.</string> + <string name="day_of_week_medium_wednesday">Mi.</string> + <string name="day_of_week_medium_thursday">Do.</string> + <string name="day_of_week_medium_friday">Fr.</string> + <string name="day_of_week_medium_saturday">Sa.</string> + + <string name="day_of_week_short_sunday">So.</string> + <string name="day_of_week_short_monday">Mo.</string> + <string name="day_of_week_short_tuesday">Di.</string> + <string name="day_of_week_short_wednesday">Mi.</string> + <string name="day_of_week_short_thursday">Do.</string> + <string name="day_of_week_short_friday">Fr.</string> + <string name="day_of_week_short_saturday">Sa.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">vorm.</string> + <string name="pm">nachm.</string> + <string name="yesterday">Gestern</string> + <string name="today">Heute</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de-rDE/donottranslate-cldr.xml b/core/res/res/values-de-rDE/donottranslate-cldr.xml new file mode 100644 index 0000000..f32095b --- /dev/null +++ b/core/res/res/values-de-rDE/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januar</string> + <string name="month_long_standalone_february">Februar</string> + <string name="month_long_standalone_march">März</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mai</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Dezember</string> + + <string name="month_long_january">Januar</string> + <string name="month_long_february">Februar</string> + <string name="month_long_march">März</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mai</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Dezember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mär</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mai</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sonntag</string> + <string name="day_of_week_long_monday">Montag</string> + <string name="day_of_week_long_tuesday">Dienstag</string> + <string name="day_of_week_long_wednesday">Mittwoch</string> + <string name="day_of_week_long_thursday">Donnerstag</string> + <string name="day_of_week_long_friday">Freitag</string> + <string name="day_of_week_long_saturday">Samstag</string> + + <string name="day_of_week_medium_sunday">So.</string> + <string name="day_of_week_medium_monday">Mo.</string> + <string name="day_of_week_medium_tuesday">Di.</string> + <string name="day_of_week_medium_wednesday">Mi.</string> + <string name="day_of_week_medium_thursday">Do.</string> + <string name="day_of_week_medium_friday">Fr.</string> + <string name="day_of_week_medium_saturday">Sa.</string> + + <string name="day_of_week_short_sunday">So.</string> + <string name="day_of_week_short_monday">Mo.</string> + <string name="day_of_week_short_tuesday">Di.</string> + <string name="day_of_week_short_wednesday">Mi.</string> + <string name="day_of_week_short_thursday">Do.</string> + <string name="day_of_week_short_friday">Fr.</string> + <string name="day_of_week_short_saturday">Sa.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">vorm.</string> + <string name="pm">nachm.</string> + <string name="yesterday">Gestern</string> + <string name="today">Heute</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de-rLI/donottranslate-cldr.xml b/core/res/res/values-de-rLI/donottranslate-cldr.xml new file mode 100644 index 0000000..f32095b --- /dev/null +++ b/core/res/res/values-de-rLI/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januar</string> + <string name="month_long_standalone_february">Februar</string> + <string name="month_long_standalone_march">März</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mai</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Dezember</string> + + <string name="month_long_january">Januar</string> + <string name="month_long_february">Februar</string> + <string name="month_long_march">März</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mai</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Dezember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mär</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mai</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sonntag</string> + <string name="day_of_week_long_monday">Montag</string> + <string name="day_of_week_long_tuesday">Dienstag</string> + <string name="day_of_week_long_wednesday">Mittwoch</string> + <string name="day_of_week_long_thursday">Donnerstag</string> + <string name="day_of_week_long_friday">Freitag</string> + <string name="day_of_week_long_saturday">Samstag</string> + + <string name="day_of_week_medium_sunday">So.</string> + <string name="day_of_week_medium_monday">Mo.</string> + <string name="day_of_week_medium_tuesday">Di.</string> + <string name="day_of_week_medium_wednesday">Mi.</string> + <string name="day_of_week_medium_thursday">Do.</string> + <string name="day_of_week_medium_friday">Fr.</string> + <string name="day_of_week_medium_saturday">Sa.</string> + + <string name="day_of_week_short_sunday">So.</string> + <string name="day_of_week_short_monday">Mo.</string> + <string name="day_of_week_short_tuesday">Di.</string> + <string name="day_of_week_short_wednesday">Mi.</string> + <string name="day_of_week_short_thursday">Do.</string> + <string name="day_of_week_short_friday">Fr.</string> + <string name="day_of_week_short_saturday">Sa.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">vorm.</string> + <string name="pm">nachm.</string> + <string name="yesterday">Gestern</string> + <string name="today">Heute</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml new file mode 100644 index 0000000..f32095b --- /dev/null +++ b/core/res/res/values-de/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januar</string> + <string name="month_long_standalone_february">Februar</string> + <string name="month_long_standalone_march">März</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mai</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Dezember</string> + + <string name="month_long_january">Januar</string> + <string name="month_long_february">Februar</string> + <string name="month_long_march">März</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mai</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Dezember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mär</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mai</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sonntag</string> + <string name="day_of_week_long_monday">Montag</string> + <string name="day_of_week_long_tuesday">Dienstag</string> + <string name="day_of_week_long_wednesday">Mittwoch</string> + <string name="day_of_week_long_thursday">Donnerstag</string> + <string name="day_of_week_long_friday">Freitag</string> + <string name="day_of_week_long_saturday">Samstag</string> + + <string name="day_of_week_medium_sunday">So.</string> + <string name="day_of_week_medium_monday">Mo.</string> + <string name="day_of_week_medium_tuesday">Di.</string> + <string name="day_of_week_medium_wednesday">Mi.</string> + <string name="day_of_week_medium_thursday">Do.</string> + <string name="day_of_week_medium_friday">Fr.</string> + <string name="day_of_week_medium_saturday">Sa.</string> + + <string name="day_of_week_short_sunday">So.</string> + <string name="day_of_week_short_monday">Mo.</string> + <string name="day_of_week_short_tuesday">Di.</string> + <string name="day_of_week_short_wednesday">Mi.</string> + <string name="day_of_week_short_thursday">Do.</string> + <string name="day_of_week_short_friday">Fr.</string> + <string name="day_of_week_short_saturday">Sa.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">vorm.</string> + <string name="pm">nachm.</string> + <string name="yesterday">Gestern</string> + <string name="today">Heute</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 674c64b..dfb4549 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Ermöglicht einer Anwendung, die aktuelle Konfiguration zu ändern, etwa das Gebietsschema oder die Schriftgröße."</string> <string name="permlab_restartPackages">"Andere Anwendungen neu starten"</string> <string name="permdesc_restartPackages">"Ermöglicht einer Anwendung, den Neustart anderer Anwendungen zu erzwingen."</string> - <string name="permlab_setProcessForeground">"Beenden nicht zulassen"</string> - <string name="permdesc_setProcessForeground">"Ermöglicht einer Anwendung, beliebige Prozesse im Vordergrund auszuführen, damit diese nicht beendet werden können. Sollte nicht für normale Anwendungen benötigt werden."</string> <string name="permlab_forceBack">"Schließen von Anwendung erzwingen"</string> <string name="permdesc_forceBack">"Ermöglicht einer Anwendung, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden."</string> <string name="permlab_dump">"Systeminternen Status abrufen"</string> <string name="permdesc_dump">"Ermöglicht einer Anwendung, den internen Status des Systems abzurufen. Schädliche Anwendungen rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string> - <string name="permlab_addSystemService">"systemnahe Dienste veröffentlichen"</string> - <string name="permdesc_addSystemService">"Ermöglicht der Anwendung, ihre eigenen systemnahen Dienste anzubieten. Schädliche Anwendungen könnten in das System eindringen und darin befindliche Daten stehlen oder manipulieren."</string> <string name="permlab_runSetActivityWatcher">"Start von Anwendungen überwachen und steuern"</string> <string name="permdesc_runSetActivityWatcher">"Ermöglicht der Anwendung, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Anwendungen können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Telefonnutzung benötigt."</string> <string name="permlab_broadcastPackageRemoved">"Broadcast ohne Paket senden"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Ermöglicht einer Anwendung, die maximale Anzahl an laufenden Prozessen zu steuern. Wird nicht für normale Anwendungen benötigt."</string> <string name="permlab_setAlwaysFinish">"alle Anwendungen im Hintergrund schließen"</string> <string name="permdesc_setAlwaysFinish">"Überlässt einer Anwendung die Entscheidung, ob Aktivitäten beendet werden, sobald Sie in den Hintergrund rücken. Wird nicht für normale Anwendungen benötigt."</string> - <string name="permlab_fotaUpdate">"System-Updates automatisch installieren"</string> - <string name="permdesc_fotaUpdate">"Ermöglicht einer Anwendung, Benachrichtigungen zu ausstehenden System-Updates zu erhalten und deren Installation einzuleiten. Schädliche Anwendungen können so das System durch nicht autorisierte Updates beschädigen oder in den Update-Prozess eingreifen."</string> <string name="permlab_batteryStats">"Akku-Daten ändern"</string> <string name="permdesc_batteryStats">"Ermöglicht die Änderung von gesammelten Akku-Daten. Nicht für normale Anwendungen vorgesehen."</string> <string name="permlab_internalSystemWindow">"nicht autorisierte Fenster anzeigen"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Passwort"</string> <string name="lockscreen_glogin_submit_button">"Anmelden"</string> <string name="lockscreen_glogin_invalid_input">"Ungültiger Nutzername oder ungültiges Passwort."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Benachrichtigungen löschen"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"Enter"</string> <string name="menu_delete_shortcut_label">"löschen"</string> <string name="search_go">"Suche"</string> - <string name="today">"Heute"</string> - <string name="yesterday">"Gestern"</string> - <string name="tomorrow">"Morgen"</string> <string name="oneMonthDurationPast">"Vor 1 Monat"</string> <string name="beforeOneMonthDurationPast">"Vor mehr als 1 Monat"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"Wochen"</string> <string name="year">"Jahr"</string> <string name="years">"Jahre"</string> - <string name="sunday">"Sonntag"</string> - <string name="monday">"Montag"</string> - <string name="tuesday">"Dienstag"</string> - <string name="wednesday">"Mittwoch"</string> - <string name="thursday">"Donnerstag"</string> - <string name="friday">"Freitag"</string> - <string name="saturday">"Samstag"</string> <string name="every_weekday">"Jeden Wochentag (Mo-Fr)"</string> <string name="daily">"Täglich"</string> <string name="weekly">"Jede Woche am <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Leider ist dieses Video nicht für Streaming auf diesem Gerät gültig."</string> <string name="VideoView_error_text_unknown">"Dieses Video kann leider nicht abgespielt werden."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"AM"</string> - <string name="pm">".."</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"Mittag"</string> <string name="Noon">"Mittag"</string> <string name="midnight">"Mitternacht"</string> <string name="Midnight">"Mitternacht"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"Sonntag"</string> - <string name="day_of_week_long_monday">"Montag"</string> - <string name="day_of_week_long_tuesday">"Dienstag"</string> - <string name="day_of_week_long_wednesday">"Mittwoch"</string> - <string name="day_of_week_long_thursday">"Donnerstag"</string> - <string name="day_of_week_long_friday">"Freitag"</string> - <string name="day_of_week_long_saturday">"Samstag"</string> - <string name="day_of_week_medium_sunday">"So"</string> - <string name="day_of_week_medium_monday">"Mo"</string> - <string name="day_of_week_medium_tuesday">"Di"</string> - <string name="day_of_week_medium_wednesday">"Mi"</string> - <string name="day_of_week_medium_thursday">"Do"</string> - <string name="day_of_week_medium_friday">"Fr"</string> - <string name="day_of_week_medium_saturday">"Sa"</string> - <string name="day_of_week_short_sunday">"So"</string> - <string name="day_of_week_short_monday">"Mo"</string> - <string name="day_of_week_short_tuesday">"Di"</string> - <string name="day_of_week_short_wednesday">"Mi"</string> - <string name="day_of_week_short_thursday">"Do"</string> - <string name="day_of_week_short_friday">"Fr"</string> - <string name="day_of_week_short_saturday">"Sa"</string> - <string name="day_of_week_shorter_sunday">"So"</string> - <string name="day_of_week_shorter_monday">"März"</string> - <string name="day_of_week_shorter_tuesday">"Di"</string> - <string name="day_of_week_shorter_wednesday">"Mi"</string> - <string name="day_of_week_shorter_thursday">"Do"</string> - <string name="day_of_week_shorter_friday">"Fr"</string> - <string name="day_of_week_shorter_saturday">"Sa"</string> - <string name="day_of_week_shortest_sunday">"Sep"</string> - <string name="day_of_week_shortest_monday">"Mo"</string> - <string name="day_of_week_shortest_tuesday">"Do"</string> - <string name="day_of_week_shortest_wednesday">"Mi"</string> - <string name="day_of_week_shortest_thursday">"Do"</string> - <string name="day_of_week_shortest_friday">"Fr"</string> - <string name="day_of_week_shortest_saturday">"Sa"</string> - <string name="month_long_january">"Januar"</string> - <string name="month_long_february">"Februar"</string> - <string name="month_long_march">"März"</string> - <string name="month_long_april">"April"</string> - <string name="month_long_may">"Mai"</string> - <string name="month_long_june">"Juni"</string> - <string name="month_long_july">"Juli"</string> - <string name="month_long_august">"August"</string> - <string name="month_long_september">"September"</string> - <string name="month_long_october">"Oktober"</string> - <string name="month_long_november">"November"</string> - <string name="month_long_december">"Dezember"</string> - <string name="month_medium_january">"Jan."</string> - <string name="month_medium_february">"Feb."</string> - <string name="month_medium_march">"März"</string> - <string name="month_medium_april">"Apr."</string> - <string name="month_medium_may">"Mai"</string> - <string name="month_medium_june">"Juni"</string> - <string name="month_medium_july">"Juli"</string> - <string name="month_medium_august">"Aug"</string> - <string name="month_medium_september">"Sep."</string> - <string name="month_medium_october">"Okt."</string> - <string name="month_medium_november">"Nov."</string> - <string name="month_medium_december">"Dez."</string> - <string name="month_shortest_january">"Juli"</string> - <string name="month_shortest_february">"Fr"</string> - <string name="month_shortest_march">"März"</string> - <string name="month_shortest_april">"Apr"</string> - <string name="month_shortest_may">"Mo"</string> - <string name="month_shortest_june">"Juni"</string> - <string name="month_shortest_july">"Juli"</string> - <string name="month_shortest_august">"Aug."</string> - <string name="month_shortest_september">"Sep"</string> - <string name="month_shortest_october">"Okt."</string> - <string name="month_shortest_november">"No"</string> - <string name="month_shortest_december">"Dez."</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Alles auswählen"</string> diff --git a/core/res/res/values-el-rGR/donottranslate-cldr.xml b/core/res/res/values-el-rGR/donottranslate-cldr.xml new file mode 100644 index 0000000..e8f02fb --- /dev/null +++ b/core/res/res/values-el-rGR/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Ιανουάριος</string> + <string name="month_long_standalone_february">Φεβρουάριος</string> + <string name="month_long_standalone_march">Μάρτιος</string> + <string name="month_long_standalone_april">Απρίλιος</string> + <string name="month_long_standalone_may">Μάιος</string> + <string name="month_long_standalone_june">Ιούνιος</string> + <string name="month_long_standalone_july">Ιούλιος</string> + <string name="month_long_standalone_august">Αύγουστος</string> + <string name="month_long_standalone_september">Σεπτέμβριος</string> + <string name="month_long_standalone_october">Οκτώβριος</string> + <string name="month_long_standalone_november">Νοέμβριος</string> + <string name="month_long_standalone_december">Δεκέμβριος</string> + + <string name="month_long_january">Ιανουαρίου</string> + <string name="month_long_february">Φεβρουαρίου</string> + <string name="month_long_march">Μαρτίου</string> + <string name="month_long_april">Απριλίου</string> + <string name="month_long_may">Μαΐου</string> + <string name="month_long_june">Ιουνίου</string> + <string name="month_long_july">Ιουλίου</string> + <string name="month_long_august">Αυγούστου</string> + <string name="month_long_september">Σεπτεμβρίου</string> + <string name="month_long_october">Οκτωβρίου</string> + <string name="month_long_november">Νοεμβρίου</string> + <string name="month_long_december">Δεκεμβρίου</string> + + <string name="month_medium_january">Ιαν</string> + <string name="month_medium_february">Φεβ</string> + <string name="month_medium_march">Μαρ</string> + <string name="month_medium_april">Απρ</string> + <string name="month_medium_may">Μαϊ</string> + <string name="month_medium_june">Ιουν</string> + <string name="month_medium_july">Ιουλ</string> + <string name="month_medium_august">Αυγ</string> + <string name="month_medium_september">Σεπ</string> + <string name="month_medium_october">Οκτ</string> + <string name="month_medium_november">Νοε</string> + <string name="month_medium_december">Δεκ</string> + + <string name="month_shortest_january">Ι</string> + <string name="month_shortest_february">Φ</string> + <string name="month_shortest_march">Μ</string> + <string name="month_shortest_april">Α</string> + <string name="month_shortest_may">Μ</string> + <string name="month_shortest_june">Ι</string> + <string name="month_shortest_july">Ι</string> + <string name="month_shortest_august">Α</string> + <string name="month_shortest_september">Σ</string> + <string name="month_shortest_october">Ο</string> + <string name="month_shortest_november">Ν</string> + <string name="month_shortest_december">Δ</string> + + <string name="day_of_week_long_sunday">Κυριακή</string> + <string name="day_of_week_long_monday">Δευτέρα</string> + <string name="day_of_week_long_tuesday">Τρίτη</string> + <string name="day_of_week_long_wednesday">Τετάρτη</string> + <string name="day_of_week_long_thursday">Πέμπτη</string> + <string name="day_of_week_long_friday">Παρασκευή</string> + <string name="day_of_week_long_saturday">Σάββατο</string> + + <string name="day_of_week_medium_sunday">Κυρ</string> + <string name="day_of_week_medium_monday">Δευ</string> + <string name="day_of_week_medium_tuesday">Τρι</string> + <string name="day_of_week_medium_wednesday">Τετ</string> + <string name="day_of_week_medium_thursday">Πεμ</string> + <string name="day_of_week_medium_friday">Παρ</string> + <string name="day_of_week_medium_saturday">Σαβ</string> + + <string name="day_of_week_short_sunday">Κυρ</string> + <string name="day_of_week_short_monday">Δευ</string> + <string name="day_of_week_short_tuesday">Τρι</string> + <string name="day_of_week_short_wednesday">Τετ</string> + <string name="day_of_week_short_thursday">Πεμ</string> + <string name="day_of_week_short_friday">Παρ</string> + <string name="day_of_week_short_saturday">Σαβ</string> + + <string name="day_of_week_shortest_sunday">Κ</string> + <string name="day_of_week_shortest_monday">Δ</string> + <string name="day_of_week_shortest_tuesday">Τ</string> + <string name="day_of_week_shortest_wednesday">Τ</string> + <string name="day_of_week_shortest_thursday">Π</string> + <string name="day_of_week_shortest_friday">Π</string> + <string name="day_of_week_shortest_saturday">Σ</string> + + <string name="am">π.μ.</string> + <string name="pm">μ.μ.</string> + <string name="yesterday">Χτες</string> + <string name="today">Σήμερα</string> + <string name="tomorrow">Αύριο</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-el/donottranslate-cldr.xml b/core/res/res/values-el/donottranslate-cldr.xml new file mode 100644 index 0000000..e8f02fb --- /dev/null +++ b/core/res/res/values-el/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Ιανουάριος</string> + <string name="month_long_standalone_february">Φεβρουάριος</string> + <string name="month_long_standalone_march">Μάρτιος</string> + <string name="month_long_standalone_april">Απρίλιος</string> + <string name="month_long_standalone_may">Μάιος</string> + <string name="month_long_standalone_june">Ιούνιος</string> + <string name="month_long_standalone_july">Ιούλιος</string> + <string name="month_long_standalone_august">Αύγουστος</string> + <string name="month_long_standalone_september">Σεπτέμβριος</string> + <string name="month_long_standalone_october">Οκτώβριος</string> + <string name="month_long_standalone_november">Νοέμβριος</string> + <string name="month_long_standalone_december">Δεκέμβριος</string> + + <string name="month_long_january">Ιανουαρίου</string> + <string name="month_long_february">Φεβρουαρίου</string> + <string name="month_long_march">Μαρτίου</string> + <string name="month_long_april">Απριλίου</string> + <string name="month_long_may">Μαΐου</string> + <string name="month_long_june">Ιουνίου</string> + <string name="month_long_july">Ιουλίου</string> + <string name="month_long_august">Αυγούστου</string> + <string name="month_long_september">Σεπτεμβρίου</string> + <string name="month_long_october">Οκτωβρίου</string> + <string name="month_long_november">Νοεμβρίου</string> + <string name="month_long_december">Δεκεμβρίου</string> + + <string name="month_medium_january">Ιαν</string> + <string name="month_medium_february">Φεβ</string> + <string name="month_medium_march">Μαρ</string> + <string name="month_medium_april">Απρ</string> + <string name="month_medium_may">Μαϊ</string> + <string name="month_medium_june">Ιουν</string> + <string name="month_medium_july">Ιουλ</string> + <string name="month_medium_august">Αυγ</string> + <string name="month_medium_september">Σεπ</string> + <string name="month_medium_october">Οκτ</string> + <string name="month_medium_november">Νοε</string> + <string name="month_medium_december">Δεκ</string> + + <string name="month_shortest_january">Ι</string> + <string name="month_shortest_february">Φ</string> + <string name="month_shortest_march">Μ</string> + <string name="month_shortest_april">Α</string> + <string name="month_shortest_may">Μ</string> + <string name="month_shortest_june">Ι</string> + <string name="month_shortest_july">Ι</string> + <string name="month_shortest_august">Α</string> + <string name="month_shortest_september">Σ</string> + <string name="month_shortest_october">Ο</string> + <string name="month_shortest_november">Ν</string> + <string name="month_shortest_december">Δ</string> + + <string name="day_of_week_long_sunday">Κυριακή</string> + <string name="day_of_week_long_monday">Δευτέρα</string> + <string name="day_of_week_long_tuesday">Τρίτη</string> + <string name="day_of_week_long_wednesday">Τετάρτη</string> + <string name="day_of_week_long_thursday">Πέμπτη</string> + <string name="day_of_week_long_friday">Παρασκευή</string> + <string name="day_of_week_long_saturday">Σάββατο</string> + + <string name="day_of_week_medium_sunday">Κυρ</string> + <string name="day_of_week_medium_monday">Δευ</string> + <string name="day_of_week_medium_tuesday">Τρι</string> + <string name="day_of_week_medium_wednesday">Τετ</string> + <string name="day_of_week_medium_thursday">Πεμ</string> + <string name="day_of_week_medium_friday">Παρ</string> + <string name="day_of_week_medium_saturday">Σαβ</string> + + <string name="day_of_week_short_sunday">Κυρ</string> + <string name="day_of_week_short_monday">Δευ</string> + <string name="day_of_week_short_tuesday">Τρι</string> + <string name="day_of_week_short_wednesday">Τετ</string> + <string name="day_of_week_short_thursday">Πεμ</string> + <string name="day_of_week_short_friday">Παρ</string> + <string name="day_of_week_short_saturday">Σαβ</string> + + <string name="day_of_week_shortest_sunday">Κ</string> + <string name="day_of_week_shortest_monday">Δ</string> + <string name="day_of_week_shortest_tuesday">Τ</string> + <string name="day_of_week_shortest_wednesday">Τ</string> + <string name="day_of_week_shortest_thursday">Π</string> + <string name="day_of_week_shortest_friday">Π</string> + <string name="day_of_week_shortest_saturday">Σ</string> + + <string name="am">π.μ.</string> + <string name="pm">μ.μ.</string> + <string name="yesterday">Χτες</string> + <string name="today">Σήμερα</string> + <string name="tomorrow">Αύριο</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %d %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml new file mode 100644 index 0000000..9811b68 --- /dev/null +++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-e/%m/%Y</string> + <string name="numeric_date_format">d/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%d/%m/%Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <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_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">%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="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">%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_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, %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, %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 9da879b..3de378b 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -314,10 +314,6 @@ <skip /> <!-- no translation found for permdesc_setAlwaysFinish (2437195869854312148) --> <skip /> - <!-- no translation found for permlab_fotaUpdate (1813039882829307079) --> - <skip /> - <!-- no translation found for permdesc_fotaUpdate (2544137712607584763) --> - <skip /> <!-- no translation found for permlab_batteryStats (1598947993704535568) --> <skip /> <!-- no translation found for permdesc_batteryStats (6247598531831307989) --> @@ -710,7 +706,6 @@ <!-- no translation found for lockscreen_glogin_invalid_input (4881057177478491580) --> <skip /> <!-- no translation found for status_bar_time_format (2168573805413119180) --> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <!-- no translation found for hour_minute_ampm (1850330605794978742) --> <skip /> <!-- no translation found for hour_minute_cap_ampm (1122840227537374196) --> @@ -864,35 +859,24 @@ <!-- from values-de/strings.xml and removal of all the german craziyness--> <skip /> <!-- no translation found for numeric_date (5120078478872821100) --> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for wday1_date1_time1_wday2_date2_time2 (7066878981949584861) --> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> <!-- no translation found for wday1_date1_wday2_date2 (8671068747172261907) --> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> <!-- no translation found for numeric_date (5537215108967329745) --> <skip /> <!-- no translation found for date1_time1_date2_time2 (3645498975775629615) --> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> <!-- no translation found for date1_date2 (377057563556488062) --> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> <!-- no translation found for time1_time2 (3173474242109288305) --> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> <!-- no translation found for time_wday_date (8928955562064570313) --> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for wday_date (8794741400546136975) --> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for time_date (1922644512833014496) --> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for time_wday (1422050241301754712) --> <skip /> <!-- no translation found for full_date_month_first (6011143962222283357) --> <skip /> <!-- no translation found for full_date_day_first (8621594762705478189) --> - <string name="full_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string> <!-- no translation found for medium_date_month_first (48990963718825728) --> <skip /> <!-- no translation found for medium_date_day_first (2898992016440387123) --> - <string name="medium_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string> <!-- no translation found for twelve_hour_time_format (6015557937879492156) --> <skip /> <!-- no translation found for twenty_four_hour_time_format (5176807998669709535) --> @@ -906,73 +890,43 @@ <!-- no translation found for Midnight (1260172107848123187) --> <skip /> <!-- no translation found for month_day (3356633704511426364) --> - <string name="month_day">"<xliff:g id="day" example="9">%-d</xliff:g> <xliff:g id="month" example="October">%B</xliff:g>"</string> <!-- no translation found for month (3017405760734206414) --> <skip /> <!-- no translation found for month_day_year (2435948225709176752) --> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (6228414124777343135) --> <skip /> <!-- no translation found for time_of_day (8375993139317154157) --> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <!-- no translation found for date_and_time (9197690194373107109) --> <skip /> <!-- no translation found for same_year_md1_md2 (9199324363135981317) --> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_md1_wday2_md2 (6006392413355305178) --> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for date_and_time (353898423108629694) --> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for same_year_mdy1_mdy2 (1576657593937827090) --> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_mdy1_wday2_mdy2 (9135935796468891580) --> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> <!-- no translation found for same_year_md1_time1_md2_time2 (2172964106375558081) --> - <string name="same_year_md1_time1_md2_time2">" <xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_md1_time1_wday2_md2_time2 (1702879534101786310) --> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_year_mdy1_time1_mdy2_time2 (2476443311723358767) --> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_mdy1_time1_wday2_mdy2_time2 (1564837340334069879) --> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_md1_md2 (8908376522875100300) --> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_md1_wday2_md2 (3239690882018292077) --> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for numeric_mdy1_mdy2 (8883797176939233525) --> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_mdy1_wday2_mdy2 (4150475769255828954) --> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for numeric_md1_time1_md2_time2 (3624746590607741419) --> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_md1_time1_wday2_md2_time2 (4258040955467298134) --> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_mdy1_time1_mdy2_time2 (3598215409314517987) --> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_mdy1_time1_wday2_mdy2_time2 (264076937155877259) --> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_md1_md2 (2393563617438036111) --> - <string name="same_month_md1_md2">"<xliff:g id="DAY1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="DAY2" example="3">%8$s</xliff:g> <xliff:g id="MONTH1" example="Oct">%2$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_md1_wday2_md2 (1208946773794057819) --> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for same_month_mdy1_mdy2 (3713236637869030492) --> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="DAY2" example="3">%8$s</xliff:g> <xliff:g id="MONTH1" example="Oct">%2$s</xliff:g> <xliff:g id="YEAR2" example="2007">%9$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_mdy1_wday2_mdy2 (389638922479870472) --> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for same_month_md1_time1_md2_time2 (7477075526337542685) --> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_md1_time1_wday2_md2_time2 (3516978303779391173) --> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_mdy1_time1_mdy2_time2 (7320410992514057310) --> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_mdy1_time1_wday2_mdy2_time2 (1332950588774239228) --> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for abbrev_month_day_year (5767271534015320250) --> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for abbrev_month_year (8058929633673942490) --> <skip /> <!-- no translation found for abbrev_month_day (458867920693482757) --> - <string name="abbrev_month_day">"<xliff:g id="day" example="31">%-d</xliff:g> <xliff:g id="month" example="Oct">%b</xliff:g>"</string> <!-- no translation found for abbrev_month (1674509986330181349) --> <skip /> <!-- no translation found for day_of_week_long_sunday (9057662850446501884) --> diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml new file mode 100644 index 0000000..1e250c7 --- /dev/null +++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%B %-e, %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%Y-%m-%d, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%Y-%m-%d</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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, %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> + <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">%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_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_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s - %7$s %8$s, %9$s, %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s - %7$s %8$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_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_year_mdy1_mdy2">%2$s %3$s - %7$s %8$s, %9$s</string> + <string name="same_month_mdy1_mdy2">%2$s %3$s-%8$s, %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s - %6$s, %7$s %8$s, %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml new file mode 100644 index 0000000..0e3e035 --- /dev/null +++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%-e %b %Y, %H:%M:%S</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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="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">%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_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 %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, %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml new file mode 100644 index 0000000..2e59dcf --- /dev/null +++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%-e %b %Y, %H:%M:%S</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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="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">%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_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 %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 %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml new file mode 100644 index 0000000..e39a59a --- /dev/null +++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%d-%b-%Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%d-%b-%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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="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">%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_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 %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 %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml new file mode 100644 index 0000000..3a8b50b --- /dev/null +++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-e/%m/%Y</string> + <string name="numeric_date_format">d/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-e/%m/%Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <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_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">%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="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">%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_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, %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, %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rSG/donottranslate-cldr.xml b/core/res/res/values-en-rSG/donottranslate-cldr.xml new file mode 100644 index 0000000..286cc0e --- /dev/null +++ b/core/res/res/values-en-rSG/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-m/%-e/%Y</string> + <string name="numeric_date_format">M/d/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%B %-e, %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%b %-e, %Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%b %-e, %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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">%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_mdy1_time1_mdy2_time2">%2$s/%3$s/%4$s, %5$s – %7$s/%8$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="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">%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_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_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$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_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_year_mdy1_mdy2">%2$s %3$s – %7$s %8$s, %9$s</string> + <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rSG/strings.xml b/core/res/res/values-en-rSG/strings.xml index 6850a5d..2ec6b0b 100644 --- a/core/res/res/values-en-rSG/strings.xml +++ b/core/res/res/values-en-rSG/strings.xml @@ -314,10 +314,6 @@ <skip /> <!-- no translation found for permdesc_setAlwaysFinish (2437195869854312148) --> <skip /> - <!-- no translation found for permlab_fotaUpdate (1813039882829307079) --> - <skip /> - <!-- no translation found for permdesc_fotaUpdate (2544137712607584763) --> - <skip /> <!-- no translation found for permlab_batteryStats (1598947993704535568) --> <skip /> <!-- no translation found for permdesc_batteryStats (6247598531831307989) --> @@ -710,7 +706,6 @@ <!-- no translation found for lockscreen_glogin_invalid_input (4881057177478491580) --> <skip /> <!-- no translation found for status_bar_time_format (2168573805413119180) --> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> <!-- no translation found for hour_minute_ampm (1850330605794978742) --> <skip /> <!-- no translation found for hour_minute_cap_ampm (1122840227537374196) --> @@ -863,33 +858,21 @@ <skip /> <!-- copied from values-de/strings.xml with the crazyness of the . removed--> <!-- no translation found for wday1_date1_time1_wday2_date2_time2 (7066878981949584861) --> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> <!-- no translation found for wday1_date1_wday2_date2 (8671068747172261907) --> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> <!-- no translation found for numeric_date (5537215108967329745) --> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for date1_time1_date2_time2 (3645498975775629615) --> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> <!-- no translation found for date1_date2 (377057563556488062) --> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> <!-- no translation found for time1_time2 (3173474242109288305) --> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> <!-- no translation found for time_wday_date (8928955562064570313) --> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for wday_date (8794741400546136975) --> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for time_date (1922644512833014496) --> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> <!-- no translation found for time_wday (1422050241301754712) --> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> <!-- no translation found for full_date_month_first (6011143962222283357) --> <skip /> <!-- no translation found for full_date_day_first (8621594762705478189) --> - <string name="full_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string> <!-- no translation found for medium_date_month_first (48990963718825728) --> <skip /> <!-- no translation found for medium_date_day_first (2898992016440387123) --> - <string name="medium_date_day_first">"<xliff:g id="DAY">dd</xliff:g> <xliff:g id="MONTH">MMM</xliff:g> <xliff:g id="YEAR">yyyy</xliff:g>"</string> <!-- no translation found for twelve_hour_time_format (6015557937879492156) --> <skip /> <!-- no translation found for twenty_four_hour_time_format (5176807998669709535) --> @@ -903,71 +886,42 @@ <!-- no translation found for Midnight (1260172107848123187) --> <skip /> <!-- no translation found for month_day (3356633704511426364) --> - <string name="month_day">"<xliff:g id="day" example="9">%-d</xliff:g> <xliff:g id="month" example="October">%B</xliff:g>"</string> <!-- no translation found for month (3017405760734206414) --> <skip /> <!-- no translation found for month_day_year (2435948225709176752) --> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (6228414124777343135) --> <skip /> <!-- no translation found for time_of_day (8375993139317154157) --> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> <!-- no translation found for date_and_time (9197690194373107109) --> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for same_year_md1_md2 (9199324363135981317) --> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_md1_wday2_md2 (6006392413355305178) --> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for same_year_mdy1_mdy2 (1576657593937827090) --> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_mdy1_wday2_mdy2 (9135935796468891580) --> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> <!-- no translation found for same_year_md1_time1_md2_time2 (2172964106375558081) --> <skip /> <!-- no translation found for same_year_wday1_md1_time1_wday2_md2_time2 (1702879534101786310) --> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_year_mdy1_time1_mdy2_time2 (2476443311723358767) --> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_year_wday1_mdy1_time1_wday2_mdy2_time2 (1564837340334069879) --> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_md1_md2 (8908376522875100300) --> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_md1_wday2_md2 (3239690882018292077) --> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for numeric_mdy1_mdy2 (8883797176939233525) --> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_mdy1_wday2_mdy2 (4150475769255828954) --> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for numeric_md1_time1_md2_time2 (3624746590607741419) --> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_md1_time1_wday2_md2_time2 (4258040955467298134) --> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_mdy1_time1_mdy2_time2 (3598215409314517987) --> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for numeric_wday1_mdy1_time1_wday2_mdy2_time2 (264076937155877259) --> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_md1_md2 (2393563617438036111) --> - <string name="same_month_md1_md2">"<xliff:g id="DAY1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="DAY2" example="3">%8$s</xliff:g> <xliff:g id="MONTH1" example="Oct">%2$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_md1_wday2_md2 (1208946773794057819) --> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> <!-- no translation found for same_month_mdy1_mdy2 (3713236637869030492) --> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="DAY2" example="3">%8$s</xliff:g> <xliff:g id="MONTH1" example="Oct">%2$s</xliff:g> <xliff:g id="YEAR2" example="2007">%9$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_mdy1_wday2_mdy2 (389638922479870472) --> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> <!-- no translation found for same_month_md1_time1_md2_time2 (7477075526337542685) --> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_md1_time1_wday2_md2_time2 (3516978303779391173) --> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_mdy1_time1_mdy2_time2 (7320410992514057310) --> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for same_month_wday1_mdy1_time1_wday2_mdy2_time2 (1332950588774239228) --> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> <!-- no translation found for abbrev_month_day_year (5767271534015320250) --> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for abbrev_month_year (8058929633673942490) --> <skip /> <!-- no translation found for abbrev_month_day (458867920693482757) --> - <string name="abbrev_month_day">"<xliff:g id="day" example="31">%-d</xliff:g> <xliff:g id="month" example="Oct">%b</xliff:g>"</string> <!-- no translation found for abbrev_month (1674509986330181349) --> <skip /> <!-- no translation found for day_of_week_long_sunday (9057662850446501884) --> diff --git a/core/res/res/values-en-rUS/donottranslate-cldr.xml b/core/res/res/values-en-rUS/donottranslate-cldr.xml new file mode 100644 index 0000000..286cc0e --- /dev/null +++ b/core/res/res/values-en-rUS/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-m/%-e/%Y</string> + <string name="numeric_date_format">M/d/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%B %-e, %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%b %-e, %Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%b %-e, %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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">%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_mdy1_time1_mdy2_time2">%2$s/%3$s/%4$s, %5$s – %7$s/%8$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="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">%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_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_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$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_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_year_mdy1_mdy2">%2$s %3$s – %7$s %8$s, %9$s</string> + <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-en-rUS/strings.xml b/core/res/res/values-en-rUS/strings.xml index b9df983..05f30fc 100644 --- a/core/res/res/values-en-rUS/strings.xml +++ b/core/res/res/values-en-rUS/strings.xml @@ -314,10 +314,6 @@ <skip /> <!-- no translation found for permdesc_setAlwaysFinish (2437195869854312148) --> <skip /> - <!-- no translation found for permlab_fotaUpdate (1813039882829307079) --> - <skip /> - <!-- no translation found for permdesc_fotaUpdate (2544137712607584763) --> - <skip /> <!-- no translation found for permlab_batteryStats (1598947993704535568) --> <skip /> <!-- no translation found for permdesc_batteryStats (6247598531831307989) --> diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml new file mode 100644 index 0000000..2e2d608 --- /dev/null +++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%Y/%m/%d</string> + <string name="numeric_date_format">yyyy/MM/dd</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%d %b %Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%d %b %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%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> + <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">%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 %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> + <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">%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 %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 %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 %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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-es-rES/donottranslate-cldr.xml b/core/res/res/values-es-rES/donottranslate-cldr.xml new file mode 100644 index 0000000..c1dc58b --- /dev/null +++ b/core/res/res/values-es-rES/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">enero</string> + <string name="month_long_standalone_february">febrero</string> + <string name="month_long_standalone_march">marzo</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">mayo</string> + <string name="month_long_standalone_june">junio</string> + <string name="month_long_standalone_july">julio</string> + <string name="month_long_standalone_august">agosto</string> + <string name="month_long_standalone_september">septiembre</string> + <string name="month_long_standalone_october">octubre</string> + <string name="month_long_standalone_november">noviembre</string> + <string name="month_long_standalone_december">diciembre</string> + + <string name="month_long_january">enero</string> + <string name="month_long_february">febrero</string> + <string name="month_long_march">marzo</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">mayo</string> + <string name="month_long_june">junio</string> + <string name="month_long_july">julio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">septiembre</string> + <string name="month_long_october">octubre</string> + <string name="month_long_november">noviembre</string> + <string name="month_long_december">diciembre</string> + + <string name="month_medium_january">ene</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">abr</string> + <string name="month_medium_may">may</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">oct</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">E</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">lunes</string> + <string name="day_of_week_long_tuesday">martes</string> + <string name="day_of_week_long_wednesday">miércoles</string> + <string name="day_of_week_long_thursday">jueves</string> + <string name="day_of_week_long_friday">viernes</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mié</string> + <string name="day_of_week_medium_thursday">jue</string> + <string name="day_of_week_medium_friday">vie</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mié</string> + <string name="day_of_week_short_thursday">jue</string> + <string name="day_of_week_short_friday">vie</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">ayer</string> + <string name="today">hoy</string> + <string name="tomorrow">mañana</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s – %8$s de %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 de %2$s – %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s – %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 – %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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml new file mode 100644 index 0000000..d6d8954 --- /dev/null +++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">enero</string> + <string name="month_long_standalone_february">febrero</string> + <string name="month_long_standalone_march">marzo</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">mayo</string> + <string name="month_long_standalone_june">junio</string> + <string name="month_long_standalone_july">julio</string> + <string name="month_long_standalone_august">agosto</string> + <string name="month_long_standalone_september">septiembre</string> + <string name="month_long_standalone_october">octubre</string> + <string name="month_long_standalone_november">noviembre</string> + <string name="month_long_standalone_december">diciembre</string> + + <string name="month_long_january">enero</string> + <string name="month_long_february">febrero</string> + <string name="month_long_march">marzo</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">mayo</string> + <string name="month_long_june">junio</string> + <string name="month_long_july">julio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">septiembre</string> + <string name="month_long_october">octubre</string> + <string name="month_long_november">noviembre</string> + <string name="month_long_december">diciembre</string> + + <string name="month_medium_january">ene</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">abr</string> + <string name="month_medium_may">may</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">oct</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">E</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">lunes</string> + <string name="day_of_week_long_tuesday">martes</string> + <string name="day_of_week_long_wednesday">miércoles</string> + <string name="day_of_week_long_thursday">jueves</string> + <string name="day_of_week_long_friday">viernes</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mié</string> + <string name="day_of_week_medium_thursday">jue</string> + <string name="day_of_week_medium_friday">vie</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mié</string> + <string name="day_of_week_short_thursday">jue</string> + <string name="day_of_week_short_friday">vie</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">ayer</string> + <string name="today">hoy</string> + <string name="tomorrow">mañana</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-m/%-e/%Y</string> + <string name="numeric_date_format">M/d/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %b %-e, %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%b %-e, %Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e 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 %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 %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> + <string name="date1_time1_date2_time2">%3$s %2$s a el %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">%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 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 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 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 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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 7b60a39..84435aa 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -178,14 +178,10 @@ <string name="permdesc_changeConfiguration">"Admite una aplicación para cambiar la configuración actual, como el tamaño de fuente local o general."</string> <string name="permlab_restartPackages">"reiniciar otras aplicaciones"</string> <string name="permdesc_restartPackages">"Admite una aplicación que reinicia otras aplicaciones por la fuerza."</string> - <string name="permlab_setProcessForeground">"impedir la detención"</string> - <string name="permdesc_setProcessForeground">"Admite una aplicación que ejecuta cualquier tipo de proceso en primer plano, de manera que no se pueda suprimir. Se debe evitar utilizarlo en aplicaciones normales."</string> <string name="permlab_forceBack">"provocar que la aplicación se acerque"</string> <string name="permdesc_forceBack">"Admite una aplicación que provoca que cualquier actividad del fondo se acerque y vuelva a alejarse. Se debe evitar utilizarlo en aplicaciones normales."</string> <string name="permlab_dump">"recuperar el estado interno del sistema"</string> <string name="permdesc_dump">"Admite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una gran variedad de información privada y segura que normalmente nunca necesitaría."</string> - <string name="permlab_addSystemService">"publicar servicios de bajo nivel"</string> - <string name="permdesc_addSystemService">"Admite que la aplicación publique sus propios servicios del sistema de bajo nivel. Las aplicaciones maliciosas pueden apropiarse del sistema y robar o corromper cualquiera de sus datos."</string> <string name="permlab_runSetActivityWatcher">"verificar y controlar todos los lanzamientos de actividades"</string> <string name="permdesc_runSetActivityWatcher">"Admite una aplicación que verifica y controla el lanzamiento de actividades por parte del sistema. Las aplicaciones maliciosas pueden comprometer totalmente al sistema. Este permiso sólo es necesario para el desarrollo, nunca para el uso normal del teléfono."</string> <string name="permlab_broadcastPackageRemoved">"enviar emisión de paquete eliminado"</string> @@ -198,8 +194,6 @@ <string name="permdesc_setProcessLimit">"Admite una aplicación que controla la cantidad máxima de procesos que se ejecutarán. No se utiliza nunca en aplicaciones normales."</string> <string name="permlab_setAlwaysFinish">"cerrar todas las aplicaciones del fondo"</string> <string name="permdesc_setAlwaysFinish">"Admite una aplicación que controla si las actividades siempre finalizan cuando van al fondo. No se utiliza nunca en aplicaciones normales."</string> - <string name="permlab_fotaUpdate">"instalar automáticamente las actualizaciones del sistema"</string> - <string name="permdesc_fotaUpdate">"Admite una aplicación que recibe notificaciones sobre las actualizaciones pendientes del sistema y activa su instalación. Las aplicaciones maliciosas pueden utilizarlo para corromper el sistema con actualizaciones no autorizadas o, en general, para interferir en el proceso de actualización."</string> <string name="permlab_batteryStats">"modificar la estadística de la batería"</string> <string name="permdesc_batteryStats">"Admite la modificación de estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben utilizarlo."</string> <string name="permlab_internalSystemWindow">"mostrar ventanas no autorizadas"</string> @@ -436,9 +430,6 @@ <string name="lockscreen_glogin_password_hint">"Contraseña"</string> <string name="lockscreen_glogin_submit_button">"Inicia sesión"</string> <string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña incorrecta."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Borrar notificaciones"</string> @@ -470,9 +461,6 @@ <string name="menu_enter_shortcut_label">"ingresar"</string> <string name="menu_delete_shortcut_label">"borrar"</string> <string name="search_go">"Buscar"</string> - <string name="today">"Hoy"</string> - <string name="yesterday">"Ayer"</string> - <string name="tomorrow">"Mañana"</string> <string name="oneMonthDurationPast">"hace 1 mes"</string> <string name="beforeOneMonthDurationPast">"Anterior a 1 mes atrás"</string> <plurals name="num_seconds_ago"> @@ -554,13 +542,6 @@ <string name="weeks">"semanas"</string> <string name="year">"año"</string> <string name="years">"años"</string> - <string name="sunday">"Domingo"</string> - <string name="monday">"Lunes"</string> - <string name="tuesday">"Martes"</string> - <string name="wednesday">"Miércoles"</string> - <string name="thursday">"Jueves"</string> - <string name="friday">"Viernes"</string> - <string name="saturday">"Sábado"</string> <string name="every_weekday">"Los días de semana (lunes a viernes)"</string> <string name="daily">"Diariamente"</string> <string name="weekly">"Semanalmente el día <xliff:g id="DAY">%s</xliff:g>"</string> @@ -570,137 +551,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Lo sentimos, este video no es válido para las transmisiones a este dispositivo."</string> <string name="VideoView_error_text_unknown">"Lo sentimos, no se puede reproducir este video."</string> <string name="VideoView_error_button">"Aceptar"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mediodía"</string> <string name="Noon">"Mediodía"</string> <string name="midnight">"medianoche"</string> <string name="Midnight">"Medianoche"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"Domingo"</string> - <string name="day_of_week_long_monday">"Lunes"</string> - <string name="day_of_week_long_tuesday">"Martes"</string> - <string name="day_of_week_long_wednesday">"Miércoles"</string> - <string name="day_of_week_long_thursday">"Jueves"</string> - <string name="day_of_week_long_friday">"Viernes"</string> - <string name="day_of_week_long_saturday">"Sábado"</string> - <string name="day_of_week_medium_sunday">"Dom."</string> - <string name="day_of_week_medium_monday">"Lun."</string> - <string name="day_of_week_medium_tuesday">"Mar."</string> - <string name="day_of_week_medium_wednesday">"Mié."</string> - <string name="day_of_week_medium_thursday">"Jue."</string> - <string name="day_of_week_medium_friday">"Vie."</string> - <string name="day_of_week_medium_saturday">"Sáb."</string> - <string name="day_of_week_short_sunday">"Dom."</string> - <string name="day_of_week_short_monday">"Lun."</string> - <string name="day_of_week_short_tuesday">"Mar."</string> - <string name="day_of_week_short_wednesday">"Nosotros"</string> - <string name="day_of_week_short_thursday">"Jue."</string> - <string name="day_of_week_short_friday">"V"</string> - <string name="day_of_week_short_saturday">"Sáb."</string> - <string name="day_of_week_shorter_sunday">"Dom."</string> - <string name="day_of_week_shorter_monday">"L"</string> - <string name="day_of_week_shorter_tuesday">"Mar."</string> - <string name="day_of_week_shorter_wednesday">"M"</string> - <string name="day_of_week_shorter_thursday">"Jue."</string> - <string name="day_of_week_shorter_friday">"V"</string> - <string name="day_of_week_shorter_saturday">"Sáb."</string> - <string name="day_of_week_shortest_sunday">"D"</string> - <string name="day_of_week_shortest_monday">"L"</string> - <string name="day_of_week_shortest_tuesday">"Mar."</string> - <string name="day_of_week_shortest_wednesday">"M"</string> - <string name="day_of_week_shortest_thursday">"Jue."</string> - <string name="day_of_week_shortest_friday">"V"</string> - <string name="day_of_week_shortest_saturday">"D"</string> - <string name="month_long_january">"Enero"</string> - <string name="month_long_february">"Febrero"</string> - <string name="month_long_march">"Marzo"</string> - <string name="month_long_april">"Abril"</string> - <string name="month_long_may">"Mayo"</string> - <string name="month_long_june">"Junio"</string> - <string name="month_long_july">"Julio"</string> - <string name="month_long_august">"Agosto"</string> - <string name="month_long_september">"Septiembre"</string> - <string name="month_long_october">"Octubre"</string> - <string name="month_long_november">"Noviembre"</string> - <string name="month_long_december">"Diciembre"</string> - <string name="month_medium_january">"Ene."</string> - <string name="month_medium_february">"Feb."</string> - <string name="month_medium_march">"Mar."</string> - <string name="month_medium_april">"Abr."</string> - <string name="month_medium_may">"Mayo"</string> - <string name="month_medium_june">"Jun."</string> - <string name="month_medium_july">"Jul."</string> - <string name="month_medium_august">"Ago."</string> - <string name="month_medium_september">"Sep."</string> - <string name="month_medium_october">"Oct."</string> - <string name="month_medium_november">"Nov."</string> - <string name="month_medium_december">"Dic."</string> - <string name="month_shortest_january">"E"</string> - <string name="month_shortest_february">"V"</string> - <string name="month_shortest_march">"M"</string> - <string name="month_shortest_april">"A"</string> - <string name="month_shortest_may">"M"</string> - <string name="month_shortest_june">"E"</string> - <string name="month_shortest_july">"J"</string> - <string name="month_shortest_august">"Ago."</string> - <string name="month_shortest_september">"D"</string> - <string name="month_shortest_october">"O"</string> - <string name="month_shortest_november">"N"</string> - <string name="month_shortest_december">"Dic."</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Seleccionar todos"</string> diff --git a/core/res/res/values-es/donottranslate-cldr.xml b/core/res/res/values-es/donottranslate-cldr.xml new file mode 100644 index 0000000..c1dc58b --- /dev/null +++ b/core/res/res/values-es/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">enero</string> + <string name="month_long_standalone_february">febrero</string> + <string name="month_long_standalone_march">marzo</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">mayo</string> + <string name="month_long_standalone_june">junio</string> + <string name="month_long_standalone_july">julio</string> + <string name="month_long_standalone_august">agosto</string> + <string name="month_long_standalone_september">septiembre</string> + <string name="month_long_standalone_october">octubre</string> + <string name="month_long_standalone_november">noviembre</string> + <string name="month_long_standalone_december">diciembre</string> + + <string name="month_long_january">enero</string> + <string name="month_long_february">febrero</string> + <string name="month_long_march">marzo</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">mayo</string> + <string name="month_long_june">junio</string> + <string name="month_long_july">julio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">septiembre</string> + <string name="month_long_october">octubre</string> + <string name="month_long_november">noviembre</string> + <string name="month_long_december">diciembre</string> + + <string name="month_medium_january">ene</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">abr</string> + <string name="month_medium_may">may</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">oct</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">E</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">lunes</string> + <string name="day_of_week_long_tuesday">martes</string> + <string name="day_of_week_long_wednesday">miércoles</string> + <string name="day_of_week_long_thursday">jueves</string> + <string name="day_of_week_long_friday">viernes</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mié</string> + <string name="day_of_week_medium_thursday">jue</string> + <string name="day_of_week_medium_friday">vie</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mié</string> + <string name="day_of_week_short_thursday">jue</string> + <string name="day_of_week_short_friday">vie</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">a.m.</string> + <string name="pm">p.m.</string> + <string name="yesterday">ayer</string> + <string name="today">hoy</string> + <string name="tomorrow">mañana</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s – %8$s de %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 de %2$s – %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s – %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 – %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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index a9f267a..920ac3e 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Permite que una aplicación cambie la configuración actual como, por ejemplo, la configuración local o el tamaño de fuente general."</string> <string name="permlab_restartPackages">"reiniciar otras aplicaciones"</string> <string name="permdesc_restartPackages">"Permite que una aplicación reinicie de forma forzosa otras aplicaciones."</string> - <string name="permlab_setProcessForeground">"impedir su interrupción"</string> - <string name="permdesc_setProcessForeground">"Permite que una aplicación ejecute cualquier proceso en segundo plano, de forma que no se pueda interrumpir. No debería ser necesario nunca para las aplicaciones normales."</string> <string name="permlab_forceBack">"forzar el cierre de la aplicación"</string> <string name="permdesc_forceBack">"Permite que una aplicación fuerce a cualquier actividad en segundo plano a cerrarse y volver a la pantalla anterior. No debería ser necesario nunca para las aplicaciones normales."</string> <string name="permlab_dump">"recuperar estado interno del sistema"</string> <string name="permdesc_dump">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones malintencionadas pueden recuperar una amplia variedad de información protegida y privada que normalmente no deberían necesitar."</string> - <string name="permlab_addSystemService">"publicar servicios de nivel inferior"</string> - <string name="permdesc_addSystemService">"Permite que la aplicación publique sus propios servicios de sistema de nivel inferior. Las aplicaciones malintencionadas pueden hacerse con el control del sistema, y robar o dañar los datos contenidos en él."</string> <string name="permlab_runSetActivityWatcher">"supervisar y controlar la ejecución de todas las aplicaciones"</string> <string name="permdesc_runSetActivityWatcher">"Permite que una aplicación supervise y controle la ejecución de las actividades por parte del sistema. Las aplicaciones malintencionadas pueden vulnerar la seguridad del sistema. Este permiso sólo es necesario para tareas de desarrollo, nunca para el uso habitual del teléfono."</string> <string name="permlab_broadcastPackageRemoved">"enviar emisión eliminada de paquete"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Permite que una aplicación controle el número máximo de procesos que se ejecutarán. No es necesario nunca para las aplicaciones normales."</string> <string name="permlab_setAlwaysFinish">"hacer que se cierren todas las aplicaciones en segundo plano"</string> <string name="permdesc_setAlwaysFinish">"Permite que una aplicación controle si las actividades finalizan siempre en cuanto pasan a segundo plano. No es necesario nunca para las aplicaciones normales."</string> - <string name="permlab_fotaUpdate">"instalar actualizaciones del sistema de forma automática"</string> - <string name="permdesc_fotaUpdate">"Permite que una aplicación reciba notificaciones sobre actualizaciones pendientes del sistema e inicie su instalación. Las aplicaciones malintencionadas pueden utilizar este permiso para provocar daños en el sistema con actualizaciones no autorizadas o interferir de forma general en el proceso de actualización."</string> <string name="permlab_batteryStats">"modificar estadísticas de la batería"</string> <string name="permdesc_batteryStats">"Permite la modificación de estadísticas recopiladas sobre la batería. No está destinado al uso por parte de aplicaciones normales."</string> <string name="permlab_internalSystemWindow">"mostrar ventanas no autorizadas"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Contraseña"</string> <string name="lockscreen_glogin_submit_button">"Acceder"</string> <string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña no válido"</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Cerrar notificaciones"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"intro"</string> <string name="menu_delete_shortcut_label">"suprimir"</string> <string name="search_go">"Buscar"</string> - <string name="today">"Hoy"</string> - <string name="yesterday">"Ayer"</string> - <string name="tomorrow">"Mañana"</string> <string name="oneMonthDurationPast">"Hace un mes"</string> <string name="beforeOneMonthDurationPast">"Hace más de un mes"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"semanas"</string> <string name="year">"año"</string> <string name="years">"años"</string> - <string name="sunday">"Domingo"</string> - <string name="monday">"Lunes"</string> - <string name="tuesday">"Martes"</string> - <string name="wednesday">"Miércoles"</string> - <string name="thursday">"Jueves"</string> - <string name="friday">"Viernes"</string> - <string name="saturday">"Sábado"</string> <string name="every_weekday">"Todos los días laborables (Lun-Vie)"</string> <string name="daily">"Diariamente"</string> <string name="weekly">"Semanalmente, el <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Este vídeo no se puede transmitir al dispositivo."</string> <string name="VideoView_error_text_unknown">"Este vídeo no se puede reproducir."</string> <string name="VideoView_error_button">"Aceptar"</string> - <string name="am">"a.m."</string> - <string name="pm">"p.m."</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mediodía"</string> <string name="Noon">"Mediodía"</string> <string name="midnight">"medianoche"</string> <string name="Midnight">"Medianoche"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g> de <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g> de <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g> de <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g> de <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%b</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"Domingo"</string> - <string name="day_of_week_long_monday">"Lunes"</string> - <string name="day_of_week_long_tuesday">"Martes"</string> - <string name="day_of_week_long_wednesday">"Miércoles"</string> - <string name="day_of_week_long_thursday">"Jueves"</string> - <string name="day_of_week_long_friday">"Viernes"</string> - <string name="day_of_week_long_saturday">"Sábado"</string> - <string name="day_of_week_medium_sunday">"Dom"</string> - <string name="day_of_week_medium_monday">"Lun"</string> - <string name="day_of_week_medium_tuesday">"Mar"</string> - <string name="day_of_week_medium_wednesday">"Mié"</string> - <string name="day_of_week_medium_thursday">"Jue"</string> - <string name="day_of_week_medium_friday">"Vie"</string> - <string name="day_of_week_medium_saturday">"Sáb"</string> - <string name="day_of_week_short_sunday">"Do"</string> - <string name="day_of_week_short_monday">"Lu"</string> - <string name="day_of_week_short_tuesday">"Ma"</string> - <string name="day_of_week_short_wednesday">"Mi"</string> - <string name="day_of_week_short_thursday">"Ju"</string> - <string name="day_of_week_short_friday">"Vi"</string> - <string name="day_of_week_short_saturday">"Sá"</string> - <string name="day_of_week_shorter_sunday">"Do"</string> - <string name="day_of_week_shorter_monday">"L"</string> - <string name="day_of_week_shorter_tuesday">"Ma"</string> - <string name="day_of_week_shorter_wednesday">"Mi"</string> - <string name="day_of_week_shorter_thursday">"Ju"</string> - <string name="day_of_week_shorter_friday">"V"</string> - <string name="day_of_week_shorter_saturday">"S"</string> - <string name="day_of_week_shortest_sunday">"D"</string> - <string name="day_of_week_shortest_monday">"Mz"</string> - <string name="day_of_week_shortest_tuesday">"M"</string> - <string name="day_of_week_shortest_wednesday">"Mi"</string> - <string name="day_of_week_shortest_thursday">"M"</string> - <string name="day_of_week_shortest_friday">"V"</string> - <string name="day_of_week_shortest_saturday">"D"</string> - <string name="month_long_january">"Enero"</string> - <string name="month_long_february">"Febrero"</string> - <string name="month_long_march">"Marzo"</string> - <string name="month_long_april">"Abril"</string> - <string name="month_long_may">"Mayo"</string> - <string name="month_long_june">"Junio"</string> - <string name="month_long_july">"Julio"</string> - <string name="month_long_august">"Agosto"</string> - <string name="month_long_september">"Septiembre"</string> - <string name="month_long_october">"Octubre"</string> - <string name="month_long_november">"Noviembre"</string> - <string name="month_long_december">"Diciembre"</string> - <string name="month_medium_january">"Ene"</string> - <string name="month_medium_february">"Feb"</string> - <string name="month_medium_march">"Mar"</string> - <string name="month_medium_april">"Abr"</string> - <string name="month_medium_may">"May"</string> - <string name="month_medium_june">"Jun"</string> - <string name="month_medium_july">"Jul"</string> - <string name="month_medium_august">"Ago"</string> - <string name="month_medium_september">"Sep"</string> - <string name="month_medium_october">"Oct"</string> - <string name="month_medium_november">"Nov"</string> - <string name="month_medium_december">"Dic"</string> - <string name="month_shortest_january">"E"</string> - <string name="month_shortest_february">"V"</string> - <string name="month_shortest_march">"Mz"</string> - <string name="month_shortest_april">"A"</string> - <string name="month_shortest_may">"My"</string> - <string name="month_shortest_june">"J"</string> - <string name="month_shortest_july">"E"</string> - <string name="month_shortest_august">"Ag"</string> - <string name="month_shortest_september">"S"</string> - <string name="month_shortest_october">"O"</string> - <string name="month_shortest_november">"N"</string> - <string name="month_shortest_december">"D"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Seleccionar todo"</string> diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml new file mode 100644 index 0000000..df3866e --- /dev/null +++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">tammikuu</string> + <string name="month_long_standalone_february">helmikuu</string> + <string name="month_long_standalone_march">maaliskuu</string> + <string name="month_long_standalone_april">huhtikuu</string> + <string name="month_long_standalone_may">toukokuu</string> + <string name="month_long_standalone_june">kesäkuu</string> + <string name="month_long_standalone_july">heinäkuu</string> + <string name="month_long_standalone_august">elokuu</string> + <string name="month_long_standalone_september">syyskuu</string> + <string name="month_long_standalone_october">lokakuu</string> + <string name="month_long_standalone_november">marraskuu</string> + <string name="month_long_standalone_december">joulukuu</string> + + <string name="month_long_january">tammikuuta</string> + <string name="month_long_february">helmikuuta</string> + <string name="month_long_march">maaliskuuta</string> + <string name="month_long_april">huhtikuuta</string> + <string name="month_long_may">toukokuuta</string> + <string name="month_long_june">kesäkuuta</string> + <string name="month_long_july">heinäkuuta</string> + <string name="month_long_august">elokuuta</string> + <string name="month_long_september">syyskuuta</string> + <string name="month_long_october">lokakuuta</string> + <string name="month_long_november">marraskuuta</string> + <string name="month_long_december">joulukuuta</string> + + <string name="month_medium_january">tammikuuta</string> + <string name="month_medium_february">helmikuuta</string> + <string name="month_medium_march">maaliskuuta</string> + <string name="month_medium_april">huhtikuuta</string> + <string name="month_medium_may">toukokuuta</string> + <string name="month_medium_june">kesäkuuta</string> + <string name="month_medium_july">heinäkuuta</string> + <string name="month_medium_august">elokuuta</string> + <string name="month_medium_september">syyskuuta</string> + <string name="month_medium_october">lokakuuta</string> + <string name="month_medium_november">marraskuuta</string> + <string name="month_medium_december">joulukuuta</string> + + <string name="month_shortest_january">T</string> + <string name="month_shortest_february">H</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">H</string> + <string name="month_shortest_may">T</string> + <string name="month_shortest_june">K</string> + <string name="month_shortest_july">H</string> + <string name="month_shortest_august">E</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">L</string> + <string name="month_shortest_november">M</string> + <string name="month_shortest_december">J</string> + + <string name="day_of_week_long_sunday">sunnuntaina</string> + <string name="day_of_week_long_monday">maanantaina</string> + <string name="day_of_week_long_tuesday">tiistaina</string> + <string name="day_of_week_long_wednesday">keskiviikkona</string> + <string name="day_of_week_long_thursday">torstaina</string> + <string name="day_of_week_long_friday">perjantaina</string> + <string name="day_of_week_long_saturday">lauantaina</string> + + <string name="day_of_week_medium_sunday">su</string> + <string name="day_of_week_medium_monday">ma</string> + <string name="day_of_week_medium_tuesday">ti</string> + <string name="day_of_week_medium_wednesday">ke</string> + <string name="day_of_week_medium_thursday">to</string> + <string name="day_of_week_medium_friday">pe</string> + <string name="day_of_week_medium_saturday">la</string> + + <string name="day_of_week_short_sunday">su</string> + <string name="day_of_week_short_monday">ma</string> + <string name="day_of_week_short_tuesday">ti</string> + <string name="day_of_week_short_wednesday">ke</string> + <string name="day_of_week_short_thursday">to</string> + <string name="day_of_week_short_friday">pe</string> + <string name="day_of_week_short_saturday">la</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">K</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">ap.</string> + <string name="pm">ip.</string> + <string name="yesterday">eilen</string> + <string name="today">tänään</string> + <string name="tomorrow">huomenna</string> + + <string name="hour_minute_24">%-k.%M</string> + <string name="hour_minute_ampm">%-l.%M %p</string> + <string name="hour_minute_cap_ampm">%-l.%M %^p</string> + <string name="twelve_hour_time_format">h.mm a</string> + <string name="twenty_four_hour_time_format">H.mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k.%M.%S</string> + <string name="date_and_time">%-k.%M.%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr-rBE/donottranslate-cldr.xml b/core/res/res/values-fr-rBE/donottranslate-cldr.xml new file mode 100644 index 0000000..e190837 --- /dev/null +++ b/core/res/res/values-fr-rBE/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvier</string> + <string name="month_long_standalone_february">février</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avril</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juin</string> + <string name="month_long_standalone_july">juillet</string> + <string name="month_long_standalone_august">août</string> + <string name="month_long_standalone_september">septembre</string> + <string name="month_long_standalone_october">octobre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">décembre</string> + + <string name="month_long_january">janvier</string> + <string name="month_long_february">février</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avril</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juin</string> + <string name="month_long_july">juillet</string> + <string name="month_long_august">août</string> + <string name="month_long_september">septembre</string> + <string name="month_long_october">octobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">décembre</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">févr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juin</string> + <string name="month_medium_july">juil.</string> + <string name="month_medium_august">août</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">déc.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">dimanche</string> + <string name="day_of_week_long_monday">lundi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mercredi</string> + <string name="day_of_week_long_thursday">jeudi</string> + <string name="day_of_week_long_friday">vendredi</string> + <string name="day_of_week_long_saturday">samedi</string> + + <string name="day_of_week_medium_sunday">dim.</string> + <string name="day_of_week_medium_monday">lun.</string> + <string name="day_of_week_medium_tuesday">mar.</string> + <string name="day_of_week_medium_wednesday">mer.</string> + <string name="day_of_week_medium_thursday">jeu.</string> + <string name="day_of_week_medium_friday">ven.</string> + <string name="day_of_week_medium_saturday">sam.</string> + + <string name="day_of_week_short_sunday">dim.</string> + <string name="day_of_week_short_monday">lun.</string> + <string name="day_of_week_short_tuesday">mar.</string> + <string name="day_of_week_short_wednesday">mer.</string> + <string name="day_of_week_short_thursday">jeu.</string> + <string name="day_of_week_short_friday">ven.</string> + <string name="day_of_week_short_saturday">sam.</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">matin</string> + <string name="pm">soir</string> + <string name="yesterday">hier</string> + <string name="today">aujourd’hui</string> + <string name="tomorrow">demain</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e/%m/%Y</string> + <string name="numeric_date_format">d/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">du %1$s au %2$s</string> + <string name="date1_date2">du %2$s au %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">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="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">%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_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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr-rCA/donottranslate-cldr.xml b/core/res/res/values-fr-rCA/donottranslate-cldr.xml new file mode 100644 index 0000000..346b971 --- /dev/null +++ b/core/res/res/values-fr-rCA/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvier</string> + <string name="month_long_standalone_february">février</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avril</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juin</string> + <string name="month_long_standalone_july">juillet</string> + <string name="month_long_standalone_august">août</string> + <string name="month_long_standalone_september">septembre</string> + <string name="month_long_standalone_october">octobre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">décembre</string> + + <string name="month_long_january">janvier</string> + <string name="month_long_february">février</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avril</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juin</string> + <string name="month_long_july">juillet</string> + <string name="month_long_august">août</string> + <string name="month_long_september">septembre</string> + <string name="month_long_october">octobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">décembre</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">févr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juin</string> + <string name="month_medium_july">juil.</string> + <string name="month_medium_august">août</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">déc.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">dimanche</string> + <string name="day_of_week_long_monday">lundi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mercredi</string> + <string name="day_of_week_long_thursday">jeudi</string> + <string name="day_of_week_long_friday">vendredi</string> + <string name="day_of_week_long_saturday">samedi</string> + + <string name="day_of_week_medium_sunday">dim.</string> + <string name="day_of_week_medium_monday">lun.</string> + <string name="day_of_week_medium_tuesday">mar.</string> + <string name="day_of_week_medium_wednesday">mer.</string> + <string name="day_of_week_medium_thursday">jeu.</string> + <string name="day_of_week_medium_friday">ven.</string> + <string name="day_of_week_medium_saturday">sam.</string> + + <string name="day_of_week_short_sunday">dim.</string> + <string name="day_of_week_short_monday">lun.</string> + <string name="day_of_week_short_tuesday">mar.</string> + <string name="day_of_week_short_wednesday">mer.</string> + <string name="day_of_week_short_thursday">jeu.</string> + <string name="day_of_week_short_friday">ven.</string> + <string name="day_of_week_short_saturday">sam.</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">matin</string> + <string name="pm">soir</string> + <string name="yesterday">hier</string> + <string name="today">aujourd’hui</string> + <string name="tomorrow">demain</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y-%m-%d</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y-%m-%d</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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">du %1$s %4$s-%2$s-%3$s au %6$s %9$s-%7$s-%8$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_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="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">%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_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_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_year_mdy1_mdy2">du %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">du %1$s %3$s %2$s au %6$s %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr-rCH/donottranslate-cldr.xml b/core/res/res/values-fr-rCH/donottranslate-cldr.xml new file mode 100644 index 0000000..48db6b8 --- /dev/null +++ b/core/res/res/values-fr-rCH/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvier</string> + <string name="month_long_standalone_february">février</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avril</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juin</string> + <string name="month_long_standalone_july">juillet</string> + <string name="month_long_standalone_august">août</string> + <string name="month_long_standalone_september">septembre</string> + <string name="month_long_standalone_october">octobre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">décembre</string> + + <string name="month_long_january">janvier</string> + <string name="month_long_february">février</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avril</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juin</string> + <string name="month_long_july">juillet</string> + <string name="month_long_august">août</string> + <string name="month_long_september">septembre</string> + <string name="month_long_october">octobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">décembre</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">févr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juin</string> + <string name="month_medium_july">juil.</string> + <string name="month_medium_august">août</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">déc.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">dimanche</string> + <string name="day_of_week_long_monday">lundi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mercredi</string> + <string name="day_of_week_long_thursday">jeudi</string> + <string name="day_of_week_long_friday">vendredi</string> + <string name="day_of_week_long_saturday">samedi</string> + + <string name="day_of_week_medium_sunday">dim.</string> + <string name="day_of_week_medium_monday">lun.</string> + <string name="day_of_week_medium_tuesday">mar.</string> + <string name="day_of_week_medium_wednesday">mer.</string> + <string name="day_of_week_medium_thursday">jeu.</string> + <string name="day_of_week_medium_friday">ven.</string> + <string name="day_of_week_medium_saturday">sam.</string> + + <string name="day_of_week_short_sunday">dim.</string> + <string name="day_of_week_short_monday">lun.</string> + <string name="day_of_week_short_tuesday">mar.</string> + <string name="day_of_week_short_wednesday">mer.</string> + <string name="day_of_week_short_thursday">jeu.</string> + <string name="day_of_week_short_friday">ven.</string> + <string name="day_of_week_short_saturday">sam.</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">matin</string> + <string name="pm">soir</string> + <string name="yesterday">hier</string> + <string name="today">aujourd’hui</string> + <string name="tomorrow">demain</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <string name="time1_time2">du %1$s au %2$s</string> + <string name="date1_date2">du %2$s au %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">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="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">%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_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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr-rFR/donottranslate-cldr.xml b/core/res/res/values-fr-rFR/donottranslate-cldr.xml new file mode 100644 index 0000000..f340e83 --- /dev/null +++ b/core/res/res/values-fr-rFR/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvier</string> + <string name="month_long_standalone_february">février</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avril</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juin</string> + <string name="month_long_standalone_july">juillet</string> + <string name="month_long_standalone_august">août</string> + <string name="month_long_standalone_september">septembre</string> + <string name="month_long_standalone_october">octobre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">décembre</string> + + <string name="month_long_january">janvier</string> + <string name="month_long_february">février</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avril</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juin</string> + <string name="month_long_july">juillet</string> + <string name="month_long_august">août</string> + <string name="month_long_september">septembre</string> + <string name="month_long_october">octobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">décembre</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">févr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juin</string> + <string name="month_medium_july">juil.</string> + <string name="month_medium_august">août</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">déc.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">dimanche</string> + <string name="day_of_week_long_monday">lundi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mercredi</string> + <string name="day_of_week_long_thursday">jeudi</string> + <string name="day_of_week_long_friday">vendredi</string> + <string name="day_of_week_long_saturday">samedi</string> + + <string name="day_of_week_medium_sunday">dim.</string> + <string name="day_of_week_medium_monday">lun.</string> + <string name="day_of_week_medium_tuesday">mar.</string> + <string name="day_of_week_medium_wednesday">mer.</string> + <string name="day_of_week_medium_thursday">jeu.</string> + <string name="day_of_week_medium_friday">ven.</string> + <string name="day_of_week_medium_saturday">sam.</string> + + <string name="day_of_week_short_sunday">dim.</string> + <string name="day_of_week_short_monday">lun.</string> + <string name="day_of_week_short_tuesday">mar.</string> + <string name="day_of_week_short_wednesday">mer.</string> + <string name="day_of_week_short_thursday">jeu.</string> + <string name="day_of_week_short_friday">ven.</string> + <string name="day_of_week_short_saturday">sam.</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">matin</string> + <string name="pm">soir</string> + <string name="yesterday">hier</string> + <string name="today">aujourd’hui</string> + <string name="tomorrow">demain</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr/donottranslate-cldr.xml b/core/res/res/values-fr/donottranslate-cldr.xml new file mode 100644 index 0000000..f340e83 --- /dev/null +++ b/core/res/res/values-fr/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvier</string> + <string name="month_long_standalone_february">février</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avril</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juin</string> + <string name="month_long_standalone_july">juillet</string> + <string name="month_long_standalone_august">août</string> + <string name="month_long_standalone_september">septembre</string> + <string name="month_long_standalone_october">octobre</string> + <string name="month_long_standalone_november">novembre</string> + <string name="month_long_standalone_december">décembre</string> + + <string name="month_long_january">janvier</string> + <string name="month_long_february">février</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avril</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juin</string> + <string name="month_long_july">juillet</string> + <string name="month_long_august">août</string> + <string name="month_long_september">septembre</string> + <string name="month_long_october">octobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">décembre</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">févr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juin</string> + <string name="month_medium_july">juil.</string> + <string name="month_medium_august">août</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">déc.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">dimanche</string> + <string name="day_of_week_long_monday">lundi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mercredi</string> + <string name="day_of_week_long_thursday">jeudi</string> + <string name="day_of_week_long_friday">vendredi</string> + <string name="day_of_week_long_saturday">samedi</string> + + <string name="day_of_week_medium_sunday">dim.</string> + <string name="day_of_week_medium_monday">lun.</string> + <string name="day_of_week_medium_tuesday">mar.</string> + <string name="day_of_week_medium_wednesday">mer.</string> + <string name="day_of_week_medium_thursday">jeu.</string> + <string name="day_of_week_medium_friday">ven.</string> + <string name="day_of_week_medium_saturday">sam.</string> + + <string name="day_of_week_short_sunday">dim.</string> + <string name="day_of_week_short_monday">lun.</string> + <string name="day_of_week_short_tuesday">mar.</string> + <string name="day_of_week_short_wednesday">mer.</string> + <string name="day_of_week_short_thursday">jeu.</string> + <string name="day_of_week_short_friday">ven.</string> + <string name="day_of_week_short_saturday">sam.</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">matin</string> + <string name="pm">soir</string> + <string name="yesterday">hier</string> + <string name="today">aujourd’hui</string> + <string name="tomorrow">demain</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index c664d1a..ce650c1 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -21,6 +21,7 @@ <string name="gigabyteShort">"Go"</string> <string name="terabyteShort">"To"</string> <string name="petabyteShort">"Po"</string> + <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="KB">%2$s</xliff:g></string> <string name="untitled">"<sans titre>"</string> <string name="ellipsis">"…"</string> <string name="emptyPhoneNumber">"(Aucun numéro de téléphone)"</string> @@ -161,14 +162,10 @@ <string name="permdesc_changeConfiguration">"Permet à une application de modifier la configuration actuelle (par ex. : la taille de la police générale ou des paramètres régionaux)."</string> <string name="permlab_restartPackages">"Démarrage d\'autres applications"</string> <string name="permdesc_restartPackages">"Permet à une application de forcer le lancement d\'autres applications."</string> - <string name="permlab_setProcessForeground">"Non-possibilité d\'interruption"</string> - <string name="permdesc_setProcessForeground">"Permet à une application d\'exécuter tout processus au premier plan afin qu\'il ne puisse pas être interrompu. Les applications normales ne devraient jamais nécessiter cette fonctionnalité."</string> <string name="permlab_forceBack">"Fermeture forcée de l\'application"</string> <string name="permdesc_forceBack">"Permet à une application de forcer une autre application exécutée au premier plan à se fermer et à passer en arrière-plan. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_dump">"Vérification de l\'état interne du système"</string> <string name="permdesc_dump">"Permet à l\'application de récupérer l\'état interne du système. Des applications malveillantes peuvent obtenir de nombreuses informations personnelles et sécurisées auxquelles elles ne devraient pas avoir accès."</string> - <string name="permlab_addSystemService">"Éditer des services à faible niveau"</string> - <string name="permdesc_addSystemService">"Permet à l\'application de publier ses propres services de système de niveau inférieur. Des applications malveillantes peuvent prendre le contrôle du système et subtiliser ou endommager ses données."</string> <string name="permlab_runSetActivityWatcher">"Contrôle du lancement des applications"</string> <string name="permdesc_runSetActivityWatcher">"Permet à une application de suivre et de contrôler la façon dont le système lance des activités. Des applications malveillantes peuvent entièrement déstabiliser le système. Cette autorisation est uniquement nécessaire au développement et non pour l\'utilisation normale du téléphone."</string> <string name="permlab_broadcastPackageRemoved">"Envoyer une diffusion sans paquet"</string> @@ -181,8 +178,6 @@ <string name="permdesc_setProcessLimit">"Permet à une application de contrôler le nombre de processus maximal exécutés en même temps. Les applications normales n\'ont jamais recours à cette fonctionnalité."</string> <string name="permlab_setAlwaysFinish">"Fermeture de toutes les applications en tâche de fond"</string> <string name="permdesc_setAlwaysFinish">"Permet à une application de vérifier si des activités sont systématiquement interrompues lorsqu\'elles sont placées en tâche de fond. Cette fonctionnalité n\'est jamais utilisée par les applications normales."</string> - <string name="permlab_fotaUpdate">"Installation des mises à jour du système"</string> - <string name="permdesc_fotaUpdate">"Permet à une application de recevoir des notifications sur des mises à jour système en cours et de lancer leur installation. Des applications malveillantes peuvent utiliser cette fonctionnalité pour endommager le système avec des mises à jour non autorisées ou interférer avec le processus de mise à jour."</string> <string name="permlab_batteryStats">"Modification des statistiques de la batterie"</string> <string name="permdesc_batteryStats">"Autoriser la modification des statistiques de la batterie. Les applications normales n\'utilisent pas cette fonctionnalité."</string> <string name="permlab_internalSystemWindow">"Affichage de fenêtres non autorisées"</string> @@ -418,9 +413,6 @@ <string name="lockscreen_glogin_password_hint">"Mot de passe"</string> <string name="lockscreen_glogin_submit_button">"Se connecter"</string> <string name="lockscreen_glogin_invalid_input">"Nom d\'utilisateur ou mot de passe incorrect."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Effacer les notifications"</string> @@ -452,9 +444,6 @@ <string name="menu_enter_shortcut_label">"entrée"</string> <string name="menu_delete_shortcut_label">"supprimer"</string> <string name="search_go">"Rechercher"</string> - <string name="today">"Aujourd\'hui"</string> - <string name="yesterday">"Hier"</string> - <string name="tomorrow">"Demain"</string> <string name="oneMonthDurationPast">"Il y a 1 mois"</string> <string name="beforeOneMonthDurationPast">"Il y a plus d\'un mois"</string> <plurals name="num_seconds_ago"> @@ -536,13 +525,6 @@ <string name="weeks">"semaines"</string> <string name="year">"année"</string> <string name="years">"années"</string> - <string name="sunday">"dimanche"</string> - <string name="monday">"lundi"</string> - <string name="tuesday">"mardi"</string> - <string name="wednesday">"mercredi"</string> - <string name="thursday">"jeudi"</string> - <string name="friday">"vendredi"</string> - <string name="saturday">"samedi"</string> <string name="every_weekday">"Tous les jours ouvrés (lun.- ven.)"</string> <string name="daily">"Tous les jours"</string> <string name="weekly">"Toutes les semaines le <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +534,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Désolé, cette vidéo ne peut être lue sur cet appareil."</string> <string name="VideoView_error_text_unknown">"Désolé, impossible de lire cette vidéo."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"midi"</string> <string name="Noon">"Midi"</string> <string name="midnight">"minuit"</string> <string name="Midnight">"Minuit"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"dimanche"</string> - <string name="day_of_week_long_monday">"lundi"</string> - <string name="day_of_week_long_tuesday">"mardi"</string> - <string name="day_of_week_long_wednesday">"mercredi"</string> - <string name="day_of_week_long_thursday">"jeudi"</string> - <string name="day_of_week_long_friday">"vendredi"</string> - <string name="day_of_week_long_saturday">"samedi"</string> - <string name="day_of_week_medium_sunday">"dim."</string> - <string name="day_of_week_medium_monday">"Lun"</string> - <string name="day_of_week_medium_tuesday">"Mar"</string> - <string name="day_of_week_medium_wednesday">"Mer"</string> - <string name="day_of_week_medium_thursday">"Jeu"</string> - <string name="day_of_week_medium_friday">"Ven"</string> - <string name="day_of_week_medium_saturday">"Sam"</string> - <string name="day_of_week_short_sunday">"Dim"</string> - <string name="day_of_week_short_monday">"Lun"</string> - <string name="day_of_week_short_tuesday">"Mar"</string> - <string name="day_of_week_short_wednesday">"Mer"</string> - <string name="day_of_week_short_thursday">"Jeu"</string> - <string name="day_of_week_short_friday">"Ven"</string> - <string name="day_of_week_short_saturday">"Sam"</string> - <string name="day_of_week_shorter_sunday">"Dim"</string> - <string name="day_of_week_shorter_monday">"Lun"</string> - <string name="day_of_week_shorter_tuesday">"Mar"</string> - <string name="day_of_week_shorter_wednesday">"Mer"</string> - <string name="day_of_week_shorter_thursday">"Jeu"</string> - <string name="day_of_week_shorter_friday">"Ven"</string> - <string name="day_of_week_shorter_saturday">"sam."</string> - <string name="day_of_week_shortest_sunday">"Dim"</string> - <string name="day_of_week_shortest_monday">"Lun"</string> - <string name="day_of_week_shortest_tuesday">"Mar"</string> - <string name="day_of_week_shortest_wednesday">"Mer"</string> - <string name="day_of_week_shortest_thursday">"Jeu"</string> - <string name="day_of_week_shortest_friday">"Ven"</string> - <string name="day_of_week_shortest_saturday">"Sam"</string> - <string name="month_long_january">"janvier"</string> - <string name="month_long_february">"février"</string> - <string name="month_long_march">"mars"</string> - <string name="month_long_april">"avril"</string> - <string name="month_long_may">"mai"</string> - <string name="month_long_june">"juin"</string> - <string name="month_long_july">"juillet"</string> - <string name="month_long_august">"août"</string> - <string name="month_long_september">"septembre"</string> - <string name="month_long_october">"octobre"</string> - <string name="month_long_november">"novembre"</string> - <string name="month_long_december">"décembre"</string> - <string name="month_medium_january">"janv."</string> - <string name="month_medium_february">"févr."</string> - <string name="month_medium_march">"mars"</string> - <string name="month_medium_april">"avr."</string> - <string name="month_medium_may">"mai"</string> - <string name="month_medium_june">"juin"</string> - <string name="month_medium_july">"juil."</string> - <string name="month_medium_august">"août"</string> - <string name="month_medium_september">"sept."</string> - <string name="month_medium_october">"oct."</string> - <string name="month_medium_november">"nov."</string> - <string name="month_medium_december">"déc."</string> - <string name="month_shortest_january">"jan."</string> - <string name="month_shortest_february">"Ven"</string> - <string name="month_shortest_march">"mars"</string> - <string name="month_shortest_april">"avr."</string> - <string name="month_shortest_may">"mai"</string> - <string name="month_shortest_june">"juin"</string> - <string name="month_shortest_july">"juil."</string> - <string name="month_shortest_august">"août"</string> - <string name="month_shortest_september">"sept."</string> - <string name="month_shortest_october">"oct."</string> - <string name="month_shortest_november">"nov."</string> - <string name="month_shortest_december">"déc."</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Tout sélectionner"</string> diff --git a/core/res/res/values-he-rIL/donottranslate-cldr.xml b/core/res/res/values-he-rIL/donottranslate-cldr.xml new file mode 100644 index 0000000..e3feb1e --- /dev/null +++ b/core/res/res/values-he-rIL/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">ינואר</string> + <string name="month_long_standalone_february">פברואר</string> + <string name="month_long_standalone_march">מרס</string> + <string name="month_long_standalone_april">אפריל</string> + <string name="month_long_standalone_may">מאי</string> + <string name="month_long_standalone_june">יוני</string> + <string name="month_long_standalone_july">יולי</string> + <string name="month_long_standalone_august">אוגוסט</string> + <string name="month_long_standalone_september">ספטמבר</string> + <string name="month_long_standalone_october">אוקטובר</string> + <string name="month_long_standalone_november">נובמבר</string> + <string name="month_long_standalone_december">דצמבר</string> + + <string name="month_long_january">ינואר</string> + <string name="month_long_february">פברואר</string> + <string name="month_long_march">מרס</string> + <string name="month_long_april">אפריל</string> + <string name="month_long_may">מאי</string> + <string name="month_long_june">יוני</string> + <string name="month_long_july">יולי</string> + <string name="month_long_august">אוגוסט</string> + <string name="month_long_september">ספטמבר</string> + <string name="month_long_october">אוקטובר</string> + <string name="month_long_november">נובמבר</string> + <string name="month_long_december">דצמבר</string> + + <string name="month_medium_january">ינו</string> + <string name="month_medium_february">פבר</string> + <string name="month_medium_march">מרס</string> + <string name="month_medium_april">אפר</string> + <string name="month_medium_may">מאי</string> + <string name="month_medium_june">יונ</string> + <string name="month_medium_july">יול</string> + <string name="month_medium_august">אוג</string> + <string name="month_medium_september">ספט</string> + <string name="month_medium_october">אוק</string> + <string name="month_medium_november">נוב</string> + <string name="month_medium_december">דצמ</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">יום ראשון</string> + <string name="day_of_week_long_monday">יום שני</string> + <string name="day_of_week_long_tuesday">יום שלישי</string> + <string name="day_of_week_long_wednesday">יום רביעי</string> + <string name="day_of_week_long_thursday">יום חמישי</string> + <string name="day_of_week_long_friday">יום שישי</string> + <string name="day_of_week_long_saturday">יום שבת</string> + + <string name="day_of_week_medium_sunday">יום א'</string> + <string name="day_of_week_medium_monday">יום ב'</string> + <string name="day_of_week_medium_tuesday">יום ג'</string> + <string name="day_of_week_medium_wednesday">יום ד'</string> + <string name="day_of_week_medium_thursday">יום ה'</string> + <string name="day_of_week_medium_friday">יום ו'</string> + <string name="day_of_week_medium_saturday">שבת</string> + + <string name="day_of_week_short_sunday">יום א'</string> + <string name="day_of_week_short_monday">יום ב'</string> + <string name="day_of_week_short_tuesday">יום ג'</string> + <string name="day_of_week_short_wednesday">יום ד'</string> + <string name="day_of_week_short_thursday">יום ה'</string> + <string name="day_of_week_short_friday">יום ו'</string> + <string name="day_of_week_short_saturday">שבת</string> + + <string name="day_of_week_shortest_sunday">א</string> + <string name="day_of_week_shortest_monday">ב</string> + <string name="day_of_week_shortest_tuesday">ג</string> + <string name="day_of_week_shortest_wednesday">ד</string> + <string name="day_of_week_shortest_thursday">ה</string> + <string name="day_of_week_shortest_friday">ו</string> + <string name="day_of_week_shortest_saturday">ש</string> + + <string name="am">לפנה"צ</string> + <string name="pm">אחה"צ</string> + <string name="yesterday">אתמול</string> + <string name="today">היום</string> + <string name="tomorrow">מחר</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e ב%B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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> + <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, %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_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="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">%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_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_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_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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml new file mode 100644 index 0000000..2a19da4 --- /dev/null +++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">जनवरी</string> + <string name="month_long_standalone_february">फरवरी</string> + <string name="month_long_standalone_march">मार्च</string> + <string name="month_long_standalone_april">अप्रैल</string> + <string name="month_long_standalone_may">मई</string> + <string name="month_long_standalone_june">जून</string> + <string name="month_long_standalone_july">जुलाई</string> + <string name="month_long_standalone_august">अगस्त</string> + <string name="month_long_standalone_september">सितम्बर</string> + <string name="month_long_standalone_october">अक्तूबर</string> + <string name="month_long_standalone_november">नवम्बर</string> + <string name="month_long_standalone_december">दिसम्बर</string> + + <string name="month_long_january">जनवरी</string> + <string name="month_long_february">फरवरी</string> + <string name="month_long_march">मार्च</string> + <string name="month_long_april">अप्रैल</string> + <string name="month_long_may">मई</string> + <string name="month_long_june">जून</string> + <string name="month_long_july">जुलाई</string> + <string name="month_long_august">अगस्त</string> + <string name="month_long_september">सितम्बर</string> + <string name="month_long_october">अक्तूबर</string> + <string name="month_long_november">नवम्बर</string> + <string name="month_long_december">दिसम्बर</string> + + <string name="month_medium_january">जनवरी</string> + <string name="month_medium_february">फरवरी</string> + <string name="month_medium_march">मार्च</string> + <string name="month_medium_april">अप्रैल</string> + <string name="month_medium_may">मई</string> + <string name="month_medium_june">जून</string> + <string name="month_medium_july">जुलाई</string> + <string name="month_medium_august">अगस्त</string> + <string name="month_medium_september">सितम्बर</string> + <string name="month_medium_october">अक्तूबर</string> + <string name="month_medium_november">नवम्बर</string> + <string name="month_medium_december">दिसम्बर</string> + + <string name="month_shortest_january">ज</string> + <string name="month_shortest_february">फ़</string> + <string name="month_shortest_march">मा</string> + <string name="month_shortest_april">अ</string> + <string name="month_shortest_may">म</string> + <string name="month_shortest_june">जू</string> + <string name="month_shortest_july">जु</string> + <string name="month_shortest_august">अ</string> + <string name="month_shortest_september">सि</string> + <string name="month_shortest_october">अ</string> + <string name="month_shortest_november">न</string> + <string name="month_shortest_december">दि</string> + + <string name="day_of_week_long_sunday">रविवार</string> + <string name="day_of_week_long_monday">सोमवार</string> + <string name="day_of_week_long_tuesday">मंगलवार</string> + <string name="day_of_week_long_wednesday">बुधवार</string> + <string name="day_of_week_long_thursday">गुरुवार</string> + <string name="day_of_week_long_friday">शुक्रवार</string> + <string name="day_of_week_long_saturday">शनिवार</string> + + <string name="day_of_week_medium_sunday">रवि</string> + <string name="day_of_week_medium_monday">सोम</string> + <string name="day_of_week_medium_tuesday">मंगल</string> + <string name="day_of_week_medium_wednesday">बुध</string> + <string name="day_of_week_medium_thursday">गुरु</string> + <string name="day_of_week_medium_friday">शुक्र</string> + <string name="day_of_week_medium_saturday">शनि</string> + + <string name="day_of_week_short_sunday">रवि</string> + <string name="day_of_week_short_monday">सोम</string> + <string name="day_of_week_short_tuesday">मंगल</string> + <string name="day_of_week_short_wednesday">बुध</string> + <string name="day_of_week_short_thursday">गुरु</string> + <string name="day_of_week_short_friday">शुक्र</string> + <string name="day_of_week_short_saturday">शनि</string> + + <string name="day_of_week_shortest_sunday">र</string> + <string name="day_of_week_shortest_monday">सो</string> + <string name="day_of_week_shortest_tuesday">मं</string> + <string name="day_of_week_shortest_wednesday">बु</string> + <string name="day_of_week_shortest_thursday">गु</string> + <string name="day_of_week_shortest_friday">शु</string> + <string name="day_of_week_shortest_saturday">श</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e-%-m-%Y</string> + <string name="numeric_date_format">d-M-yyyy</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%-l:%M:%S %p %d-%m-%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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">%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">%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">%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 %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="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">%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_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_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, %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">%2$s-%3$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">%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">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml new file mode 100644 index 0000000..08a70b8 --- /dev/null +++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">január</string> + <string name="month_long_standalone_february">február</string> + <string name="month_long_standalone_march">március</string> + <string name="month_long_standalone_april">április</string> + <string name="month_long_standalone_may">május</string> + <string name="month_long_standalone_june">június</string> + <string name="month_long_standalone_july">július</string> + <string name="month_long_standalone_august">augusztus</string> + <string name="month_long_standalone_september">szeptember</string> + <string name="month_long_standalone_october">október</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">január</string> + <string name="month_long_february">február</string> + <string name="month_long_march">március</string> + <string name="month_long_april">április</string> + <string name="month_long_may">május</string> + <string name="month_long_june">június</string> + <string name="month_long_july">július</string> + <string name="month_long_august">augusztus</string> + <string name="month_long_september">szeptember</string> + <string name="month_long_october">október</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">márc.</string> + <string name="month_medium_april">ápr.</string> + <string name="month_medium_may">máj.</string> + <string name="month_medium_june">jún.</string> + <string name="month_medium_july">júl.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">szept.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">Á</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">vasárnap</string> + <string name="day_of_week_long_monday">hétfő</string> + <string name="day_of_week_long_tuesday">kedd</string> + <string name="day_of_week_long_wednesday">szerda</string> + <string name="day_of_week_long_thursday">csütörtök</string> + <string name="day_of_week_long_friday">péntek</string> + <string name="day_of_week_long_saturday">szombat</string> + + <string name="day_of_week_medium_sunday">V</string> + <string name="day_of_week_medium_monday">H</string> + <string name="day_of_week_medium_tuesday">K</string> + <string name="day_of_week_medium_wednesday">Sze</string> + <string name="day_of_week_medium_thursday">Cs</string> + <string name="day_of_week_medium_friday">P</string> + <string name="day_of_week_medium_saturday">Szo</string> + + <string name="day_of_week_short_sunday">V</string> + <string name="day_of_week_short_monday">H</string> + <string name="day_of_week_short_tuesday">K</string> + <string name="day_of_week_short_wednesday">Sze</string> + <string name="day_of_week_short_thursday">Cs</string> + <string name="day_of_week_short_friday">P</string> + <string name="day_of_week_short_saturday">Szo</string> + + <string name="day_of_week_shortest_sunday">V</string> + <string name="day_of_week_shortest_monday">H</string> + <string name="day_of_week_shortest_tuesday">K</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">de.</string> + <string name="pm">du.</string> + <string name="yesterday">tegnap</string> + <string name="today">ma</string> + <string name="tomorrow">holnap</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%Y.%m.%d.</string> + <string name="numeric_date_format">yyyy.MM.dd.</string> + <string name="numeric_date_template">"%s.%s.%s."</string> + <string name="month_day_year">%Y. %B %-e.</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %Y.%m.%d.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y.%m.%d.</string> + <string name="month_day">%B %-e.</string> + <string name="month">%-B</string> + <string name="month_year">%Y. %B</string> + <string name="abbrev_month_day">%b %-e.</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y. %b</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml new file mode 100644 index 0000000..6adec84 --- /dev/null +++ b/core/res/res/values-id-rID/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Januari</string> + <string name="month_long_standalone_february">Februari</string> + <string name="month_long_standalone_march">Maret</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">Mei</string> + <string name="month_long_standalone_june">Juni</string> + <string name="month_long_standalone_july">Juli</string> + <string name="month_long_standalone_august">Agustus</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">Oktober</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">Desember</string> + + <string name="month_long_january">Januari</string> + <string name="month_long_february">Februari</string> + <string name="month_long_march">Maret</string> + <string name="month_long_april">April</string> + <string name="month_long_may">Mei</string> + <string name="month_long_june">Juni</string> + <string name="month_long_july">Juli</string> + <string name="month_long_august">Agustus</string> + <string name="month_long_september">September</string> + <string name="month_long_october">Oktober</string> + <string name="month_long_november">November</string> + <string name="month_long_december">Desember</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">Mei</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Agu</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Okt</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Des</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">Minggu</string> + <string name="day_of_week_long_monday">Senin</string> + <string name="day_of_week_long_tuesday">Selasa</string> + <string name="day_of_week_long_wednesday">Rabu</string> + <string name="day_of_week_long_thursday">Kamis</string> + <string name="day_of_week_long_friday">Jumat</string> + <string name="day_of_week_long_saturday">Sabtu</string> + + <string name="day_of_week_medium_sunday">Min</string> + <string name="day_of_week_medium_monday">Sen</string> + <string name="day_of_week_medium_tuesday">Sel</string> + <string name="day_of_week_medium_wednesday">Rab</string> + <string name="day_of_week_medium_thursday">Kam</string> + <string name="day_of_week_medium_friday">Jum</string> + <string name="day_of_week_medium_saturday">Sab</string> + + <string name="day_of_week_short_sunday">Min</string> + <string name="day_of_week_short_monday">Sen</string> + <string name="day_of_week_short_tuesday">Sel</string> + <string name="day_of_week_short_wednesday">Rab</string> + <string name="day_of_week_short_thursday">Kam</string> + <string name="day_of_week_short_friday">Jum</string> + <string name="day_of_week_short_saturday">Sab</string> + + <string name="day_of_week_shortest_sunday">1</string> + <string name="day_of_week_shortest_monday">2</string> + <string name="day_of_week_shortest_tuesday">3</string> + <string name="day_of_week_shortest_wednesday">4</string> + <string name="day_of_week_shortest_thursday">5</string> + <string name="day_of_week_shortest_friday">6</string> + <string name="day_of_week_shortest_saturday">7</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%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> + <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">%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">%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_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="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">%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_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_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_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_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">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-it-rCH/donottranslate-cldr.xml b/core/res/res/values-it-rCH/donottranslate-cldr.xml new file mode 100644 index 0000000..12170d6 --- /dev/null +++ b/core/res/res/values-it-rCH/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Gennaio</string> + <string name="month_long_standalone_february">Febbraio</string> + <string name="month_long_standalone_march">Marzo</string> + <string name="month_long_standalone_april">Aprile</string> + <string name="month_long_standalone_may">Maggio</string> + <string name="month_long_standalone_june">Giugno</string> + <string name="month_long_standalone_july">Luglio</string> + <string name="month_long_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> + <string name="month_long_march">marzo</string> + <string name="month_long_april">aprile</string> + <string name="month_long_may">maggio</string> + <string name="month_long_june">giugno</string> + <string name="month_long_july">luglio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">settembre</string> + <string name="month_long_october">ottobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">dicembre</string> + + <string name="month_medium_january">gen</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">mag</string> + <string name="month_medium_june">giu</string> + <string name="month_medium_july">lug</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">set</string> + <string name="month_medium_october">ott</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">G</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">G</string> + <string name="month_shortest_july">L</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domenica</string> + <string name="day_of_week_long_monday">lunedì</string> + <string name="day_of_week_long_tuesday">martedì</string> + <string name="day_of_week_long_wednesday">mercoledì</string> + <string name="day_of_week_long_thursday">giovedì</string> + <string name="day_of_week_long_friday">venerdì</string> + <string name="day_of_week_long_saturday">sabato</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mer</string> + <string name="day_of_week_medium_thursday">gio</string> + <string name="day_of_week_medium_friday">ven</string> + <string name="day_of_week_medium_saturday">sab</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mer</string> + <string name="day_of_week_short_thursday">gio</string> + <string name="day_of_week_short_friday">ven</string> + <string name="day_of_week_short_saturday">sab</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">G</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">m.</string> + <string name="pm">p.</string> + <string name="yesterday">ieri</string> + <string name="today">oggi</string> + <string name="tomorrow">domani</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %-e-%b-%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e-%b-%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-it-rIT/donottranslate-cldr.xml b/core/res/res/values-it-rIT/donottranslate-cldr.xml new file mode 100644 index 0000000..2178bbe --- /dev/null +++ b/core/res/res/values-it-rIT/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Gennaio</string> + <string name="month_long_standalone_february">Febbraio</string> + <string name="month_long_standalone_march">Marzo</string> + <string name="month_long_standalone_april">Aprile</string> + <string name="month_long_standalone_may">Maggio</string> + <string name="month_long_standalone_june">Giugno</string> + <string name="month_long_standalone_july">Luglio</string> + <string name="month_long_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> + <string name="month_long_march">marzo</string> + <string name="month_long_april">aprile</string> + <string name="month_long_may">maggio</string> + <string name="month_long_june">giugno</string> + <string name="month_long_july">luglio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">settembre</string> + <string name="month_long_october">ottobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">dicembre</string> + + <string name="month_medium_january">gen</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">mag</string> + <string name="month_medium_june">giu</string> + <string name="month_medium_july">lug</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">set</string> + <string name="month_medium_october">ott</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">G</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">G</string> + <string name="month_shortest_july">L</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domenica</string> + <string name="day_of_week_long_monday">lunedì</string> + <string name="day_of_week_long_tuesday">martedì</string> + <string name="day_of_week_long_wednesday">mercoledì</string> + <string name="day_of_week_long_thursday">giovedì</string> + <string name="day_of_week_long_friday">venerdì</string> + <string name="day_of_week_long_saturday">sabato</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mer</string> + <string name="day_of_week_medium_thursday">gio</string> + <string name="day_of_week_medium_friday">ven</string> + <string name="day_of_week_medium_saturday">sab</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mer</string> + <string name="day_of_week_short_thursday">gio</string> + <string name="day_of_week_short_friday">ven</string> + <string name="day_of_week_short_saturday">sab</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">G</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">m.</string> + <string name="pm">p.</string> + <string name="yesterday">ieri</string> + <string name="today">oggi</string> + <string name="tomorrow">domani</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d/%b/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%b/%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml new file mode 100644 index 0000000..2178bbe --- /dev/null +++ b/core/res/res/values-it/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Gennaio</string> + <string name="month_long_standalone_february">Febbraio</string> + <string name="month_long_standalone_march">Marzo</string> + <string name="month_long_standalone_april">Aprile</string> + <string name="month_long_standalone_may">Maggio</string> + <string name="month_long_standalone_june">Giugno</string> + <string name="month_long_standalone_july">Luglio</string> + <string name="month_long_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> + <string name="month_long_march">marzo</string> + <string name="month_long_april">aprile</string> + <string name="month_long_may">maggio</string> + <string name="month_long_june">giugno</string> + <string name="month_long_july">luglio</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">settembre</string> + <string name="month_long_october">ottobre</string> + <string name="month_long_november">novembre</string> + <string name="month_long_december">dicembre</string> + + <string name="month_medium_january">gen</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">mag</string> + <string name="month_medium_june">giu</string> + <string name="month_medium_july">lug</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">set</string> + <string name="month_medium_october">ott</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dic</string> + + <string name="month_shortest_january">G</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">G</string> + <string name="month_shortest_july">L</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domenica</string> + <string name="day_of_week_long_monday">lunedì</string> + <string name="day_of_week_long_tuesday">martedì</string> + <string name="day_of_week_long_wednesday">mercoledì</string> + <string name="day_of_week_long_thursday">giovedì</string> + <string name="day_of_week_long_friday">venerdì</string> + <string name="day_of_week_long_saturday">sabato</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">lun</string> + <string name="day_of_week_medium_tuesday">mar</string> + <string name="day_of_week_medium_wednesday">mer</string> + <string name="day_of_week_medium_thursday">gio</string> + <string name="day_of_week_medium_friday">ven</string> + <string name="day_of_week_medium_saturday">sab</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">lun</string> + <string name="day_of_week_short_tuesday">mar</string> + <string name="day_of_week_short_wednesday">mer</string> + <string name="day_of_week_short_thursday">gio</string> + <string name="day_of_week_short_friday">ven</string> + <string name="day_of_week_short_saturday">sab</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">G</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">m.</string> + <string name="pm">p.</string> + <string name="yesterday">ieri</string> + <string name="today">oggi</string> + <string name="tomorrow">domani</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d/%b/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%b/%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index f80a4f4..5bfbc49 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Consente a un\'applicazione di modificare la configurazione corrente, come le dimensioni dei caratteri locali o complessive."</string> <string name="permlab_restartPackages">"riavvio altre applicazioni"</string> <string name="permdesc_restartPackages">"Consente a un\'applicazione di riavviare forzatamente altre applicazioni."</string> - <string name="permlab_setProcessForeground">"impedire l\'interruzione"</string> - <string name="permdesc_setProcessForeground">"Consente a un\'applicazione di eseguire i processi in primo piano in modo che non possano essere interrotti. Non dovrebbe essere mai necessario per le normali applicazioni."</string> <string name="permlab_forceBack">"chiusura forzata dell\'applicazione"</string> <string name="permdesc_forceBack">"Consente a un\'applicazione di forzare la chiusura di attività in primo piano. Non dovrebbe essere mai necessario per le normali applicazioni."</string> <string name="permlab_dump">"recupero stato interno del sistema"</string> <string name="permdesc_dump">"Consente all\'applicazione di recuperare lo stato interno del sistema. Le applicazioni dannose potrebbero recuperare molte informazioni riservate e protette di cui non dovrebbero avere mai bisogno."</string> - <string name="permlab_addSystemService">"pubblicaz. servizi di basso livello"</string> - <string name="permdesc_addSystemService">"Consente a un\'applicazione di pubblicare i suoi servizi di sistema di basso livello. Le applicazioni dannose potrebbero assumere il controllo del sistema e impossessarsi di dati o danneggiarli."</string> <string name="permlab_runSetActivityWatcher">"monitoraggio e controllo avvio applicazioni"</string> <string name="permdesc_runSetActivityWatcher">"Consente a un\'applicazione di monitorare e controllare la modalità di avvio delle attività nel sistema. Le applicazioni dannose potrebbero compromettere totalmente il sistema. Questa autorizzazione è necessaria soltanto per lo sviluppo, mai per il normale utilizzo del telefono."</string> <string name="permlab_broadcastPackageRemoved">"invio broadcast rimossi dal pacchetto"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Consente a un\'applicazione di stabilire il numero massimo di processi in esecuzione. Mai necessario per le normali applicazioni."</string> <string name="permlab_setAlwaysFinish">"chiusura applicazioni in background"</string> <string name="permdesc_setAlwaysFinish">"Consente a un\'applicazione di controllare se le attività sono sempre completate quando vengono messe in secondo piano. Mai necessario per le normali applicazioni."</string> - <string name="permlab_fotaUpdate">"installazione autom. aggiornamenti di sistema"</string> - <string name="permdesc_fotaUpdate">"Consente a un\'applicazione di ricevere notifiche sugli aggiornamenti del sistema in sospeso e di attivarne l\'installazione. Le applicazioni dannose possono sfruttare questa possibilità per danneggiare il sistema con aggiornamenti non autorizzati, o interferire con il processo di aggiornamento."</string> <string name="permlab_batteryStats">"modifica statistiche batteria"</string> <string name="permdesc_batteryStats">"Consente la modifica delle statistiche sulla batteria raccolte. Da non usare per normali applicazioni."</string> <string name="permlab_internalSystemWindow">"visualizzazione finestre non autorizzate"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Accedi"</string> <string name="lockscreen_glogin_invalid_input">"Password o nome utente non valido."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Cancella notifiche"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"Invio"</string> <string name="menu_delete_shortcut_label">"Canc"</string> <string name="search_go">"Cerca"</string> - <string name="today">"Oggi"</string> - <string name="yesterday">"Ieri"</string> - <string name="tomorrow">"Domani"</string> <string name="oneMonthDurationPast">"1 mese fa"</string> <string name="beforeOneMonthDurationPast">"Oltre 1 mese fa"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"settimane"</string> <string name="year">"anno"</string> <string name="years">"anni"</string> - <string name="sunday">"Domenica"</string> - <string name="monday">"Lunedì"</string> - <string name="tuesday">"Martedì"</string> - <string name="wednesday">"Mercoledì"</string> - <string name="thursday">"Giovedì"</string> - <string name="friday">"Venerdì"</string> - <string name="saturday">"Sabato"</string> <string name="every_weekday">"Ogni giorno feriale (lun-ven)"</string> <string name="daily">"Quotidianamente"</string> <string name="weekly">"Ogni settimana il <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Spiacenti, questo video non è valido per lo streaming su questo dispositivo."</string> <string name="VideoView_error_text_unknown">"Spiacenti. Impossibile riprodurre il video."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mezzogiorno"</string> <string name="Noon">"Mezzogiorno"</string> <string name="midnight">"mezzanotte"</string> <string name="Midnight">"Mezzanotte"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"Domenica"</string> - <string name="day_of_week_long_monday">"Lunedì"</string> - <string name="day_of_week_long_tuesday">"Martedì"</string> - <string name="day_of_week_long_wednesday">"Mercoledì"</string> - <string name="day_of_week_long_thursday">"Giovedì"</string> - <string name="day_of_week_long_friday">"Venerdì"</string> - <string name="day_of_week_long_saturday">"Sabato"</string> - <string name="day_of_week_medium_sunday">"Dom"</string> - <string name="day_of_week_medium_monday">"Lun"</string> - <string name="day_of_week_medium_tuesday">"Mar"</string> - <string name="day_of_week_medium_wednesday">"Mer"</string> - <string name="day_of_week_medium_thursday">"Gio"</string> - <string name="day_of_week_medium_friday">"Ven"</string> - <string name="day_of_week_medium_saturday">"Sab"</string> - <string name="day_of_week_short_sunday">"Do"</string> - <string name="day_of_week_short_monday">"Lu"</string> - <string name="day_of_week_short_tuesday">"Ma"</string> - <string name="day_of_week_short_wednesday">"Me"</string> - <string name="day_of_week_short_thursday">"Gi"</string> - <string name="day_of_week_short_friday">"Ve"</string> - <string name="day_of_week_short_saturday">"Sa"</string> - <string name="day_of_week_shorter_sunday">"Do"</string> - <string name="day_of_week_shorter_monday">"Lu"</string> - <string name="day_of_week_shorter_tuesday">"Ma"</string> - <string name="day_of_week_shorter_wednesday">"Me"</string> - <string name="day_of_week_shorter_thursday">"Gi"</string> - <string name="day_of_week_shorter_friday">"V"</string> - <string name="day_of_week_shorter_saturday">"Sa"</string> - <string name="day_of_week_shortest_sunday">"D"</string> - <string name="day_of_week_shortest_monday">"Lun"</string> - <string name="day_of_week_shortest_tuesday">"M"</string> - <string name="day_of_week_shortest_wednesday">"Me"</string> - <string name="day_of_week_shortest_thursday">"G"</string> - <string name="day_of_week_shortest_friday">"V"</string> - <string name="day_of_week_shortest_saturday">"Sa"</string> - <string name="month_long_january">"Gennaio"</string> - <string name="month_long_february">"Febbraio"</string> - <string name="month_long_march">"Marzo"</string> - <string name="month_long_april">"Aprile"</string> - <string name="month_long_may">"Maggio"</string> - <string name="month_long_june">"Giugno"</string> - <string name="month_long_july">"Luglio"</string> - <string name="month_long_august">"Agosto"</string> - <string name="month_long_september">"Settembre"</string> - <string name="month_long_october">"Ottobre"</string> - <string name="month_long_november">"Novembre"</string> - <string name="month_long_december">"Dicembre"</string> - <string name="month_medium_january">"Gen"</string> - <string name="month_medium_february">"Feb"</string> - <string name="month_medium_march">"Mar"</string> - <string name="month_medium_april">"Apr"</string> - <string name="month_medium_may">"Mag"</string> - <string name="month_medium_june">"Giu"</string> - <string name="month_medium_july">"Lug"</string> - <string name="month_medium_august">"Ago"</string> - <string name="month_medium_september">"Set"</string> - <string name="month_medium_october">"Ott"</string> - <string name="month_medium_november">"Nov"</string> - <string name="month_medium_december">"Dic"</string> - <string name="month_shortest_january">"G"</string> - <string name="month_shortest_february">"F"</string> - <string name="month_shortest_march">"M"</string> - <string name="month_shortest_april">"Ap"</string> - <string name="month_shortest_may">"Mag"</string> - <string name="month_shortest_june">"Gi"</string> - <string name="month_shortest_july">"Lug"</string> - <string name="month_shortest_august">"Ago"</string> - <string name="month_shortest_september">"Set"</string> - <string name="month_shortest_october">"O"</string> - <string name="month_shortest_november">"N"</string> - <string name="month_shortest_december">"Di"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Seleziona tutto"</string> diff --git a/core/res/res/values-ja-rJP/donottranslate-cldr.xml b/core/res/res/values-ja-rJP/donottranslate-cldr.xml new file mode 100644 index 0000000..d2510f6 --- /dev/null +++ b/core/res/res/values-ja-rJP/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">1月</string> + <string name="month_long_standalone_february">2月</string> + <string name="month_long_standalone_march">3月</string> + <string name="month_long_standalone_april">4月</string> + <string name="month_long_standalone_may">5月</string> + <string name="month_long_standalone_june">6月</string> + <string name="month_long_standalone_july">7月</string> + <string name="month_long_standalone_august">8月</string> + <string name="month_long_standalone_september">9月</string> + <string name="month_long_standalone_october">10月</string> + <string name="month_long_standalone_november">11月</string> + <string name="month_long_standalone_december">12月</string> + + <string name="month_long_january">1月</string> + <string name="month_long_february">2月</string> + <string name="month_long_march">3月</string> + <string name="month_long_april">4月</string> + <string name="month_long_may">5月</string> + <string name="month_long_june">6月</string> + <string name="month_long_july">7月</string> + <string name="month_long_august">8月</string> + <string name="month_long_september">9月</string> + <string name="month_long_october">10月</string> + <string name="month_long_november">11月</string> + <string name="month_long_december">12月</string> + + <string name="month_medium_january">1月</string> + <string name="month_medium_february">2月</string> + <string name="month_medium_march">3月</string> + <string name="month_medium_april">4月</string> + <string name="month_medium_may">5月</string> + <string name="month_medium_june">6月</string> + <string name="month_medium_july">7月</string> + <string name="month_medium_august">8月</string> + <string name="month_medium_september">9月</string> + <string name="month_medium_october">10月</string> + <string name="month_medium_november">11月</string> + <string name="month_medium_december">12月</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">日曜日</string> + <string name="day_of_week_long_monday">月曜日</string> + <string name="day_of_week_long_tuesday">火曜日</string> + <string name="day_of_week_long_wednesday">水曜日</string> + <string name="day_of_week_long_thursday">木曜日</string> + <string name="day_of_week_long_friday">金曜日</string> + <string name="day_of_week_long_saturday">土曜日</string> + + <string name="day_of_week_medium_sunday">日</string> + <string name="day_of_week_medium_monday">月</string> + <string name="day_of_week_medium_tuesday">火</string> + <string name="day_of_week_medium_wednesday">水</string> + <string name="day_of_week_medium_thursday">木</string> + <string name="day_of_week_medium_friday">金</string> + <string name="day_of_week_medium_saturday">土</string> + + <string name="day_of_week_short_sunday">日</string> + <string name="day_of_week_short_monday">月</string> + <string name="day_of_week_short_tuesday">火</string> + <string name="day_of_week_short_wednesday">水</string> + <string name="day_of_week_short_thursday">木</string> + <string name="day_of_week_short_friday">金</string> + <string name="day_of_week_short_saturday">土</string> + + <string name="day_of_week_shortest_sunday">日</string> + <string name="day_of_week_shortest_monday">月</string> + <string name="day_of_week_shortest_tuesday">火</string> + <string name="day_of_week_shortest_wednesday">水</string> + <string name="day_of_week_shortest_thursday">木</string> + <string name="day_of_week_shortest_friday">金</string> + <string name="day_of_week_shortest_saturday">土</string> + + <string name="am">午前</string> + <string name="pm">午後</string> + <string name="yesterday">昨日</string> + <string name="today">今日</string> + <string name="tomorrow">明日</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%p%-l:%M</string> + <string name="hour_minute_cap_ampm">%p%-l:%M</string> + <string name="twelve_hour_time_format">ah:mm</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y/%m/%d</string> + <string name="numeric_date_format">yyyy/MM/dd</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%Y年%-m月%-e日</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y/%m/%d</string> + <string name="month_day">%-m月%-e日</string> + <string name="month">%-B</string> + <string name="month_year">%Y年%-m月</string> + <string name="abbrev_month_day">%-m月%-e日</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y年%-m月</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <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 new file mode 100644 index 0000000..d2510f6 --- /dev/null +++ b/core/res/res/values-ja/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">1月</string> + <string name="month_long_standalone_february">2月</string> + <string name="month_long_standalone_march">3月</string> + <string name="month_long_standalone_april">4月</string> + <string name="month_long_standalone_may">5月</string> + <string name="month_long_standalone_june">6月</string> + <string name="month_long_standalone_july">7月</string> + <string name="month_long_standalone_august">8月</string> + <string name="month_long_standalone_september">9月</string> + <string name="month_long_standalone_october">10月</string> + <string name="month_long_standalone_november">11月</string> + <string name="month_long_standalone_december">12月</string> + + <string name="month_long_january">1月</string> + <string name="month_long_february">2月</string> + <string name="month_long_march">3月</string> + <string name="month_long_april">4月</string> + <string name="month_long_may">5月</string> + <string name="month_long_june">6月</string> + <string name="month_long_july">7月</string> + <string name="month_long_august">8月</string> + <string name="month_long_september">9月</string> + <string name="month_long_october">10月</string> + <string name="month_long_november">11月</string> + <string name="month_long_december">12月</string> + + <string name="month_medium_january">1月</string> + <string name="month_medium_february">2月</string> + <string name="month_medium_march">3月</string> + <string name="month_medium_april">4月</string> + <string name="month_medium_may">5月</string> + <string name="month_medium_june">6月</string> + <string name="month_medium_july">7月</string> + <string name="month_medium_august">8月</string> + <string name="month_medium_september">9月</string> + <string name="month_medium_october">10月</string> + <string name="month_medium_november">11月</string> + <string name="month_medium_december">12月</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">日曜日</string> + <string name="day_of_week_long_monday">月曜日</string> + <string name="day_of_week_long_tuesday">火曜日</string> + <string name="day_of_week_long_wednesday">水曜日</string> + <string name="day_of_week_long_thursday">木曜日</string> + <string name="day_of_week_long_friday">金曜日</string> + <string name="day_of_week_long_saturday">土曜日</string> + + <string name="day_of_week_medium_sunday">日</string> + <string name="day_of_week_medium_monday">月</string> + <string name="day_of_week_medium_tuesday">火</string> + <string name="day_of_week_medium_wednesday">水</string> + <string name="day_of_week_medium_thursday">木</string> + <string name="day_of_week_medium_friday">金</string> + <string name="day_of_week_medium_saturday">土</string> + + <string name="day_of_week_short_sunday">日</string> + <string name="day_of_week_short_monday">月</string> + <string name="day_of_week_short_tuesday">火</string> + <string name="day_of_week_short_wednesday">水</string> + <string name="day_of_week_short_thursday">木</string> + <string name="day_of_week_short_friday">金</string> + <string name="day_of_week_short_saturday">土</string> + + <string name="day_of_week_shortest_sunday">日</string> + <string name="day_of_week_shortest_monday">月</string> + <string name="day_of_week_shortest_tuesday">火</string> + <string name="day_of_week_shortest_wednesday">水</string> + <string name="day_of_week_shortest_thursday">木</string> + <string name="day_of_week_shortest_friday">金</string> + <string name="day_of_week_shortest_saturday">土</string> + + <string name="am">午前</string> + <string name="pm">午後</string> + <string name="yesterday">昨日</string> + <string name="today">今日</string> + <string name="tomorrow">明日</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%p%-l:%M</string> + <string name="hour_minute_cap_ampm">%p%-l:%M</string> + <string name="twelve_hour_time_format">ah:mm</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y/%m/%d</string> + <string name="numeric_date_format">yyyy/MM/dd</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%Y年%-m月%-e日</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %Y/%m/%d</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y/%m/%d</string> + <string name="month_day">%-m月%-e日</string> + <string name="month">%-B</string> + <string name="month_year">%Y年%-m月</string> + <string name="abbrev_month_day">%-m月%-e日</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y年%-m月</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ja/donottranslate.xml b/core/res/res/values-ja/donottranslate.xml new file mode 100644 index 0000000..f7c3566 --- /dev/null +++ b/core/res/res/values-ja/donottranslate.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Default text encoding for WebSettings. --> + <string name="default_text_encoding">Shift_JIS</string> +</resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 8da040e..a2e3e51 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"地域/言語やフォントのサイズなど、現在の設定の変更をアプリケーションに許可します。"</string> <string name="permlab_restartPackages">"他のアプリケーションの再起動"</string> <string name="permdesc_restartPackages">"他のアプリケーションの強制的な再起動をアプリケーションに許可します。"</string> - <string name="permlab_setProcessForeground">"停止の阻止"</string> - <string name="permdesc_setProcessForeground">"フォアグラウンドでプロセスを実行して、強制終了できないようにすることをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string> <string name="permlab_forceBack">"アプリケーションの強制終了"</string> <string name="permdesc_forceBack">"フォアグラウンドで実行されている操作を強制終了して戻ることをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string> <string name="permlab_dump">"システムの内部状態の取得"</string> <string name="permdesc_dump">"システムの内部状態の取得をアプリケーションに許可します。悪意のあるアプリケーションが、通常は必要としない広範囲にわたる非公開の機密情報を取得する恐れがあります。"</string> - <string name="permlab_addSystemService">"低レベルサービスの公開"</string> - <string name="permdesc_addSystemService">"独自の低レベルのシステムサービスを公開することをアプリケーションに許可します。悪意のあるアプリケーションがシステムを乗っ取って、データの盗用や破壊をする恐れがあります。"</string> <string name="permlab_runSetActivityWatcher">"起動中のすべてのアプリケーションの監視と制御"</string> <string name="permdesc_runSetActivityWatcher">"システムが起動する操作の監視と制御をアプリケーションに許可します。悪意のあるアプリケーションがシステムを完全に破壊する恐れがあります。この許可は開発にのみ必要で、携帯電話の通常の使用にはまったく必要ありません。"</string> <string name="permlab_broadcastPackageRemoved">"パッケージ削除ブロードキャストの送信"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"実行するプロセス数の上限の制御をアプリケーションに許可します。通常のアプリケーションにはまったく必要ありません。"</string> <string name="permlab_setAlwaysFinish">"バックグラウンドアプリケーションをすべて終了する"</string> <string name="permdesc_setAlwaysFinish">"バックグラウンドになり次第必ず操作を終了させるかどうかの制御をアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string> - <string name="permlab_fotaUpdate">"システムアップデートの自動インストール"</string> - <string name="permdesc_fotaUpdate">"保留中のシステムアップデートに関する通知の受信とインストールの開始をアプリケーションに許可します。悪意のあるアプリケーションが許可なく更新を行ってシステムを破壊したり、更新処理を妨害する恐れがあります。"</string> <string name="permlab_batteryStats">"電池統計情報の変国"</string> <string name="permdesc_batteryStats">"収集した電池統計情報の変更を許可します。通常のアプリケーションでは使用しません。"</string> <string name="permlab_internalSystemWindow">"未許可のウィンドウの表示"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"パスワード"</string> <string name="lockscreen_glogin_submit_button">"ログイン"</string> <string name="lockscreen_glogin_invalid_input">"ユーザー名またはパスワードが正しくありません。"</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"通知を消去"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"Enter"</string> <string name="menu_delete_shortcut_label">"Del"</string> <string name="search_go">"検索"</string> - <string name="today">"今日"</string> - <string name="yesterday">"昨日"</string> - <string name="tomorrow">"明日"</string> <string name="oneMonthDurationPast">"1か月前"</string> <string name="beforeOneMonthDurationPast">"1か月前"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"週間"</string> <string name="year">"年"</string> <string name="years">"年"</string> - <string name="sunday">"日曜日"</string> - <string name="monday">"月曜日"</string> - <string name="tuesday">"火曜日"</string> - <string name="wednesday">"水曜日"</string> - <string name="thursday">"木曜日"</string> - <string name="friday">"金曜日"</string> - <string name="saturday">"土曜日"</string> <string name="every_weekday">"平日(月~金)"</string> <string name="daily">"毎日"</string> <string name="weekly">"毎週<xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"この動画はご使用の端末でストリーミングできません。"</string> <string name="VideoView_error_text_unknown">"この動画は再生できません。"</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%3$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g><xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g>~<xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> - <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g><xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>'日 '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'年'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'日'"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'年'"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"正午"</string> <string name="Noon">"正午"</string> <string name="midnight">"午前0時"</string> <string name="Midnight">"午前0時"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string> - <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%B</xliff:g>/<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>月<xliff:g id="DAY1">%3$s</xliff:g>日~<xliff:g id="DAY2">%8$s</xliff:g>日"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> - <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g><xliff:g id="TIME1">%5$s</xliff:g>~<xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g><xliff:g id="WEEKDAY2">%6$s</xliff:g><xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>/<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%b</xliff:g>月"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g>/<xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"日曜日"</string> - <string name="day_of_week_long_monday">"月曜日"</string> - <string name="day_of_week_long_tuesday">"火曜日"</string> - <string name="day_of_week_long_wednesday">"水曜日"</string> - <string name="day_of_week_long_thursday">"木曜日"</string> - <string name="day_of_week_long_friday">"金曜日"</string> - <string name="day_of_week_long_saturday">"土曜日"</string> - <string name="day_of_week_medium_sunday">"(日)"</string> - <string name="day_of_week_medium_monday">"(月)"</string> - <string name="day_of_week_medium_tuesday">"(火)"</string> - <string name="day_of_week_medium_wednesday">"(水)"</string> - <string name="day_of_week_medium_thursday">"(木)"</string> - <string name="day_of_week_medium_friday">"(金)"</string> - <string name="day_of_week_medium_saturday">"(土)"</string> - <string name="day_of_week_short_sunday">"日"</string> - <string name="day_of_week_short_monday">"月"</string> - <string name="day_of_week_short_tuesday">"火"</string> - <string name="day_of_week_short_wednesday">"水"</string> - <string name="day_of_week_short_thursday">"木"</string> - <string name="day_of_week_short_friday">"金"</string> - <string name="day_of_week_short_saturday">"土"</string> - <string name="day_of_week_shorter_sunday">"日"</string> - <string name="day_of_week_shorter_monday">"月"</string> - <string name="day_of_week_shorter_tuesday">"火"</string> - <string name="day_of_week_shorter_wednesday">"水"</string> - <string name="day_of_week_shorter_thursday">"木"</string> - <string name="day_of_week_shorter_friday">"金"</string> - <string name="day_of_week_shorter_saturday">"土"</string> - <string name="day_of_week_shortest_sunday">"日"</string> - <string name="day_of_week_shortest_monday">"月"</string> - <string name="day_of_week_shortest_tuesday">"火"</string> - <string name="day_of_week_shortest_wednesday">"水"</string> - <string name="day_of_week_shortest_thursday">"火"</string> - <string name="day_of_week_shortest_friday">"金"</string> - <string name="day_of_week_shortest_saturday">"土"</string> - <string name="month_long_january">"1月"</string> - <string name="month_long_february">"2月"</string> - <string name="month_long_march">"3月"</string> - <string name="month_long_april">"4月"</string> - <string name="month_long_may">"5月"</string> - <string name="month_long_june">"6月"</string> - <string name="month_long_july">"7月"</string> - <string name="month_long_august">"8月"</string> - <string name="month_long_september">"9月"</string> - <string name="month_long_october">"10月"</string> - <string name="month_long_november">"11月"</string> - <string name="month_long_december">"12月"</string> - <string name="month_medium_january">"1"</string> - <string name="month_medium_february">"2"</string> - <string name="month_medium_march">"3"</string> - <string name="month_medium_april">"4"</string> - <string name="month_medium_may">"5"</string> - <string name="month_medium_june">"6"</string> - <string name="month_medium_july">"7"</string> - <string name="month_medium_august">"8"</string> - <string name="month_medium_september">"9"</string> - <string name="month_medium_october">"10"</string> - <string name="month_medium_november">"11"</string> - <string name="month_medium_december">"12"</string> - <string name="month_shortest_january">"1"</string> - <string name="month_shortest_february">"2"</string> - <string name="month_shortest_march">"3"</string> - <string name="month_shortest_april">"4"</string> - <string name="month_shortest_may">"5"</string> - <string name="month_shortest_june">"6"</string> - <string name="month_shortest_july">"7"</string> - <string name="month_shortest_august">"8"</string> - <string name="month_shortest_september">"9"</string> - <string name="month_shortest_october">"10"</string> - <string name="month_shortest_november">"11"</string> - <string name="month_shortest_december">"12"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"すべて選択"</string> diff --git a/core/res/res/values-ko-rKR/donottranslate-cldr.xml b/core/res/res/values-ko-rKR/donottranslate-cldr.xml new file mode 100644 index 0000000..57cd356 --- /dev/null +++ b/core/res/res/values-ko-rKR/donottranslate-cldr.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">1월</string> + <string name="month_long_standalone_february">2월</string> + <string name="month_long_standalone_march">3월</string> + <string name="month_long_standalone_april">4월</string> + <string name="month_long_standalone_may">5월</string> + <string name="month_long_standalone_june">6월</string> + <string name="month_long_standalone_july">7월</string> + <string name="month_long_standalone_august">8월</string> + <string name="month_long_standalone_september">9월</string> + <string name="month_long_standalone_october">10월</string> + <string name="month_long_standalone_november">11월</string> + <string name="month_long_standalone_december">12월</string> + + <string name="month_long_january">1월</string> + <string name="month_long_february">2월</string> + <string name="month_long_march">3월</string> + <string name="month_long_april">4월</string> + <string name="month_long_may">5월</string> + <string name="month_long_june">6월</string> + <string name="month_long_july">7월</string> + <string name="month_long_august">8월</string> + <string name="month_long_september">9월</string> + <string name="month_long_october">10월</string> + <string name="month_long_november">11월</string> + <string name="month_long_december">12월</string> + + + <string name="month_shortest_january">1월</string> + <string name="month_shortest_february">2월</string> + <string name="month_shortest_march">3월</string> + <string name="month_shortest_april">4월</string> + <string name="month_shortest_may">5월</string> + <string name="month_shortest_june">6월</string> + <string name="month_shortest_july">7월</string> + <string name="month_shortest_august">8월</string> + <string name="month_shortest_september">9월</string> + <string name="month_shortest_october">10월</string> + <string name="month_shortest_november">11월</string> + <string name="month_shortest_december">12월</string> + + <string name="day_of_week_long_sunday">일요일</string> + <string name="day_of_week_long_monday">월요일</string> + <string name="day_of_week_long_tuesday">화요일</string> + <string name="day_of_week_long_wednesday">수요일</string> + <string name="day_of_week_long_thursday">목요일</string> + <string name="day_of_week_long_friday">금요일</string> + <string name="day_of_week_long_saturday">토요일</string> + + <string name="day_of_week_medium_sunday">일</string> + <string name="day_of_week_medium_monday">월</string> + <string name="day_of_week_medium_tuesday">화</string> + <string name="day_of_week_medium_wednesday">수</string> + <string name="day_of_week_medium_thursday">목</string> + <string name="day_of_week_medium_friday">금</string> + <string name="day_of_week_medium_saturday">토</string> + + <string name="day_of_week_short_sunday">일</string> + <string name="day_of_week_short_monday">월</string> + <string name="day_of_week_short_tuesday">화</string> + <string name="day_of_week_short_wednesday">수</string> + <string name="day_of_week_short_thursday">목</string> + <string name="day_of_week_short_friday">금</string> + <string name="day_of_week_short_saturday">토</string> + + <string name="day_of_week_shortest_sunday">일</string> + <string name="day_of_week_shortest_monday">월</string> + <string name="day_of_week_shortest_tuesday">화</string> + <string name="day_of_week_shortest_wednesday">수</string> + <string name="day_of_week_shortest_thursday">목</string> + <string name="day_of_week_shortest_friday">금</string> + <string name="day_of_week_shortest_saturday">토</string> + + <string name="am">오전</string> + <string name="pm">오후</string> + <string name="yesterday">어제</string> + <string name="today">오늘</string> + <string name="tomorrow">내일</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y. %-m. %-e.</string> + <string name="numeric_date_format">yyyy. M. d.</string> + <string name="numeric_date_template">"%s. %s. %s."</string> + <string name="month_day_year">%Y년 %-m월 %-e일</string> + <string name="time_of_day">%p %-l:%M:%S</string> + <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y. %-m. %-e.</string> + <string name="month_day">%B %-e일</string> + <string name="month">%-B</string> + <string name="month_year">%Y년 %B</string> + <string name="abbrev_month_day">%b %-e일</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y년 %b</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <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 new file mode 100644 index 0000000..57cd356 --- /dev/null +++ b/core/res/res/values-ko/donottranslate-cldr.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">1월</string> + <string name="month_long_standalone_february">2월</string> + <string name="month_long_standalone_march">3월</string> + <string name="month_long_standalone_april">4월</string> + <string name="month_long_standalone_may">5월</string> + <string name="month_long_standalone_june">6월</string> + <string name="month_long_standalone_july">7월</string> + <string name="month_long_standalone_august">8월</string> + <string name="month_long_standalone_september">9월</string> + <string name="month_long_standalone_october">10월</string> + <string name="month_long_standalone_november">11월</string> + <string name="month_long_standalone_december">12월</string> + + <string name="month_long_january">1월</string> + <string name="month_long_february">2월</string> + <string name="month_long_march">3월</string> + <string name="month_long_april">4월</string> + <string name="month_long_may">5월</string> + <string name="month_long_june">6월</string> + <string name="month_long_july">7월</string> + <string name="month_long_august">8월</string> + <string name="month_long_september">9월</string> + <string name="month_long_october">10월</string> + <string name="month_long_november">11월</string> + <string name="month_long_december">12월</string> + + + <string name="month_shortest_january">1월</string> + <string name="month_shortest_february">2월</string> + <string name="month_shortest_march">3월</string> + <string name="month_shortest_april">4월</string> + <string name="month_shortest_may">5월</string> + <string name="month_shortest_june">6월</string> + <string name="month_shortest_july">7월</string> + <string name="month_shortest_august">8월</string> + <string name="month_shortest_september">9월</string> + <string name="month_shortest_october">10월</string> + <string name="month_shortest_november">11월</string> + <string name="month_shortest_december">12월</string> + + <string name="day_of_week_long_sunday">일요일</string> + <string name="day_of_week_long_monday">월요일</string> + <string name="day_of_week_long_tuesday">화요일</string> + <string name="day_of_week_long_wednesday">수요일</string> + <string name="day_of_week_long_thursday">목요일</string> + <string name="day_of_week_long_friday">금요일</string> + <string name="day_of_week_long_saturday">토요일</string> + + <string name="day_of_week_medium_sunday">일</string> + <string name="day_of_week_medium_monday">월</string> + <string name="day_of_week_medium_tuesday">화</string> + <string name="day_of_week_medium_wednesday">수</string> + <string name="day_of_week_medium_thursday">목</string> + <string name="day_of_week_medium_friday">금</string> + <string name="day_of_week_medium_saturday">토</string> + + <string name="day_of_week_short_sunday">일</string> + <string name="day_of_week_short_monday">월</string> + <string name="day_of_week_short_tuesday">화</string> + <string name="day_of_week_short_wednesday">수</string> + <string name="day_of_week_short_thursday">목</string> + <string name="day_of_week_short_friday">금</string> + <string name="day_of_week_short_saturday">토</string> + + <string name="day_of_week_shortest_sunday">일</string> + <string name="day_of_week_shortest_monday">월</string> + <string name="day_of_week_shortest_tuesday">화</string> + <string name="day_of_week_shortest_wednesday">수</string> + <string name="day_of_week_shortest_thursday">목</string> + <string name="day_of_week_shortest_friday">금</string> + <string name="day_of_week_shortest_saturday">토</string> + + <string name="am">오전</string> + <string name="pm">오후</string> + <string name="yesterday">어제</string> + <string name="today">오늘</string> + <string name="tomorrow">내일</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y. %-m. %-e.</string> + <string name="numeric_date_format">yyyy. M. d.</string> + <string name="numeric_date_template">"%s. %s. %s."</string> + <string name="month_day_year">%Y년 %-m월 %-e일</string> + <string name="time_of_day">%p %-l:%M:%S</string> + <string name="date_and_time">%p %-l:%M:%S %Y. %-m. %-e.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y. %-m. %-e.</string> + <string name="month_day">%B %-e일</string> + <string name="month">%-B</string> + <string name="month_year">%Y년 %B</string> + <string name="abbrev_month_day">%b %-e일</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y년 %b</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 96b897a..e2c6e57 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"응용프로그램이 로케일 또는 전체 글꼴 크기 같은 현재 구성을 변경할 수 있습니다."</string> <string name="permlab_restartPackages">"다른 응용프로그램 다시 시작"</string> <string name="permdesc_restartPackages">"응용프로그램이 다른 응용프로그램을 강제로 다시 시작할 수 있습니다."</string> - <string name="permlab_setProcessForeground">"중지되지 않도록 하기"</string> - <string name="permdesc_setProcessForeground">"응용프로그램이 프로세스를 포그라운드에서 실행되도록 하여 프로세스를 중지할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다."</string> <string name="permlab_forceBack">"강제로 응용프로그램 닫기"</string> <string name="permdesc_forceBack">"응용프로그램이 포그라운드에 있는 활동을 강제로 닫을 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다."</string> <string name="permlab_dump">"시스템 내부 상태 검색"</string> <string name="permdesc_dump">"응용프로그램이 시스템의 내부 상태를 검색할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인 정보와 보안 정보를 검색할 수 있습니다."</string> - <string name="permlab_addSystemService">"하위 수준 서비스 게시"</string> - <string name="permdesc_addSystemService">"응용프로그램이 자체 하위 수준 시스템 서비스를 게시할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 시스템을 하이재킹하거나 시스템의 데이터를 도용 또는 손상시킬 수 있습니다."</string> <string name="permlab_runSetActivityWatcher">"실행 중인 모든 응용프로그램 모니터링 및 제어"</string> <string name="permdesc_runSetActivityWatcher">"응용프로그램이 시스템에서 활동이 시작되는 방식을 모니터링하고 제어할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 시스템을 완전히 손상시킬 수 있습니다. 이 권한은 개발 과정에만 필요하며 일반 전화기 사용 시에는 필요하지 않습니다."</string> <string name="permlab_broadcastPackageRemoved">"패키지 제거 브로드캐스트 보내기"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"응용프로그램이 실행할 최대 프로세스 수를 제어할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다."</string> <string name="permlab_setAlwaysFinish">"모든 백그라운드 응용프로그램이 닫히도록 하기"</string> <string name="permdesc_setAlwaysFinish">"응용프로그램이 백그라운드로 이동한 활동을 항상 바로 마칠지 여부를 제어할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다."</string> - <string name="permlab_fotaUpdate">"시스템 업데이트 자동으로 설치"</string> - <string name="permdesc_fotaUpdate">"응용프로그램이 대기 중인 시스템 업데이트에 대한 알림을 받고 설치를 트리거할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 인증되지 않은 업데이트로 시스템을 손상시키거나 업데이트 절차를 방해할 수 있습니다."</string> <string name="permlab_batteryStats">"배터리 통계 수정"</string> <string name="permdesc_batteryStats">"수집된 배터리 통계를 수정할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다."</string> <string name="permlab_internalSystemWindow">"인증되지 않은 창 표시"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"비밀번호"</string> <string name="lockscreen_glogin_submit_button">"로그인"</string> <string name="lockscreen_glogin_invalid_input">"사용자 이름 또는 비밀번호가 잘못되었습니다."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"알림 지우기"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"입력"</string> <string name="menu_delete_shortcut_label">"삭제"</string> <string name="search_go">"검색"</string> - <string name="today">"오늘"</string> - <string name="yesterday">"어제"</string> - <string name="tomorrow">"내일"</string> <string name="oneMonthDurationPast">"한 달 전"</string> <string name="beforeOneMonthDurationPast">"한 달 전"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"주"</string> <string name="year">"년"</string> <string name="years">"년"</string> - <string name="sunday">"일요일"</string> - <string name="monday">"월요일"</string> - <string name="tuesday">"화요일"</string> - <string name="wednesday">"수요일"</string> - <string name="thursday">"목요일"</string> - <string name="friday">"금요일"</string> - <string name="saturday">"토요일"</string> <string name="every_weekday">"주중 매일(월-금)"</string> <string name="daily">"매일"</string> <string name="weekly">"매주 <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"죄송합니다. 이 기기로의 스트리밍에 적합하지 않은 동영상입니다."</string> <string name="VideoView_error_text_unknown">"죄송합니다. 동영상을 재생할 수 없습니다."</string> <string name="VideoView_error_button">"확인"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="DAY">d</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="DAY">d</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"정오"</string> <string name="Noon">"정오"</string> <string name="midnight">"자정"</string> <string name="Midnight">"자정"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%b</xliff:g>, <xliff:g id="DAY">%-d</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"일요일"</string> - <string name="day_of_week_long_monday">"월요일"</string> - <string name="day_of_week_long_tuesday">"화요일"</string> - <string name="day_of_week_long_wednesday">"수요일"</string> - <string name="day_of_week_long_thursday">"목요일"</string> - <string name="day_of_week_long_friday">"금요일"</string> - <string name="day_of_week_long_saturday">"토요일"</string> - <string name="day_of_week_medium_sunday">"일요일"</string> - <string name="day_of_week_medium_monday">"월"</string> - <string name="day_of_week_medium_tuesday">"화"</string> - <string name="day_of_week_medium_wednesday">"수"</string> - <string name="day_of_week_medium_thursday">"목"</string> - <string name="day_of_week_medium_friday">"금"</string> - <string name="day_of_week_medium_saturday">"토"</string> - <string name="day_of_week_short_sunday">"일"</string> - <string name="day_of_week_short_monday">"월"</string> - <string name="day_of_week_short_tuesday">"화"</string> - <string name="day_of_week_short_wednesday">"수"</string> - <string name="day_of_week_short_thursday">"목"</string> - <string name="day_of_week_short_friday">"금"</string> - <string name="day_of_week_short_saturday">"토"</string> - <string name="day_of_week_shorter_sunday">"일"</string> - <string name="day_of_week_shorter_monday">"월"</string> - <string name="day_of_week_shorter_tuesday">"화"</string> - <string name="day_of_week_shorter_wednesday">"수"</string> - <string name="day_of_week_shorter_thursday">"목"</string> - <string name="day_of_week_shorter_friday">"금"</string> - <string name="day_of_week_shorter_saturday">"토"</string> - <string name="day_of_week_shortest_sunday">"일"</string> - <string name="day_of_week_shortest_monday">"3월"</string> - <string name="day_of_week_shortest_tuesday">"목"</string> - <string name="day_of_week_shortest_wednesday">"수"</string> - <string name="day_of_week_shortest_thursday">"목"</string> - <string name="day_of_week_shortest_friday">"금"</string> - <string name="day_of_week_shortest_saturday">"토"</string> - <string name="month_long_january">"1월"</string> - <string name="month_long_february">"2월"</string> - <string name="month_long_march">"3월"</string> - <string name="month_long_april">"4월"</string> - <string name="month_long_may">"5월"</string> - <string name="month_long_june">"6월"</string> - <string name="month_long_july">"7월"</string> - <string name="month_long_august">"8월"</string> - <string name="month_long_september">"9월"</string> - <string name="month_long_october">"10월"</string> - <string name="month_long_november">"11월"</string> - <string name="month_long_december">"12월"</string> - <string name="month_medium_january">"1월"</string> - <string name="month_medium_february">"2월"</string> - <string name="month_medium_march">"3월"</string> - <string name="month_medium_april">"4월"</string> - <string name="month_medium_may">"5월"</string> - <string name="month_medium_june">"6월"</string> - <string name="month_medium_july">"7월"</string> - <string name="month_medium_august">"8월"</string> - <string name="month_medium_september">"9월"</string> - <string name="month_medium_october">"10월"</string> - <string name="month_medium_november">"11월"</string> - <string name="month_medium_december">"12월"</string> - <string name="month_shortest_january">"1월"</string> - <string name="month_shortest_february">"금"</string> - <string name="month_shortest_march">"3월"</string> - <string name="month_shortest_april">"4월"</string> - <string name="month_shortest_may">"5월"</string> - <string name="month_shortest_june">"6월"</string> - <string name="month_shortest_july">"7월"</string> - <string name="month_shortest_august">"8월"</string> - <string name="month_shortest_september">"9월"</string> - <string name="month_shortest_october">"10월"</string> - <string name="month_shortest_november">"11월"</string> - <string name="month_shortest_december">"12월"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"모두 선택"</string> diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml new file mode 100644 index 0000000..20d58e0 --- /dev/null +++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Sausis</string> + <string name="month_long_standalone_february">Vasaris</string> + <string name="month_long_standalone_march">Kovas</string> + <string name="month_long_standalone_april">Balandis</string> + <string name="month_long_standalone_may">Gegužė</string> + <string name="month_long_standalone_june">Birželis</string> + <string name="month_long_standalone_july">Liepa</string> + <string name="month_long_standalone_august">Rugpjūtis</string> + <string name="month_long_standalone_september">Rugsėjis</string> + <string name="month_long_standalone_october">Spalis</string> + <string name="month_long_standalone_november">Lapkritis</string> + <string name="month_long_standalone_december">Gruodis</string> + + <string name="month_long_january">sausio</string> + <string name="month_long_february">vasario</string> + <string name="month_long_march">kovo</string> + <string name="month_long_april">balandžio</string> + <string name="month_long_may">gegužės</string> + <string name="month_long_june">birželio</string> + <string name="month_long_july">liepos</string> + <string name="month_long_august">rugpjūčio</string> + <string name="month_long_september">rugsėjo</string> + <string name="month_long_october">spalio</string> + <string name="month_long_november">lapkričio</string> + <string name="month_long_december">gruodžio</string> + + <string name="month_medium_january">Sau</string> + <string name="month_medium_february">Vas</string> + <string name="month_medium_march">Kov</string> + <string name="month_medium_april">Bal</string> + <string name="month_medium_may">Geg</string> + <string name="month_medium_june">Bir</string> + <string name="month_medium_july">Lie</string> + <string name="month_medium_august">Rgp</string> + <string name="month_medium_september">Rgs</string> + <string name="month_medium_october">Spl</string> + <string name="month_medium_november">Lap</string> + <string name="month_medium_december">Grd</string> + + <string name="month_shortest_january">S</string> + <string name="month_shortest_february">V</string> + <string name="month_shortest_march">K</string> + <string name="month_shortest_april">B</string> + <string name="month_shortest_may">G</string> + <string name="month_shortest_june">B</string> + <string name="month_shortest_july">L</string> + <string name="month_shortest_august">R</string> + <string name="month_shortest_september">R</string> + <string name="month_shortest_october">S</string> + <string name="month_shortest_november">L</string> + <string name="month_shortest_december">G</string> + + <string name="day_of_week_long_sunday">sekmadienis</string> + <string name="day_of_week_long_monday">pirmadienis</string> + <string name="day_of_week_long_tuesday">antradienis</string> + <string name="day_of_week_long_wednesday">trečiadienis</string> + <string name="day_of_week_long_thursday">ketvirtadienis</string> + <string name="day_of_week_long_friday">penktadienis</string> + <string name="day_of_week_long_saturday">šeštadienis</string> + + <string name="day_of_week_medium_sunday">Sk</string> + <string name="day_of_week_medium_monday">Pr</string> + <string name="day_of_week_medium_tuesday">An</string> + <string name="day_of_week_medium_wednesday">Tr</string> + <string name="day_of_week_medium_thursday">Kt</string> + <string name="day_of_week_medium_friday">Pn</string> + <string name="day_of_week_medium_saturday">Št</string> + + <string name="day_of_week_short_sunday">Sk</string> + <string name="day_of_week_short_monday">Pr</string> + <string name="day_of_week_short_tuesday">An</string> + <string name="day_of_week_short_wednesday">Tr</string> + <string name="day_of_week_short_thursday">Kt</string> + <string name="day_of_week_short_friday">Pn</string> + <string name="day_of_week_short_saturday">Št</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">A</string> + <string name="day_of_week_shortest_wednesday">T</string> + <string name="day_of_week_shortest_thursday">K</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">Š</string> + + <string name="am">priešpiet</string> + <string name="pm">popiet</string> + <string name="yesterday">vakar</string> + <string name="today">šiandien</string> + <string name="tomorrow">rytoj</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%Y m. %B %-e d.</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y.%m.%d</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y.%m.%d</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%b %-e 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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-lv-rLV/donottranslate-cldr.xml b/core/res/res/values-lv-rLV/donottranslate-cldr.xml new file mode 100644 index 0000000..3dec1d2 --- /dev/null +++ b/core/res/res/values-lv-rLV/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janvāris</string> + <string name="month_long_standalone_february">februāris</string> + <string name="month_long_standalone_march">marts</string> + <string name="month_long_standalone_april">aprīlis</string> + <string name="month_long_standalone_may">maijs</string> + <string name="month_long_standalone_june">jūnijs</string> + <string name="month_long_standalone_july">jūlijs</string> + <string name="month_long_standalone_august">augusts</string> + <string name="month_long_standalone_september">septembris</string> + <string name="month_long_standalone_october">oktobris</string> + <string name="month_long_standalone_november">novembris</string> + <string name="month_long_standalone_december">decembris</string> + + <string name="month_long_january">janvāris</string> + <string name="month_long_february">februāris</string> + <string name="month_long_march">marts</string> + <string name="month_long_april">aprīlis</string> + <string name="month_long_may">maijs</string> + <string name="month_long_june">jūnijs</string> + <string name="month_long_july">jūlijs</string> + <string name="month_long_august">augusts</string> + <string name="month_long_september">septembris</string> + <string name="month_long_october">oktobris</string> + <string name="month_long_november">novembris</string> + <string name="month_long_december">decembris</string> + + <string name="month_medium_january">janv.</string> + <string name="month_medium_february">febr.</string> + <string name="month_medium_march">marts</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">maijs</string> + <string name="month_medium_june">jūn.</string> + <string name="month_medium_july">jūl.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">svētdiena</string> + <string name="day_of_week_long_monday">pirmdiena</string> + <string name="day_of_week_long_tuesday">otrdiena</string> + <string name="day_of_week_long_wednesday">trešdiena</string> + <string name="day_of_week_long_thursday">ceturtdiena</string> + <string name="day_of_week_long_friday">piektdiena</string> + <string name="day_of_week_long_saturday">sestdiena</string> + + <string name="day_of_week_medium_sunday">Sv</string> + <string name="day_of_week_medium_monday">Pr</string> + <string name="day_of_week_medium_tuesday">Ot</string> + <string name="day_of_week_medium_wednesday">Tr</string> + <string name="day_of_week_medium_thursday">Ce</string> + <string name="day_of_week_medium_friday">Pk</string> + <string name="day_of_week_medium_saturday">Se</string> + + <string name="day_of_week_short_sunday">Sv</string> + <string name="day_of_week_short_monday">Pr</string> + <string name="day_of_week_short_tuesday">Ot</string> + <string name="day_of_week_short_wednesday">Tr</string> + <string name="day_of_week_short_thursday">Ce</string> + <string name="day_of_week_short_friday">Pk</string> + <string name="day_of_week_short_saturday">Se</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">O</string> + <string name="day_of_week_shortest_wednesday">T</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">vakar</string> + <string name="today">šodien</string> + <string name="tomorrow">rīt</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%Y. gada %-e. %B</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y. gada %-e. %b</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y. gada %-e. %b</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%Y. g. %B</string> + <string name="abbrev_month_day">%-e. %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y. g. %b</string> + <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, %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="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">%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_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_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. gada %3$s. %2$s - %10$s %9$s. gada %8$s. %7$s</string> + <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s. g. %3$s. %2$s - %10$s %6$s, %9$s. g. %8$s. %7$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s. g. %3$s. %2$s - %6$s, %9$s. g. %8$s. %7$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">%9$s. gada %3$s. %2$s - %8$s. %7$s</string> + <string name="same_month_mdy1_mdy2">%9$s. gada %3$s.-%8$s. %2$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s. gada %3$s. %2$s - %6$s, y. gada %8$s. %7$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-mcc204-pt/strings.xml b/core/res/res/values-mcc204-pt/strings.xml new file mode 100644 index 0000000..7d96230 --- /dev/null +++ b/core/res/res/values-mcc204-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"nl_nl"</string> +</resources> diff --git a/core/res/res/values-mcc230-pt/strings.xml b/core/res/res/values-mcc230-pt/strings.xml new file mode 100644 index 0000000..d3ecdbb --- /dev/null +++ b/core/res/res/values-mcc230-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"cs_cz"</string> +</resources> diff --git a/core/res/res/values-mcc232-pt/strings.xml b/core/res/res/values-mcc232-pt/strings.xml new file mode 100644 index 0000000..4773838 --- /dev/null +++ b/core/res/res/values-mcc232-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"de_at"</string> +</resources> diff --git a/core/res/res/values-mcc234-pt/strings.xml b/core/res/res/values-mcc234-pt/strings.xml new file mode 100644 index 0000000..2538b73 --- /dev/null +++ b/core/res/res/values-mcc234-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"en_gb"</string> +</resources> diff --git a/core/res/res/values-mcc260-pt/strings.xml b/core/res/res/values-mcc260-pt/strings.xml new file mode 100644 index 0000000..1161f9a --- /dev/null +++ b/core/res/res/values-mcc260-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"pl_pl"</string> +</resources> diff --git a/core/res/res/values-mcc262-pt/strings.xml b/core/res/res/values-mcc262-pt/strings.xml new file mode 100644 index 0000000..9505cf4 --- /dev/null +++ b/core/res/res/values-mcc262-pt/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="locale_replacement">"de_de"</string> +</resources> diff --git a/core/res/res/values-nb/donottranslate-cldr.xml b/core/res/res/values-nb/donottranslate-cldr.xml new file mode 100644 index 0000000..ecf0111 --- /dev/null +++ b/core/res/res/values-nb/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januar</string> + <string name="month_long_standalone_february">februar</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">desember</string> + + <string name="month_long_january">januar</string> + <string name="month_long_february">februar</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">april</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">august</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">desember</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">juni</string> + <string name="month_medium_july">juli</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">des.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">søndag</string> + <string name="day_of_week_long_monday">mandag</string> + <string name="day_of_week_long_tuesday">tirsdag</string> + <string name="day_of_week_long_wednesday">onsdag</string> + <string name="day_of_week_long_thursday">torsdag</string> + <string name="day_of_week_long_friday">fredag</string> + <string name="day_of_week_long_saturday">lørdag</string> + + <string name="day_of_week_medium_sunday">søn.</string> + <string name="day_of_week_medium_monday">man.</string> + <string name="day_of_week_medium_tuesday">tir.</string> + <string name="day_of_week_medium_wednesday">ons.</string> + <string name="day_of_week_medium_thursday">tor.</string> + <string name="day_of_week_medium_friday">fre.</string> + <string name="day_of_week_medium_saturday">lør.</string> + + <string name="day_of_week_short_sunday">søn.</string> + <string name="day_of_week_short_monday">man.</string> + <string name="day_of_week_short_tuesday">tir.</string> + <string name="day_of_week_short_wednesday">ons.</string> + <string name="day_of_week_short_thursday">tor.</string> + <string name="day_of_week_short_friday">fre.</string> + <string name="day_of_week_short_saturday">lør.</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">O</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">i går</string> + <string name="today">i dag</string> + <string name="tomorrow">i morgen</string> + + <string name="hour_minute_24">%H.%M</string> + <string name="hour_minute_ampm">%-l.%M %p</string> + <string name="hour_minute_cap_ampm">%-l.%M %^p</string> + <string name="twelve_hour_time_format">h.mm a</string> + <string name="twenty_four_hour_time_format">HH.mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %-e. %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e. %b %Y</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e. %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 7bed159..33d0159 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -166,14 +166,10 @@ <string name="permdesc_changeConfiguration">"Tillater applikasjonen å endre gjeldende innstillinger, slik som språk eller skriftstørrelse."</string> <string name="permlab_restartPackages">"omstarte andre applikasjoner"</string> <string name="permdesc_restartPackages">"Lar applikasjonen tvinge andre applikasjoner til å starte på nytt."</string> - <string name="permlab_setProcessForeground">"unngå å bli stoppet"</string> - <string name="permdesc_setProcessForeground">"Lar applikasjonen sette en vilkårlig prosess i forgrunnen, så den ikke kan bli drept. Vanlige applikasjoner bør aldri trenge dette."</string> <string name="permlab_forceBack">"tvinge applikasjoner til å lukkes"</string> <string name="permdesc_forceBack">"Lar applikasjonen tvinge enhver aktivitet som er i forgrunnen til å lukkes og gå tilbake. Vanlige applikasjoner bør aldri trenge dette."</string> <string name="permlab_dump">"hente intern systemtilstand"</string> <string name="permdesc_dump">"Lar applikasjonen hente intern tilstand fra systemet. Onsdinnede applikasjoner kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for."</string> - <string name="permlab_addSystemService">"publisere lavnivåtjenester"</string> - <string name="permdesc_addSystemService">"Lar applikasjonen publisere sine egne lavnivås systemtjenester. Ondsinnede applikasjoner kan kapre systemet, og stjele eller ødelegge alle data på det."</string> <string name="permlab_runSetActivityWatcher">"overvåke og kontrollere all applikasjonsoppstart"</string> <string name="permdesc_runSetActivityWatcher">"Lar applikasjonen overvåke og kontrollere hvordan systemet starter applikasjoner. Ondsinnede applikasjoner kan ta over systemet helt. Denne rettigheten behøves bare for utvikling, aldri for vanlig bruk av telefonen."</string> <string name="permlab_broadcastPackageRemoved">"kringkaste melding om fjernet pakke"</string> @@ -186,8 +182,6 @@ <string name="permdesc_setProcessLimit">"Lar applikasjonen kontrollere maksimalt antall kjørende prosesser. Behøves aldri for vanlige applikasjoner."</string> <string name="permlab_setAlwaysFinish">"få alle bakgrunnsapplikasjoner til å lukkes"</string> <string name="permdesc_setAlwaysFinish">"Lar applikasjonen kontrollere om aktiviteter alltid avsluttes når de sendes til bakgrunnen. Behøves aldri for vanlige applikasjoner."</string> - <string name="permlab_fotaUpdate">"installere systemoppdateringer automatisk"</string> - <string name="permdesc_fotaUpdate">"Lar applikasjonen motta meldinger om pågående systemoppdateringer, og starte installeringen av dem. Ondsinnede applikasjoner kan bruke dette for å skade systemet med uautoriserte oppdateringer, eller generelt forstyrre oppdateringsprosessen."</string> <string name="permlab_batteryStats">"endre batteristatistikk"</string> <string name="permdesc_batteryStats">"Lar applikasjonen endre på innsamlet batteristatistikk. Ikke ment for vanlige applikasjoner."</string> <string name="permlab_internalSystemWindow">"vis uautoriserte vinduer"</string> @@ -424,9 +418,6 @@ <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Sign in"</string> <string name="lockscreen_glogin_invalid_input">"Invalid username or password."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Fjern varslinger"</string> @@ -458,9 +449,6 @@ <string name="menu_enter_shortcut_label">"enter"</string> <string name="menu_delete_shortcut_label">"slett"</string> <string name="search_go">"Søk"</string> - <string name="today">"I dag"</string> - <string name="yesterday">"I går"</string> - <string name="tomorrow">"I morgen"</string> <string name="oneMonthDurationPast">"For en måned siden"</string> <string name="beforeOneMonthDurationPast">"For over en måned siden"</string> <plurals name="num_seconds_ago"> @@ -542,13 +530,6 @@ <string name="weeks">"uker"</string> <string name="year">"år"</string> <string name="years">"år"</string> - <string name="sunday">"søndag"</string> - <string name="monday">"mandag"</string> - <string name="tuesday">"tirsdag"</string> - <string name="wednesday">"onsdag"</string> - <string name="thursday">"torsdag"</string> - <string name="friday">"fredag"</string> - <string name="saturday">"lørdag"</string> <string name="every_weekday">"Hverdager (man–fre)"</string> <string name="daily">"Hver dag"</string> <string name="weekly">"Hver <xliff:g id="DAY">%s</xliff:g>"</string> @@ -558,26 +539,7 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Beklager, denne videoen er ikke gyldig for streaming til denne enheten."</string> <string name="VideoView_error_text_unknown">"Beklager, kan ikke spille denne videoen."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g>-<xliff:g id="MONTH">%m</xliff:g>-<xliff:g id="DAY">%d</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>PLACEHOLDERplaceholder"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>'., '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"middag"</string> <string name="Noon">"Middag"</string> <string name="midnight">"midnatt"</string> @@ -586,111 +548,10 @@ <skip /> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>."</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>."</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>. <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>. <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>.–<xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>.–<xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"søndag"</string> - <string name="day_of_week_long_monday">"mandag"</string> - <string name="day_of_week_long_tuesday">"tirsdag"</string> - <string name="day_of_week_long_wednesday">"onsdag"</string> - <string name="day_of_week_long_thursday">"torsdag"</string> - <string name="day_of_week_long_friday">"fredag"</string> - <string name="day_of_week_long_saturday">"lørdag"</string> - <string name="day_of_week_medium_sunday">"søn"</string> - <string name="day_of_week_medium_monday">"man"</string> - <string name="day_of_week_medium_tuesday">"tir"</string> - <string name="day_of_week_medium_wednesday">"ons"</string> - <string name="day_of_week_medium_thursday">"tor"</string> - <string name="day_of_week_medium_friday">"fre"</string> - <string name="day_of_week_medium_saturday">"lør"</string> - <string name="day_of_week_short_sunday">"sø"</string> - <string name="day_of_week_short_monday">"ma"</string> - <string name="day_of_week_short_tuesday">"ti"</string> - <string name="day_of_week_short_wednesday">"on"</string> - <string name="day_of_week_short_thursday">"to"</string> - <string name="day_of_week_short_friday">"fr"</string> - <string name="day_of_week_short_saturday">"lø"</string> - <string name="day_of_week_shorter_sunday">"S"</string> - <string name="day_of_week_shorter_monday">"M"</string> - <string name="day_of_week_shorter_tuesday">"Ti"</string> - <string name="day_of_week_shorter_wednesday">"O"</string> - <string name="day_of_week_shorter_thursday">"To"</string> - <string name="day_of_week_shorter_friday">"F"</string> - <string name="day_of_week_shorter_saturday">"L"</string> - <string name="day_of_week_shortest_sunday">"S"</string> - <string name="day_of_week_shortest_monday">"M"</string> - <string name="day_of_week_shortest_tuesday">"T"</string> - <string name="day_of_week_shortest_wednesday">"O"</string> - <string name="day_of_week_shortest_thursday">"T"</string> - <string name="day_of_week_shortest_friday">"F"</string> - <string name="day_of_week_shortest_saturday">"L"</string> - <string name="month_long_january">"januar"</string> - <string name="month_long_february">"februar"</string> - <string name="month_long_march">"mars"</string> - <string name="month_long_april">"april"</string> - <string name="month_long_may">"mai"</string> - <string name="month_long_june">"juni"</string> - <string name="month_long_july">"juli"</string> - <string name="month_long_august">"august"</string> - <string name="month_long_september">"september"</string> - <string name="month_long_october">"oktober"</string> - <string name="month_long_november">"november"</string> - <string name="month_long_december">"desember"</string> - <string name="month_medium_january">"jan"</string> - <string name="month_medium_february">"feb"</string> - <string name="month_medium_march">"mar"</string> - <string name="month_medium_april">"apr"</string> - <string name="month_medium_may">"mai"</string> - <string name="month_medium_june">"jun"</string> - <string name="month_medium_july">"jul"</string> - <string name="month_medium_august">"aug"</string> - <string name="month_medium_september">"sep"</string> - <string name="month_medium_october">"okt"</string> - <string name="month_medium_november">"nov"</string> - <string name="month_medium_december">"des"</string> - <string name="month_shortest_january">"J"</string> - <string name="month_shortest_february">"F"</string> - <string name="month_shortest_march">"M"</string> - <string name="month_shortest_april">"A"</string> - <string name="month_shortest_may">"M"</string> - <string name="month_shortest_june">"J"</string> - <string name="month_shortest_july">"J"</string> - <string name="month_shortest_august">"A"</string> - <string name="month_shortest_september">"S"</string> - <string name="month_shortest_october">"O"</string> - <string name="month_shortest_november">"N"</string> - <string name="month_shortest_december">"D"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Merk alt"</string> diff --git a/core/res/res/values-nl-rBE/donottranslate-cldr.xml b/core/res/res/values-nl-rBE/donottranslate-cldr.xml new file mode 100644 index 0000000..680a392 --- /dev/null +++ b/core/res/res/values-nl-rBE/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januari</string> + <string name="month_long_standalone_february">februari</string> + <string name="month_long_standalone_march">maart</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">mei</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">augustus</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januari</string> + <string name="month_long_february">februari</string> + <string name="month_long_march">maart</string> + <string name="month_long_april">april</string> + <string name="month_long_may">mei</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">augustus</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mrt.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mei</string> + <string name="month_medium_june">jun.</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">zondag</string> + <string name="day_of_week_long_monday">maandag</string> + <string name="day_of_week_long_tuesday">dinsdag</string> + <string name="day_of_week_long_wednesday">woensdag</string> + <string name="day_of_week_long_thursday">donderdag</string> + <string name="day_of_week_long_friday">vrijdag</string> + <string name="day_of_week_long_saturday">zaterdag</string> + + <string name="day_of_week_medium_sunday">zo</string> + <string name="day_of_week_medium_monday">ma</string> + <string name="day_of_week_medium_tuesday">di</string> + <string name="day_of_week_medium_wednesday">wo</string> + <string name="day_of_week_medium_thursday">do</string> + <string name="day_of_week_medium_friday">vr</string> + <string name="day_of_week_medium_saturday">za</string> + + <string name="day_of_week_short_sunday">zo</string> + <string name="day_of_week_short_monday">ma</string> + <string name="day_of_week_short_tuesday">di</string> + <string name="day_of_week_short_wednesday">wo</string> + <string name="day_of_week_short_thursday">do</string> + <string name="day_of_week_short_friday">vr</string> + <string name="day_of_week_short_saturday">za</string> + + <string name="day_of_week_shortest_sunday">Z</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">Z</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Gisteren</string> + <string name="today">Vandaag</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-e/%m/%Y</string> + <string name="numeric_date_format">d/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e-%b-%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e-%b-%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e-%b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-nl-rNL/donottranslate-cldr.xml b/core/res/res/values-nl-rNL/donottranslate-cldr.xml new file mode 100644 index 0000000..b6231b6 --- /dev/null +++ b/core/res/res/values-nl-rNL/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januari</string> + <string name="month_long_standalone_february">februari</string> + <string name="month_long_standalone_march">maart</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">mei</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">augustus</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januari</string> + <string name="month_long_february">februari</string> + <string name="month_long_march">maart</string> + <string name="month_long_april">april</string> + <string name="month_long_may">mei</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">augustus</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mrt.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mei</string> + <string name="month_medium_june">jun.</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">zondag</string> + <string name="day_of_week_long_monday">maandag</string> + <string name="day_of_week_long_tuesday">dinsdag</string> + <string name="day_of_week_long_wednesday">woensdag</string> + <string name="day_of_week_long_thursday">donderdag</string> + <string name="day_of_week_long_friday">vrijdag</string> + <string name="day_of_week_long_saturday">zaterdag</string> + + <string name="day_of_week_medium_sunday">zo</string> + <string name="day_of_week_medium_monday">ma</string> + <string name="day_of_week_medium_tuesday">di</string> + <string name="day_of_week_medium_wednesday">wo</string> + <string name="day_of_week_medium_thursday">do</string> + <string name="day_of_week_medium_friday">vr</string> + <string name="day_of_week_medium_saturday">za</string> + + <string name="day_of_week_short_sunday">zo</string> + <string name="day_of_week_short_monday">ma</string> + <string name="day_of_week_short_tuesday">di</string> + <string name="day_of_week_short_wednesday">wo</string> + <string name="day_of_week_short_thursday">do</string> + <string name="day_of_week_short_friday">vr</string> + <string name="day_of_week_short_saturday">za</string> + + <string name="day_of_week_shortest_sunday">Z</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">Z</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Gisteren</string> + <string name="today">Vandaag</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d-%m-%Y</string> + <string name="numeric_date_format">dd-MM-yyyy</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e-%b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-nl/donottranslate-cldr.xml b/core/res/res/values-nl/donottranslate-cldr.xml new file mode 100644 index 0000000..b6231b6 --- /dev/null +++ b/core/res/res/values-nl/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januari</string> + <string name="month_long_standalone_february">februari</string> + <string name="month_long_standalone_march">maart</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">mei</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">augustus</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januari</string> + <string name="month_long_february">februari</string> + <string name="month_long_march">maart</string> + <string name="month_long_april">april</string> + <string name="month_long_may">mei</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">augustus</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mrt.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mei</string> + <string name="month_medium_june">jun.</string> + <string name="month_medium_july">jul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sep.</string> + <string name="month_medium_october">okt.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">zondag</string> + <string name="day_of_week_long_monday">maandag</string> + <string name="day_of_week_long_tuesday">dinsdag</string> + <string name="day_of_week_long_wednesday">woensdag</string> + <string name="day_of_week_long_thursday">donderdag</string> + <string name="day_of_week_long_friday">vrijdag</string> + <string name="day_of_week_long_saturday">zaterdag</string> + + <string name="day_of_week_medium_sunday">zo</string> + <string name="day_of_week_medium_monday">ma</string> + <string name="day_of_week_medium_tuesday">di</string> + <string name="day_of_week_medium_wednesday">wo</string> + <string name="day_of_week_medium_thursday">do</string> + <string name="day_of_week_medium_friday">vr</string> + <string name="day_of_week_medium_saturday">za</string> + + <string name="day_of_week_short_sunday">zo</string> + <string name="day_of_week_short_monday">ma</string> + <string name="day_of_week_short_tuesday">di</string> + <string name="day_of_week_short_wednesday">wo</string> + <string name="day_of_week_short_thursday">do</string> + <string name="day_of_week_short_friday">vr</string> + <string name="day_of_week_short_saturday">za</string> + + <string name="day_of_week_shortest_sunday">Z</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">D</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">D</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">Z</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Gisteren</string> + <string name="today">Vandaag</string> + <string name="tomorrow">Morgen</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d-%m-%Y</string> + <string name="numeric_date_format">dd-MM-yyyy</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e-%b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 3a9e32c..a418d72 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Hiermee kan een toepassing de huidige configuratie, zoals de landinstelling of de algemene lettergrootte, wijzigen."</string> <string name="permlab_restartPackages">"andere toepassingen opnieuw starten"</string> <string name="permdesc_restartPackages">"Hiermee kan een toepassing andere toepassingen opnieuw starten."</string> - <string name="permlab_setProcessForeground">"stoppen voorkomen"</string> - <string name="permdesc_setProcessForeground">"Hiermee kan een toepassing ervoor zorgen dat elk willekeurig proces op de voorgrond wordt uitgevoerd en dus niet kan worden afgesloten. Nooit vereist voor normale toepassingen."</string> <string name="permlab_forceBack">"toepassing nu sluiten"</string> <string name="permdesc_forceBack">"Hiermee kan een toepassing elke willekeurige activiteit die op de voorgrond wordt uitgevoerd, sluiten en naar de achtergrond verplaatsen. Nooit vereist voor normale toepassingen."</string> <string name="permlab_dump">"interne systeemstatus ophalen"</string> <string name="permdesc_dump">"Hiermee kan een toepassing de interne status van het systeem ophalen. Schadelijke toepassingen kunnen privé- of veiligheidsgegevens ophalen die ze normaal niet nodig hebben."</string> - <string name="permlab_addSystemService">"services op laag niveau publiceren"</string> - <string name="permdesc_addSystemService">"Hiermee kunnen toepassingen hun eigen systeemservices op laag niveau publiceren. Schadelijke toepassingen kunnen het systeem mogelijk kapen en willekeurige gegevens van het systeem stelen of beschadigen."</string> <string name="permlab_runSetActivityWatcher">"alle startende toepassingen bijhouden en beheren"</string> <string name="permdesc_runSetActivityWatcher">"Hiermee kan een toepassing de manier waarop het systeem activiteiten start, bijhouden en beheren. Schadelijke toepassingen kunnen het systeem volledig in gevaar brengen. Deze machtiging is alleen voor ontwikkeling vereist, nooit voor normaal telefoongebruik."</string> <string name="permlab_broadcastPackageRemoved">"melding verzenden dat pakket is verwijderd"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Hiermee kan een toepassing het maximum aantal processen bepalen dat wordt uitgevoerd. Nooit vereist voor normale toepassingen."</string> <string name="permlab_setAlwaysFinish">"alle achtergrondtoepassingen sluiten"</string> <string name="permdesc_setAlwaysFinish">"Hiermee kan een toepassing bepalen of activiteiten altijd worden afgesloten zodra deze naar de achtergrond gaan. Nooit nodig voor normale toepassingen."</string> - <string name="permlab_fotaUpdate">"systeemupdates automatisch installeren"</string> - <string name="permdesc_fotaUpdate">"Hiermee ontvangt een toepassing meldingen over beschikbare systeemupdates en kan hun installatie starten. Schadelijke toepassingen kunnen hiervan gebruik maken om het systeem met ongeautoriseerde updates te beschadigen of het updateproces in het algemeen te verstoren."</string> <string name="permlab_batteryStats">"accustatistieken aanpassen"</string> <string name="permdesc_batteryStats">"Hiermee kunnen verzamelde accustatistieken worden gewijzigd. Niet voor gebruik door normale toepassingen."</string> <string name="permlab_internalSystemWindow">"niet-geautoriseerde vensters weergeven"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Wachtwoord"</string> <string name="lockscreen_glogin_submit_button">"Aanmelden"</string> <string name="lockscreen_glogin_invalid_input">"Gebruikersnaam of wachtwoord ongeldig."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Meldingen wissen"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"invoeren"</string> <string name="menu_delete_shortcut_label">"verwijderen"</string> <string name="search_go">"Zoeken"</string> - <string name="today">"Vandaag"</string> - <string name="yesterday">"Gisteren"</string> - <string name="tomorrow">"Morgen"</string> <string name="oneMonthDurationPast">"1 maand geleden"</string> <string name="beforeOneMonthDurationPast">"Meer dan 1 maand geleden"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"weken"</string> <string name="year">"jaar"</string> <string name="years">"jaren"</string> - <string name="sunday">"Zondag"</string> - <string name="monday">"Maandag"</string> - <string name="tuesday">"Dinsdag"</string> - <string name="wednesday">"Woensdag"</string> - <string name="thursday">"Donderdag"</string> - <string name="friday">"Vrijdag"</string> - <string name="saturday">"Zaterdag"</string> <string name="every_weekday">"Elke weekdag (ma-vr)"</string> <string name="daily">"Dagelijks"</string> <string name="weekly">"Wekelijks op <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Deze video kan helaas niet worden gestreamd naar dit apparaat."</string> <string name="VideoView_error_text_unknown">"Deze video kan niet worden afgespeeld."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"am"</string> - <string name="pm">"pm"</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>-<xliff:g id="MONTH">%m</xliff:g>-<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"twaalf uur \'s middags"</string> <string name="Noon">"Twaalf uur \'s middags"</string> <string name="midnight">"middernacht"</string> <string name="Midnight">"Middernacht"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>-<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>-<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>-<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>-<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>-<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>-<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>-<xliff:g id="MONTH1">%2$s</xliff:g>-<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>-<xliff:g id="MONTH2">%7$s</xliff:g>-<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"Zondag"</string> - <string name="day_of_week_long_monday">"Maandag"</string> - <string name="day_of_week_long_tuesday">"Dinsdag"</string> - <string name="day_of_week_long_wednesday">"Woensdag"</string> - <string name="day_of_week_long_thursday">"Donderdag"</string> - <string name="day_of_week_long_friday">"Vrijdag"</string> - <string name="day_of_week_long_saturday">"Zaterdag"</string> - <string name="day_of_week_medium_sunday">"Zo"</string> - <string name="day_of_week_medium_monday">"Ma"</string> - <string name="day_of_week_medium_tuesday">"Di"</string> - <string name="day_of_week_medium_wednesday">"Wo"</string> - <string name="day_of_week_medium_thursday">"Do"</string> - <string name="day_of_week_medium_friday">"Vr"</string> - <string name="day_of_week_medium_saturday">"Za"</string> - <string name="day_of_week_short_sunday">"Zo"</string> - <string name="day_of_week_short_monday">"Ma"</string> - <string name="day_of_week_short_tuesday">"Di"</string> - <string name="day_of_week_short_wednesday">"Wo"</string> - <string name="day_of_week_short_thursday">"Do"</string> - <string name="day_of_week_short_friday">"Vr"</string> - <string name="day_of_week_short_saturday">"Za"</string> - <string name="day_of_week_shorter_sunday">"Zo"</string> - <string name="day_of_week_shorter_monday">"M"</string> - <string name="day_of_week_shorter_tuesday">"Di"</string> - <string name="day_of_week_shorter_wednesday">"W"</string> - <string name="day_of_week_shorter_thursday">"Do"</string> - <string name="day_of_week_shorter_friday">"V"</string> - <string name="day_of_week_shorter_saturday">"Za"</string> - <string name="day_of_week_shortest_sunday">"Z"</string> - <string name="day_of_week_shortest_monday">"M"</string> - <string name="day_of_week_shortest_tuesday">"D"</string> - <string name="day_of_week_shortest_wednesday">"W"</string> - <string name="day_of_week_shortest_thursday">"D"</string> - <string name="day_of_week_shortest_friday">"V"</string> - <string name="day_of_week_shortest_saturday">"Z"</string> - <string name="month_long_january">"Januari"</string> - <string name="month_long_february">"Februari"</string> - <string name="month_long_march">"Maart"</string> - <string name="month_long_april">"April"</string> - <string name="month_long_may">"Mei"</string> - <string name="month_long_june">"Juni"</string> - <string name="month_long_july">"Juli"</string> - <string name="month_long_august">"Augustus"</string> - <string name="month_long_september">"September"</string> - <string name="month_long_october">"Oktober"</string> - <string name="month_long_november">"November"</string> - <string name="month_long_december">"December"</string> - <string name="month_medium_january">"Jan"</string> - <string name="month_medium_february">"Feb"</string> - <string name="month_medium_march">"Mrt"</string> - <string name="month_medium_april">"Apr"</string> - <string name="month_medium_may">"Mei"</string> - <string name="month_medium_june">"Jun"</string> - <string name="month_medium_july">"Jul"</string> - <string name="month_medium_august">"Aug"</string> - <string name="month_medium_september">"Sep"</string> - <string name="month_medium_october">"Okt"</string> - <string name="month_medium_november">"Nov"</string> - <string name="month_medium_december">"Dec"</string> - <string name="month_shortest_january">"J"</string> - <string name="month_shortest_february">"V"</string> - <string name="month_shortest_march">"M"</string> - <string name="month_shortest_april">"A"</string> - <string name="month_shortest_may">"M"</string> - <string name="month_shortest_june">"J"</string> - <string name="month_shortest_july">"J"</string> - <string name="month_shortest_august">"A"</string> - <string name="month_shortest_september">"S"</string> - <string name="month_shortest_october">"O"</string> - <string name="month_shortest_november">"N"</string> - <string name="month_shortest_december">"D"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Alles selecteren"</string> diff --git a/core/res/res/values-pl-rPL/donottranslate-cldr.xml b/core/res/res/values-pl-rPL/donottranslate-cldr.xml new file mode 100644 index 0000000..4ad17bf --- /dev/null +++ b/core/res/res/values-pl-rPL/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">styczeń</string> + <string name="month_long_standalone_february">luty</string> + <string name="month_long_standalone_march">marzec</string> + <string name="month_long_standalone_april">kwiecień</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">czerwiec</string> + <string name="month_long_standalone_july">lipiec</string> + <string name="month_long_standalone_august">sierpień</string> + <string name="month_long_standalone_september">wrzesień</string> + <string name="month_long_standalone_october">październik</string> + <string name="month_long_standalone_november">listopad</string> + <string name="month_long_standalone_december">grudzień</string> + + <string name="month_long_january">stycznia</string> + <string name="month_long_february">lutego</string> + <string name="month_long_march">marca</string> + <string name="month_long_april">kwietnia</string> + <string name="month_long_may">maja</string> + <string name="month_long_june">czerwca</string> + <string name="month_long_july">lipca</string> + <string name="month_long_august">sierpnia</string> + <string name="month_long_september">września</string> + <string name="month_long_october">października</string> + <string name="month_long_november">listopada</string> + <string name="month_long_december">grudnia</string> + + <string name="month_medium_january">sty</string> + <string name="month_medium_february">lut</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">kwi</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">cze</string> + <string name="month_medium_july">lip</string> + <string name="month_medium_august">sie</string> + <string name="month_medium_september">wrz</string> + <string name="month_medium_october">paź</string> + <string name="month_medium_november">lis</string> + <string name="month_medium_december">gru</string> + + <string name="month_shortest_january">s</string> + <string name="month_shortest_february">l</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">k</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">c</string> + <string name="month_shortest_july">l</string> + <string name="month_shortest_august">s</string> + <string name="month_shortest_september">w</string> + <string name="month_shortest_october">p</string> + <string name="month_shortest_november">l</string> + <string name="month_shortest_december">g</string> + + <string name="day_of_week_long_sunday">niedziela</string> + <string name="day_of_week_long_monday">poniedziałek</string> + <string name="day_of_week_long_tuesday">wtorek</string> + <string name="day_of_week_long_wednesday">środa</string> + <string name="day_of_week_long_thursday">czwartek</string> + <string name="day_of_week_long_friday">piątek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">niedz.</string> + <string name="day_of_week_medium_monday">pon.</string> + <string name="day_of_week_medium_tuesday">wt.</string> + <string name="day_of_week_medium_wednesday">śr.</string> + <string name="day_of_week_medium_thursday">czw.</string> + <string name="day_of_week_medium_friday">pt.</string> + <string name="day_of_week_medium_saturday">sob.</string> + + <string name="day_of_week_short_sunday">niedz.</string> + <string name="day_of_week_short_monday">pon.</string> + <string name="day_of_week_short_tuesday">wt.</string> + <string name="day_of_week_short_wednesday">śr.</string> + <string name="day_of_week_short_thursday">czw.</string> + <string name="day_of_week_short_friday">pt.</string> + <string name="day_of_week_short_saturday">sob.</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">W</string> + <string name="day_of_week_shortest_wednesday">Ś</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Wczoraj</string> + <string name="today">Dzisiaj</string> + <string name="tomorrow">Jutro</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d-%m-%Y</string> + <string name="numeric_date_format">dd-MM-yyyy</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d-%m-%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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> + <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, %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_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="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">%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">%3$s %2$s %1$s - %8$s %7$s %6$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 %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string> + <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, %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">%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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-pl/donottranslate-cldr.xml b/core/res/res/values-pl/donottranslate-cldr.xml new file mode 100644 index 0000000..4ad17bf --- /dev/null +++ b/core/res/res/values-pl/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">styczeń</string> + <string name="month_long_standalone_february">luty</string> + <string name="month_long_standalone_march">marzec</string> + <string name="month_long_standalone_april">kwiecień</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">czerwiec</string> + <string name="month_long_standalone_july">lipiec</string> + <string name="month_long_standalone_august">sierpień</string> + <string name="month_long_standalone_september">wrzesień</string> + <string name="month_long_standalone_october">październik</string> + <string name="month_long_standalone_november">listopad</string> + <string name="month_long_standalone_december">grudzień</string> + + <string name="month_long_january">stycznia</string> + <string name="month_long_february">lutego</string> + <string name="month_long_march">marca</string> + <string name="month_long_april">kwietnia</string> + <string name="month_long_may">maja</string> + <string name="month_long_june">czerwca</string> + <string name="month_long_july">lipca</string> + <string name="month_long_august">sierpnia</string> + <string name="month_long_september">września</string> + <string name="month_long_october">października</string> + <string name="month_long_november">listopada</string> + <string name="month_long_december">grudnia</string> + + <string name="month_medium_january">sty</string> + <string name="month_medium_february">lut</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">kwi</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">cze</string> + <string name="month_medium_july">lip</string> + <string name="month_medium_august">sie</string> + <string name="month_medium_september">wrz</string> + <string name="month_medium_october">paź</string> + <string name="month_medium_november">lis</string> + <string name="month_medium_december">gru</string> + + <string name="month_shortest_january">s</string> + <string name="month_shortest_february">l</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">k</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">c</string> + <string name="month_shortest_july">l</string> + <string name="month_shortest_august">s</string> + <string name="month_shortest_september">w</string> + <string name="month_shortest_october">p</string> + <string name="month_shortest_november">l</string> + <string name="month_shortest_december">g</string> + + <string name="day_of_week_long_sunday">niedziela</string> + <string name="day_of_week_long_monday">poniedziałek</string> + <string name="day_of_week_long_tuesday">wtorek</string> + <string name="day_of_week_long_wednesday">środa</string> + <string name="day_of_week_long_thursday">czwartek</string> + <string name="day_of_week_long_friday">piątek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">niedz.</string> + <string name="day_of_week_medium_monday">pon.</string> + <string name="day_of_week_medium_tuesday">wt.</string> + <string name="day_of_week_medium_wednesday">śr.</string> + <string name="day_of_week_medium_thursday">czw.</string> + <string name="day_of_week_medium_friday">pt.</string> + <string name="day_of_week_medium_saturday">sob.</string> + + <string name="day_of_week_short_sunday">niedz.</string> + <string name="day_of_week_short_monday">pon.</string> + <string name="day_of_week_short_tuesday">wt.</string> + <string name="day_of_week_short_wednesday">śr.</string> + <string name="day_of_week_short_thursday">czw.</string> + <string name="day_of_week_short_friday">pt.</string> + <string name="day_of_week_short_saturday">sob.</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">W</string> + <string name="day_of_week_shortest_wednesday">Ś</string> + <string name="day_of_week_shortest_thursday">C</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Wczoraj</string> + <string name="today">Dzisiaj</string> + <string name="tomorrow">Jutro</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d-%m-%Y</string> + <string name="numeric_date_format">dd-MM-yyyy</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d-%m-%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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> + <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, %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_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="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">%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">%3$s %2$s %1$s - %8$s %7$s %6$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 %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string> + <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, %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">%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> + <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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 50d245b..c6c9bd0 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Pozwala aplikacji zmieniać bieżącą konfigurację, na przykład lokalny lub globalny rozmiar czcionki."</string> <string name="permlab_restartPackages">"resetowanie innych aplikacji"</string> <string name="permdesc_restartPackages">"Pozwala aplikacji na wymuszenie ponownego uruchomienia innych aplikacji."</string> - <string name="permlab_setProcessForeground">"zapobieganie zatrzymaniu"</string> - <string name="permdesc_setProcessForeground">"Pozwala aplikacji na uruchamianie dowolnego procesu na pierwszym planie tak, że nie można go wyłączyć. Nigdy nie powinno być potrzebne normalnym aplikacjom."</string> <string name="permlab_forceBack">"wymuszanie zamknięcia aplikacji"</string> <string name="permdesc_forceBack">"Pozwala aplikacji na wymuszenie zamknięcia i cofnięcia dowolnej operacji działającej na pierwszym planie. Nigdy nie powinno być potrzebne normalnym aplikacjom."</string> <string name="permlab_dump">"pobieranie informacji o wewnętrznym stanie systemu"</string> <string name="permdesc_dump">"Pozwala aplikacjom na pobieranie informacji o wewnętrznym stanie systemu. Szkodliwe aplikacje mogą pobrać szeroką gamę osobistych i zabezpieczonych informacji, które normalnie nie powinny im być nigdy potrzebne."</string> - <string name="permlab_addSystemService">"publikowanie usług niskiego poziomu"</string> - <string name="permdesc_addSystemService">"Pozwala aplikacji na publikowanie własnych usług systemowych niskiego poziomu. Szkodliwe aplikacje mogą przejąć kontrolę nad systemem oraz wykraść lub uszkodzić znajdujące się w nim dane."</string> <string name="permlab_runSetActivityWatcher">"monitorowanie i kontrolowanie wszystkich uruchamianych aplikacji"</string> <string name="permdesc_runSetActivityWatcher">"Pozwala aplikacji na monitorowanie i kontrolowanie sposobu, w jaki w systemie uruchamiane są różne działania. Szkodliwe aplikacje mogą całkowicie przejąć system. Te uprawnienia potrzebne są tylko programistom, nigdy w przypadku normalnego wykorzystywania telefonu."</string> <string name="permlab_broadcastPackageRemoved">"wysyłanie transmisji informującej o usuniętym pakiecie"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Pozwala aplikacji na kontrolowanie maksymalnej liczby uruchamianych procesów. Nigdy nie wykorzystywane przez normalne aplikacje."</string> <string name="permlab_setAlwaysFinish">"zamykanie wszystkich aplikacji działających w tle"</string> <string name="permdesc_setAlwaysFinish">"Pozwala aplikacji na kontrolowanie, czy czynności są zawsze kończone, kiedy zaczynają działać w tle. Nigdy nie jest potrzebne normalnym aplikacjom."</string> - <string name="permlab_fotaUpdate">"automatyczne instalowanie aktualizacji systemu"</string> - <string name="permdesc_fotaUpdate">"Pozwala aplikacji na otrzymywanie powiadomień o oczekujących aktualizacjach systemu i uruchamianie ich instalacji. Szkodliwe aplikacje mogą to wykorzystać do uszkodzenia systemu za pomocą nieuwierzytelnionych aktualizacji lub ogólnie wpłynąć na proces aktualizowania."</string> <string name="permlab_batteryStats">"zmienianie statystyk dotyczących baterii"</string> <string name="permdesc_batteryStats">"Pozwala na zmianę zebranych statystyk dotyczących baterii. Nie do wykorzystania przez normalne aplikacje."</string> <string name="permlab_internalSystemWindow">"wyświetlanie nieuwierzytelnionych okien"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Hasło"</string> <string name="lockscreen_glogin_submit_button">"Zaloguj"</string> <string name="lockscreen_glogin_invalid_input">"Błędna nazwa użytkownika lub hasło."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Wyczyść powiadomienia"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"enter"</string> <string name="menu_delete_shortcut_label">"usuń"</string> <string name="search_go">"Szukaj"</string> - <string name="today">"Dzisiaj"</string> - <string name="yesterday">"Wczoraj"</string> - <string name="tomorrow">"Jutro"</string> <string name="oneMonthDurationPast">"1 miesiąc temu"</string> <string name="beforeOneMonthDurationPast">"Ponad 1 miesiąc temu"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"tygodni"</string> <string name="year">"rok"</string> <string name="years">"lat"</string> - <string name="sunday">"niedziela"</string> - <string name="monday">"poniedziałek"</string> - <string name="tuesday">"wtorek"</string> - <string name="wednesday">"środa"</string> - <string name="thursday">"czwartek"</string> - <string name="friday">"piątek"</string> - <string name="saturday">"sobota"</string> <string name="every_weekday">"W każdy dzień roboczy (pon–pt)"</string> <string name="daily">"Codziennie"</string> <string name="weekly">"Co tydzień w <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"Przepraszamy, ten film wideo nie nadaje się do przesyłania strumieniowego do tego urządzenia."</string> <string name="VideoView_error_text_unknown">"Niestety, nie można odtworzyć tego filmu wideo."</string> <string name="VideoView_error_button">"OK"</string> - <string name="am">"rano"</string> - <string name="pm">"po południu"</string> - <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"południe"</string> <string name="Noon">"Południe"</string> <string name="midnight">"północ"</string> <string name="Midnight">"Północ"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"niedziela"</string> - <string name="day_of_week_long_monday">"poniedziałek"</string> - <string name="day_of_week_long_tuesday">"wtorek"</string> - <string name="day_of_week_long_wednesday">"środa"</string> - <string name="day_of_week_long_thursday">"czwartek"</string> - <string name="day_of_week_long_friday">"piątek"</string> - <string name="day_of_week_long_saturday">"sobota"</string> - <string name="day_of_week_medium_sunday">"Nie"</string> - <string name="day_of_week_medium_monday">"Pon"</string> - <string name="day_of_week_medium_tuesday">"Wt"</string> - <string name="day_of_week_medium_wednesday">"Śro"</string> - <string name="day_of_week_medium_thursday">"Czw"</string> - <string name="day_of_week_medium_friday">"Pią"</string> - <string name="day_of_week_medium_saturday">"Sob"</string> - <string name="day_of_week_short_sunday">"Nd"</string> - <string name="day_of_week_short_monday">"Pn"</string> - <string name="day_of_week_short_tuesday">"Wt"</string> - <string name="day_of_week_short_wednesday">"Śr"</string> - <string name="day_of_week_short_thursday">"Czw"</string> - <string name="day_of_week_short_friday">"Pt"</string> - <string name="day_of_week_short_saturday">"So"</string> - <string name="day_of_week_shorter_sunday">"Nd"</string> - <string name="day_of_week_shorter_monday">"Pon"</string> - <string name="day_of_week_shorter_tuesday">"Wt"</string> - <string name="day_of_week_shorter_wednesday">"Śr"</string> - <string name="day_of_week_shorter_thursday">"Czw"</string> - <string name="day_of_week_shorter_friday">"Pt"</string> - <string name="day_of_week_shorter_saturday">"So"</string> - <string name="day_of_week_shortest_sunday">"Nd"</string> - <string name="day_of_week_shortest_monday">"Pon"</string> - <string name="day_of_week_shortest_tuesday">"Czw"</string> - <string name="day_of_week_shortest_wednesday">"Śr"</string> - <string name="day_of_week_shortest_thursday">"Czw"</string> - <string name="day_of_week_shortest_friday">"Pt"</string> - <string name="day_of_week_shortest_saturday">"Sob"</string> - <string name="month_long_january">"Styczeń"</string> - <string name="month_long_february">"Luty"</string> - <string name="month_long_march">"Marzec"</string> - <string name="month_long_april">"Kwiecień"</string> - <string name="month_long_may">"Maj"</string> - <string name="month_long_june">"Czerwiec"</string> - <string name="month_long_july">"Lipiec"</string> - <string name="month_long_august">"Sierpień"</string> - <string name="month_long_september">"Wrzesień"</string> - <string name="month_long_october">"Październik"</string> - <string name="month_long_november">"Listopad"</string> - <string name="month_long_december">"Grudzień"</string> - <string name="month_medium_january">"Sty"</string> - <string name="month_medium_february">"Lut"</string> - <string name="month_medium_march">"Mar"</string> - <string name="month_medium_april">"Kwi"</string> - <string name="month_medium_may">"Maj"</string> - <string name="month_medium_june">"Cze"</string> - <string name="month_medium_july">"Lip"</string> - <string name="month_medium_august">"Sie"</string> - <string name="month_medium_september">"Wrz"</string> - <string name="month_medium_october">"Paź"</string> - <string name="month_medium_november">"Lis"</string> - <string name="month_medium_december">"Gru"</string> - <string name="month_shortest_january">"Sty"</string> - <string name="month_shortest_february">"Lut"</string> - <string name="month_shortest_march">"Pon"</string> - <string name="month_shortest_april">"Kwi"</string> - <string name="month_shortest_may">"Maj"</string> - <string name="month_shortest_june">"Cze"</string> - <string name="month_shortest_july">"Lip"</string> - <string name="month_shortest_august">"Sie"</string> - <string name="month_shortest_september">"Wrz"</string> - <string name="month_shortest_october">"Paź"</string> - <string name="month_shortest_november">"Lis"</string> - <string name="month_shortest_december">"Gru"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Zaznacz wszystko"</string> diff --git a/core/res/res/values-pt-rBR/donottranslate-cldr.xml b/core/res/res/values-pt-rBR/donottranslate-cldr.xml new file mode 100644 index 0000000..4729055 --- /dev/null +++ b/core/res/res/values-pt-rBR/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janeiro</string> + <string name="month_long_standalone_february">fevereiro</string> + <string name="month_long_standalone_march">março</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">maio</string> + <string name="month_long_standalone_june">junho</string> + <string name="month_long_standalone_july">julho</string> + <string name="month_long_standalone_august">agosto</string> + <string name="month_long_standalone_september">setembro</string> + <string name="month_long_standalone_october">outubro</string> + <string name="month_long_standalone_november">novembro</string> + <string name="month_long_standalone_december">dezembro</string> + + <string name="month_long_january">janeiro</string> + <string name="month_long_february">fevereiro</string> + <string name="month_long_march">março</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">maio</string> + <string name="month_long_june">junho</string> + <string name="month_long_july">julho</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">setembro</string> + <string name="month_long_october">outubro</string> + <string name="month_long_november">novembro</string> + <string name="month_long_december">dezembro</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">fev</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">abr</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">set</string> + <string name="month_medium_october">out</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">segunda-feira</string> + <string name="day_of_week_long_tuesday">terça-feira</string> + <string name="day_of_week_long_wednesday">quarta-feira</string> + <string name="day_of_week_long_thursday">quinta-feira</string> + <string name="day_of_week_long_friday">sexta-feira</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">seg</string> + <string name="day_of_week_medium_tuesday">ter</string> + <string name="day_of_week_medium_wednesday">qua</string> + <string name="day_of_week_medium_thursday">qui</string> + <string name="day_of_week_medium_friday">sex</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">seg</string> + <string name="day_of_week_short_tuesday">ter</string> + <string name="day_of_week_short_wednesday">qua</string> + <string name="day_of_week_short_thursday">qui</string> + <string name="day_of_week_short_friday">sex</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">S</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">Q</string> + <string name="day_of_week_shortest_thursday">Q</string> + <string name="day_of_week_shortest_friday">S</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Ontem</string> + <string name="today">Hoje</string> + <string name="tomorrow">Amanhã</string> + + <string name="hour_minute_24">%-kh%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H'h'mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e de %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b de %Y</string> + <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, %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s de %2$s - %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 - %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 - %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 - %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 de %2$s de %4$s - %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 - %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 - %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 de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s de %2$s - %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 - %6$s, %8$s de %7$s de %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml new file mode 100644 index 0000000..f38a2d0 --- /dev/null +++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Janeiro</string> + <string name="month_long_standalone_february">Fevereiro</string> + <string name="month_long_standalone_march">Março</string> + <string name="month_long_standalone_april">Abril</string> + <string name="month_long_standalone_may">Maio</string> + <string name="month_long_standalone_june">Junho</string> + <string name="month_long_standalone_july">Julho</string> + <string name="month_long_standalone_august">Agosto</string> + <string name="month_long_standalone_september">Setembro</string> + <string name="month_long_standalone_october">Outubro</string> + <string name="month_long_standalone_november">Novembro</string> + <string name="month_long_standalone_december">Dezembro</string> + + <string name="month_long_january">Janeiro</string> + <string name="month_long_february">Fevereiro</string> + <string name="month_long_march">Março</string> + <string name="month_long_april">Abril</string> + <string name="month_long_may">Maio</string> + <string name="month_long_june">Junho</string> + <string name="month_long_july">Julho</string> + <string name="month_long_august">Agosto</string> + <string name="month_long_september">Setembro</string> + <string name="month_long_october">Outubro</string> + <string name="month_long_november">Novembro</string> + <string name="month_long_december">Dezembro</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Fev</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Abr</string> + <string name="month_medium_may">Mai</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Ago</string> + <string name="month_medium_september">Set</string> + <string name="month_medium_october">Out</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">segunda-feira</string> + <string name="day_of_week_long_tuesday">terça-feira</string> + <string name="day_of_week_long_wednesday">quarta-feira</string> + <string name="day_of_week_long_thursday">quinta-feira</string> + <string name="day_of_week_long_friday">sexta-feira</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">seg</string> + <string name="day_of_week_medium_tuesday">ter</string> + <string name="day_of_week_medium_wednesday">qua</string> + <string name="day_of_week_medium_thursday">qui</string> + <string name="day_of_week_medium_friday">sex</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">seg</string> + <string name="day_of_week_short_tuesday">ter</string> + <string name="day_of_week_short_wednesday">qua</string> + <string name="day_of_week_short_thursday">qui</string> + <string name="day_of_week_short_friday">sex</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">S</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">Q</string> + <string name="day_of_week_shortest_thursday">Q</string> + <string name="day_of_week_shortest_friday">S</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">Antes do meio-dia</string> + <string name="pm">Depois do meio-dia</string> + <string name="yesterday">Ontem</string> + <string name="today">Hoje</string> + <string name="tomorrow">Amanhã</string> + + <string name="hour_minute_24">%-kh%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H'h'mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e de %b de %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e de %b de %Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e de %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b de %Y</string> + <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, %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s de %2$s - %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 - %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 - %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 - %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 de %2$s de %4$s - %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 - %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 - %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 de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s de %2$s - %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 - %6$s, %8$s de %7$s de %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-pt/donottranslate-cldr.xml b/core/res/res/values-pt/donottranslate-cldr.xml new file mode 100644 index 0000000..4729055 --- /dev/null +++ b/core/res/res/values-pt/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">janeiro</string> + <string name="month_long_standalone_february">fevereiro</string> + <string name="month_long_standalone_march">março</string> + <string name="month_long_standalone_april">abril</string> + <string name="month_long_standalone_may">maio</string> + <string name="month_long_standalone_june">junho</string> + <string name="month_long_standalone_july">julho</string> + <string name="month_long_standalone_august">agosto</string> + <string name="month_long_standalone_september">setembro</string> + <string name="month_long_standalone_october">outubro</string> + <string name="month_long_standalone_november">novembro</string> + <string name="month_long_standalone_december">dezembro</string> + + <string name="month_long_january">janeiro</string> + <string name="month_long_february">fevereiro</string> + <string name="month_long_march">março</string> + <string name="month_long_april">abril</string> + <string name="month_long_may">maio</string> + <string name="month_long_june">junho</string> + <string name="month_long_july">julho</string> + <string name="month_long_august">agosto</string> + <string name="month_long_september">setembro</string> + <string name="month_long_october">outubro</string> + <string name="month_long_november">novembro</string> + <string name="month_long_december">dezembro</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">fev</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">abr</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">ago</string> + <string name="month_medium_september">set</string> + <string name="month_medium_october">out</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dez</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">domingo</string> + <string name="day_of_week_long_monday">segunda-feira</string> + <string name="day_of_week_long_tuesday">terça-feira</string> + <string name="day_of_week_long_wednesday">quarta-feira</string> + <string name="day_of_week_long_thursday">quinta-feira</string> + <string name="day_of_week_long_friday">sexta-feira</string> + <string name="day_of_week_long_saturday">sábado</string> + + <string name="day_of_week_medium_sunday">dom</string> + <string name="day_of_week_medium_monday">seg</string> + <string name="day_of_week_medium_tuesday">ter</string> + <string name="day_of_week_medium_wednesday">qua</string> + <string name="day_of_week_medium_thursday">qui</string> + <string name="day_of_week_medium_friday">sex</string> + <string name="day_of_week_medium_saturday">sáb</string> + + <string name="day_of_week_short_sunday">dom</string> + <string name="day_of_week_short_monday">seg</string> + <string name="day_of_week_short_tuesday">ter</string> + <string name="day_of_week_short_wednesday">qua</string> + <string name="day_of_week_short_thursday">qui</string> + <string name="day_of_week_short_friday">sex</string> + <string name="day_of_week_short_saturday">sáb</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">S</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">Q</string> + <string name="day_of_week_shortest_thursday">Q</string> + <string name="day_of_week_shortest_friday">S</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Ontem</string> + <string name="today">Hoje</string> + <string name="tomorrow">Amanhã</string> + + <string name="hour_minute_24">%-kh%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H'h'mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e de %B de %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d/%m/%Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d/%m/%Y</string> + <string name="month_day">%-e de %B</string> + <string name="month">%-B</string> + <string name="month_year">%B de %Y</string> + <string name="abbrev_month_day">%-e de %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b de %Y</string> + <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, %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="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">%1$s %2$s</string> + <string name="same_year_md1_md2">%3$s de %2$s - %8$s de %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s - %10$s %8$s de %7$s</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s de %2$s - %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 - %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 - %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 - %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 de %2$s de %4$s - %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 - %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 - %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 de %2$s - %6$s, %8$s de %7$s</string> + <string name="same_year_mdy1_mdy2">%3$s de %2$s - %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 - %6$s, %8$s de %7$s de %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml new file mode 100644 index 0000000..c5c5bbb --- /dev/null +++ b/core/res/res/values-pt/strings.xml @@ -0,0 +1,793 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- 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. +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="byteShort">"B"</string> + <string name="kilobyteShort">"KB"</string> + <string name="megabyteShort">"MB"</string> + <string name="gigabyteShort">"GB"</string> + <string name="terabyteShort">"TB"</string> + <string name="petabyteShort">"PB"</string> + <string name="untitled">"<sem título>"</string> + <string name="ellipsis">"…"</string> + <string name="emptyPhoneNumber">"(Nenhum número de telefone)"</string> + <string name="unknownName">"(Desconhecido)"</string> + <string name="defaultVoiceMailAlphaTag">"Correio de voz"</string> + <string name="defaultMsisdnAlphaTag">"MSISDN1"</string> + <string name="mmiError">"Problema de conexão ou código MMI inválido."</string> + <string name="serviceEnabled">"O serviço foi ativado."</string> + <string name="serviceEnabledFor">"O serviço foi ativado para:"</string> + <string name="serviceDisabled">"O serviço foi desativado."</string> + <string name="serviceRegistered">"O registro foi bem-sucedido."</string> + <string name="serviceErased">"Exclusão bem-sucedida."</string> + <string name="passwordIncorrect">"Senha incorreta"</string> + <string name="mmiComplete">"MMI completo."</string> + <string name="badPin">"O PIN antigo digitado não está correto."</string> + <string name="badPuk">"O PUK digitado não está correto."</string> + <string name="mismatchPin">"Os PINs digitados não correspondem."</string> + <string name="invalidPin">"Digite um PIN com 4 a 8 números."</string> + <string name="needPuk">"Seu cartão SIM está bloqueado pelo código PUK. Digite o PUK para desbloqueá-lo."</string> + <string name="needPuk2">"Digite PUK2 para desbloquear cartão SIM."</string> + <string name="ClipMmi">"ID do chamador"</string> + <string name="ClirMmi">"ID de quem realiza a chamada"</string> + <string name="CfMmi">"Transferência de chamada"</string> + <string name="CwMmi">"Chamada em espera"</string> + <string name="BaMmi">"Bloqueio de chamada"</string> + <string name="PwdMmi">"Alteração da senha"</string> + <string name="PinMmi">"Alteração de PIN"</string> + <!-- no translation found for CnipMmi (3110534680557857162) --> + <skip /> + <!-- no translation found for CnirMmi (3062102121430548731) --> + <skip /> + <!-- no translation found for ThreeWCMmi (9051047170321190368) --> + <skip /> + <!-- no translation found for RuacMmi (7827887459138308886) --> + <skip /> + <!-- no translation found for CndMmi (3116446237081575808) --> + <skip /> + <!-- no translation found for DndMmi (1265478932418334331) --> + <skip /> + <string name="CLIRDefaultOnNextCallOn">"ID do chamador assume o padrão de restrito. Próxima chamada: restrita"</string> + <string name="CLIRDefaultOnNextCallOff">"ID do chamador assume o padrão de restrito. Próxima chamada: não restrita"</string> + <string name="CLIRDefaultOffNextCallOn">"ID do chamador assume o padrão de não restrito. Próxima chamada: restrita"</string> + <string name="CLIRDefaultOffNextCallOff">"ID do chamador assume o padrão de não restrito. Próxima chamada: não restrita"</string> + <string name="serviceNotProvisioned">"Serviço não fornecido"</string> + <string name="CLIRPermanent">"A configuração da ID do chamador não pode ser alterada."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> + <string name="serviceClassVoice">"Voz"</string> + <string name="serviceClassData">"Dados"</string> + <string name="serviceClassFAX">"FAX"</string> + <string name="serviceClassSMS">"SMS"</string> + <string name="serviceClassDataAsync">"Assíncrono"</string> + <string name="serviceClassDataSync">"Sincronizar"</string> + <string name="serviceClassPacket">"Pacote"</string> + <string name="serviceClassPAD">"PAD"</string> + <!-- no translation found for roamingText0 (7170335472198694945) --> + <skip /> + <!-- no translation found for roamingText1 (5314861519752538922) --> + <skip /> + <!-- no translation found for roamingText2 (8969929049081268115) --> + <skip /> + <!-- no translation found for roamingText3 (5148255027043943317) --> + <skip /> + <!-- no translation found for roamingText4 (8808456682550796530) --> + <skip /> + <!-- no translation found for roamingText5 (7604063252850354350) --> + <skip /> + <!-- no translation found for roamingText6 (2059440825782871513) --> + <skip /> + <!-- no translation found for roamingText7 (7112078724097233605) --> + <skip /> + <!-- no translation found for roamingText8 (5989569778604089291) --> + <skip /> + <!-- no translation found for roamingText9 (7969296811355152491) --> + <skip /> + <!-- no translation found for roamingText10 (3992906999815316417) --> + <skip /> + <!-- no translation found for roamingText11 (4154476854426920970) --> + <skip /> + <!-- no translation found for roamingText12 (1189071119992726320) --> + <skip /> + <!-- no translation found for roamingTextSearching (8360141885972279963) --> + <skip /> + <string name="cfTemplateNotForwarded">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não transferido"</string> + <string name="cfTemplateForwarded">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> + <string name="cfTemplateForwardedTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string> + <string name="cfTemplateRegistered">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não transferido"</string> + <string name="cfTemplateRegisteredTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não transferido"</string> + <!-- no translation found for fcComplete (3118848230966886575) --> + <skip /> + <!-- no translation found for fcError (3327560126588500777) --> + <skip /> + <string name="httpErrorOk">"OK"</string> + <string name="httpError">"A página da web contém um erro."</string> + <string name="httpErrorLookup">"Não foi possível encontrar o URL."</string> + <string name="httpErrorUnsupportedAuthScheme">"O esquema de autenticação não é suportado."</string> + <string name="httpErrorAuth">"Falha na autenticação."</string> + <string name="httpErrorProxyAuth">"Falha na autenticação pelo servidor proxy."</string> + <string name="httpErrorConnect">"Falha na conexão com o servidor."</string> + <string name="httpErrorIO">"Falha de comunicação com o servidor. Tente novamente mais tarde."</string> + <string name="httpErrorTimeout">"Tempo limite da conexão com o servidor esgotado."</string> + <string name="httpErrorRedirectLoop">"A página contém muitos redirecionamentos do servidor."</string> + <string name="httpErrorUnsupportedScheme">"O protocolo não é suportado."</string> + <string name="httpErrorFailedSslHandshake">"Não foi possível estabelecer uma conexão segura."</string> + <string name="httpErrorBadUrl">"A página não pode ser aberta, pois o URL é inválido."</string> + <string name="httpErrorFile">"Não foi possível acessar o arquivo."</string> + <string name="httpErrorFileNotFound">"O arquivo solicitado não foi encontrado."</string> + <string name="httpErrorTooManyRequests">"Muitas solicitações sendo processadas. Tente novamente mais tarde."</string> + <string name="contentServiceSync">"Sincronizar"</string> + <string name="contentServiceSyncNotificationTitle">"Sincronizar"</string> + <string name="contentServiceTooManyDeletesNotificationDesc">"Muitas exclusões do <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string> + <string name="low_memory">"O armazenamento do telefone está cheio! Exclua alguns arquivos para liberar espaço."</string> + <string name="me">"Eu"</string> + <string name="power_dialog">"Opções do telefone"</string> + <string name="silent_mode">"Modo silencioso"</string> + <string name="turn_on_radio">"Ativar rede sem fio"</string> + <string name="turn_off_radio">"Desativar a rede sem fio"</string> + <string name="screen_lock">"Bloqueio de tela"</string> + <string name="power_off">"Desligar"</string> + <string name="shutdown_progress">"Desligando…"</string> + <string name="shutdown_confirm">"Seu telefone desligará"</string> + <string name="no_recent_tasks">"Nenhum aplicativo recente."</string> + <string name="global_actions">"Opções do telefone"</string> + <string name="global_action_lock">"Bloqueio de tela"</string> + <string name="global_action_power_off">"Desligar"</string> + <string name="global_action_toggle_silent_mode">"Modo silencioso"</string> + <string name="global_action_silent_mode_on_status">"O som está DESLIGADO"</string> + <string name="global_action_silent_mode_off_status">"O som está ATIVADO"</string> + <!-- no translation found for global_actions_toggle_airplane_mode (5884330306926307456) --> + <skip /> + <!-- no translation found for global_actions_airplane_mode_on_status (2719557982608919750) --> + <skip /> + <!-- no translation found for global_actions_airplane_mode_off_status (5075070442854490296) --> + <skip /> + <string name="safeMode">"Modo de segurança"</string> + <!-- no translation found for android_system_label (6577375335728551336) --> + <skip /> + <string name="permgrouplab_costMoney">"Serviços que custam dinheiro"</string> + <string name="permgroupdesc_costMoney">"Permite que os aplicativos façam coisas que podem custar dinheiro."</string> + <string name="permgrouplab_messages">"Suas mensagens"</string> + <string name="permgroupdesc_messages">"Ler e gravar suas mensagens SMS, e-mail e outras mensagens."</string> + <string name="permgrouplab_personalInfo">"Suas informações pessoais"</string> + <string name="permgroupdesc_personalInfo">"Acesso direto aos seus contatos e calendário armazenados no telefone."</string> + <string name="permgrouplab_location">"Sua localização"</string> + <string name="permgroupdesc_location">"Monitore seu local físico"</string> + <string name="permgrouplab_network">"Comunicação de rede"</string> + <string name="permgroupdesc_network">"Permite que os aplicativos acessem diversos recursos de rede."</string> + <string name="permgrouplab_accounts">"Suas contas do Google"</string> + <string name="permgroupdesc_accounts">"Acesse as contas do Google disponíveis."</string> + <string name="permgrouplab_hardwareControls">"Controles de hardware"</string> + <string name="permgroupdesc_hardwareControls">"Acesso direto ao hardware no handset."</string> + <string name="permgrouplab_phoneCalls">"Chamadas telefônicas"</string> + <string name="permgroupdesc_phoneCalls">"Monitorar, registrar e processar chamadas telefônicas."</string> + <string name="permgrouplab_systemTools">"Ferramentas do sistema"</string> + <string name="permgroupdesc_systemTools">"Acesso de nível inferior e controle do sistema."</string> + <string name="permgrouplab_developmentTools">"Ferramentas de desenvolvimento"</string> + <string name="permgroupdesc_developmentTools">"Recursos necessários apenas aos desenvolvedores de aplicativo."</string> + <!-- no translation found for permgrouplab_storage (1971118770546336966) --> + <skip /> + <!-- no translation found for permgroupdesc_storage (9203302214915355774) --> + <skip /> + <string name="permlab_statusBar">"desativar ou modificar a barra de status"</string> + <string name="permdesc_statusBar">"Permite que os aplicativos desativem a barra de status ou adicionem e removam ícones do sistema."</string> + <string name="permlab_expandStatusBar">"expandir/recolher barra de status"</string> + <string name="permdesc_expandStatusBar">"Permite que um aplicativo expanda ou recolha a barra de status."</string> + <string name="permlab_processOutgoingCalls">"Interceptar chamadas realizadas"</string> + <string name="permdesc_processOutgoingCalls">"Permite que aplicativos processem chamadas realizadas e alterem o número a ser discado. Aplicativos maliciosos podem monitorar, redirecionar ou impedir chamadas realizadas."</string> + <string name="permlab_receiveSms">"receber SMS"</string> + <string name="permdesc_receiveSms">"Permite que o aplicativo receba e processe mensagens SMS. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você."</string> + <string name="permlab_receiveMms">"receber MMS"</string> + <string name="permdesc_receiveMms">"Permite que o aplicativo receba e processe mensagens MMS. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você."</string> + <string name="permlab_sendSms">"enviar mensagens SMS"</string> + <string name="permdesc_sendSms">"Permite que os aplicativos enviem mensagens SMS. Os aplicativos maliciosos podem causar prejuízo financeiro a você ao enviar mensagens sem a sua confirmação."</string> + <string name="permlab_readSms">"ler SMS ou MMS"</string> + <string name="permdesc_readSms">"Permite que um aplicativo leia mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem ler suas mensagens confidenciais."</string> + <string name="permlab_writeSms">"editar SMS ou MMS"</string> + <string name="permdesc_writeSms">"Permite que um aplicativo grave mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem excluir suas mensagens."</string> + <string name="permlab_receiveWapPush">"receber WAP"</string> + <string name="permdesc_receiveWapPush">"Permite que o aplicativo receba e processe mensagens WAP. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você."</string> + <string name="permlab_getTasks">"recuperar aplicativos em execução"</string> + <string name="permdesc_getTasks">"Permite que os aplicativos recuperem informações sobre as tarefas em execução no momento ou recentemente. Pode permitir que aplicativos maliciosos descubram informações particulares sobre outros aplicativos."</string> + <string name="permlab_reorderTasks">"reorganizar os aplicativos em execução"</string> + <string name="permdesc_reorderTasks">"Permite que um aplicativo mova as tarefas para o primeiro ou segundo plano. Os aplicativos maliciosos podem forçar sua permanência no primeiro plano sem o seu controle."</string> + <string name="permlab_setDebugApp">"ativar depuração do aplicativo"</string> + <string name="permdesc_setDebugApp">"Permite que um aplicativo ative a depuração de outro aplicativo. Aplicativos maliciosos podem usar isso para encerrar outros aplicativos."</string> + <string name="permlab_changeConfiguration">"alterar as configurações da sua IU"</string> + <string name="permdesc_changeConfiguration">"Permite que um aplicativo mude a configuração atual, como a localidade ou o tamanho geral de fonte."</string> + <string name="permlab_restartPackages">"reiniciar outros aplicativos"</string> + <string name="permdesc_restartPackages">"Permite que um aplicativo reinicie outros aplicativos forçosamente."</string> + <string name="permlab_forceBack">"forçar fechamento do aplicativo"</string> + <string name="permdesc_forceBack">"Permite que um aplicativo force qualquer atividade que esteja em primeiro plano a fechar e voltar. Normalmente não é necessário para aplicativos normais."</string> + <string name="permlab_dump">"recuperar estado interno do sistema"</string> + <string name="permdesc_dump">"Permite que um aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem recuperar um ampla variedade de informações privadas e seguras, as quais não deveriam precisar normalmente."</string> + <!-- no translation found for permlab_shutdown (7185747824038909016) --> + <skip /> + <!-- no translation found for permdesc_shutdown (7046500838746291775) --> + <skip /> + <!-- no translation found for permlab_stopAppSwitches (4138608610717425573) --> + <skip /> + <!-- no translation found for permdesc_stopAppSwitches (3857886086919033794) --> + <skip /> + <string name="permlab_runSetActivityWatcher">"monitorar e controle toda inicialização de aplicativo"</string> + <string name="permdesc_runSetActivityWatcher">"Permite que um aplicativo monitore e controle como o sistema inicia as atividades. Os aplicativos maliciosos podem comprometer completamente o sistema. Esta permissão é necessária apenas para desenvolvimento, nunca para uso normal do telefone."</string> + <string name="permlab_broadcastPackageRemoved">"enviar transmissão de pacote removido"</string> + <string name="permdesc_broadcastPackageRemoved">"Permite que um aplicativo transmita uma notificação de que o pacote de um aplicativo foi removido. Aplicativos maliciosos podem usar isso para encerrar outro aplicativo em execução."</string> + <string name="permlab_broadcastSmsReceived">"enviar transmissão de SMS recebido"</string> + <string name="permdesc_broadcastSmsReceived">"Permite que um aplicativo transmita uma notificação de que uma mensagem SMS foi recebida. Aplicativos maliciosos podem usar isso para forjar o recebimento de mensagens SMS."</string> + <string name="permlab_broadcastWapPush">"enviar transmissão de WAP-PUSH recebido"</string> + <string name="permdesc_broadcastWapPush">"Permite que um aplicativo transmita uma notificação de que uma mensagem WAP PUSH foi recebida. Aplicativos maliciosos podem usar isso para forjar o recebimento de uma mensagem MMS ou substituir silenciosamente o conteúdo de qualquer página da web por variantes maliciosas."</string> + <string name="permlab_setProcessLimit">"limitar o número de processos em execução"</string> + <string name="permdesc_setProcessLimit">"Permite que um aplicativo controle o número máximo de processos que serão executados. Nunca é necessário para aplicativos normais."</string> + <string name="permlab_setAlwaysFinish">"fazer todos os aplicativos em segundo plano fechar"</string> + <string name="permdesc_setAlwaysFinish">"Permite que um aplicativo controle se as atividades são sempre concluídas assim que vão para o segundo plano. Nunca é necessário para aplicativos normais."</string> + <string name="permlab_batteryStats">"Modificar as estatísticas da bateria"</string> + <string name="permdesc_batteryStats">"Permite a modificação das estatísticas coletadas sobre a bateria. Não deve ser usado em aplicativos normais."</string> + <!-- no translation found for permlab_backup (470013022865453920) --> + <skip /> + <!-- no translation found for permdesc_backup (2305432853944929371) --> + <skip /> + <string name="permlab_internalSystemWindow">"exibir janelas não autorizadas"</string> + <string name="permdesc_internalSystemWindow">"Permite a criação de janelas que devem ser usadas pela interface de usuário do sistema interno. Normalmente não é necessário para aplicativos normais."</string> + <string name="permlab_systemAlertWindow">"exibir alertas do nível do sistema"</string> + <string name="permdesc_systemAlertWindow">"Permite que um aplicativo mostre janelas de alerta do sistema. Aplicativos maliciosos podem assumir o controle de toda a tela do telefone."</string> + <string name="permlab_setAnimationScale">"modificar a velocidade de animação global"</string> + <string name="permdesc_setAnimationScale">"Permite que um aplicativo altere a velocidade de animação global (animações mais rápidas ou mais lentas) a qualquer momento."</string> + <string name="permlab_manageAppTokens">"gerenciar os símbolos do aplicativo"</string> + <string name="permdesc_manageAppTokens">"Permite que um aplicativo crie e gerencie seus próprio símbolos, ignorando a ordem-Z (Z-ordering). Normalmente não é necessário para aplicativos normais."</string> + <string name="permlab_injectEvents">"pressionar as teclas e os botões de controle"</string> + <string name="permdesc_injectEvents">"Permite que um aplicativo proporcione seus próprios eventos de entrada (pressionamentos de tecla etc.) a outros aplicativos. Aplicativos maliciosos podem usar isso para assumir o controle do telefone."</string> + <string name="permlab_readInputState">"registrar o que você digita e as ações que executa"</string> + <string name="permdesc_readInputState">"Permite que os aplicativos observem as teclas que você pressiona ao interagir com outro aplicativo (como ao digitar uma senha). Normalmente não é necessário para aplicativos normais."</string> + <string name="permlab_bindInputMethod">"aderir a um método de entrada"</string> + <string name="permdesc_bindInputMethod">"Permite que o portador se vincule à interface de nível superior de um método de entrada. Normalmente não é necessário em aplicativos normais."</string> + <string name="permlab_setOrientation">"alterar orientação da tela"</string> + <string name="permdesc_setOrientation">"Permite que um aplicativo altere a rotação da tela a qualquer momento. Normalmente não é necessário para aplicativos normais."</string> + <string name="permlab_signalPersistentProcesses">"enviar sinais de Linux aos aplicativos"</string> + <string name="permdesc_signalPersistentProcesses">"Permite que o aplicativo solicite que o sinal fornecido seja enviado a todos os processos persistentes."</string> + <string name="permlab_persistentActivity">"fazer com que o aplicativo execute sempre"</string> + <string name="permdesc_persistentActivity">"Permite que um aplicativo torne partes dele mesmo persistentes, para que o sistema não possa usá-lo para outros aplicativos."</string> + <string name="permlab_deletePackages">"excluir aplicativos"</string> + <string name="permdesc_deletePackages">"Permite que um aplicativo exclua pacotes do Android. Aplicativos maliciosos podem usar isso para excluir aplicativos importantes."</string> + <string name="permlab_clearAppUserData">"excluir os dados de outros aplicativos"</string> + <string name="permdesc_clearAppUserData">"Permite que um aplicativo limpe os dados do usuário."</string> + <string name="permlab_deleteCacheFiles">"excluir o cache de outros aplicativos"</string> + <string name="permdesc_deleteCacheFiles">"Permite que um aplicativo exclua arquivos armazenados em cache."</string> + <string name="permlab_getPackageSize">"medir o espaço de armazenamento do aplicativo"</string> + <string name="permdesc_getPackageSize">"Permite que um aplicativo recupere seu código, dados e tamanho de cache"</string> + <string name="permlab_installPackages">"instalar os aplicativos diretamente"</string> + <string name="permdesc_installPackages">"Permite que um aplicativo instale pacotes novos ou atualizados do Android. Aplicativos maliciosos podem usar isso para adicionar novos aplicativos com permissões aleatórias avançadas."</string> + <string name="permlab_clearAppCache">"excluir todos os dados do cache do aplicativo"</string> + <string name="permdesc_clearAppCache">"Permite que um aplicativo libere espaço de armazenamento do telefone excluindo arquivos no diretório de cache do aplicativo. O acesso é normalmente restrito ao processo do sistema."</string> + <string name="permlab_readLogs">"ler arquivos do registro do sistema"</string> + <string name="permdesc_readLogs">"Permite que um aplicativo leia os diversos arquivos de registro do sistema. Isso permite que ele descubra informações gerais sobre o que você está fazendo com o telefone, mas esses arquivos não devem conter informações pessoais ou privadas."</string> + <string name="permlab_diagnostic">"ler/gravar em recursos que pertencem ao diagnóstico"</string> + <string name="permdesc_diagnostic">"Permite que um aplicativo leia e grave em qualquer recurso que pertença ao grupo diag; por exemplo, arquivos em /dev. Isso poderia afetar a estabilidade e a segurança do sistema. Por isso, SÓ deve ser usado para diagnósticos específicos do hardware pelo fabricante ou operador."</string> + <string name="permlab_changeComponentState">"ativar ou desativar componentes do aplicativo"</string> + <string name="permdesc_changeComponentState">"Permite que um aplicativo altere a ativação ou desativação de um componente de outro aplicativo. Aplicativos maliciosos podem usar isso para desativar recursos importantes do telefone. É preciso ter permissão e cuidado no uso, pois é possível deixar os componentes do aplicativo em um estado inutilizável, inconsistente ou instável."</string> + <string name="permlab_setPreferredApplications">"definir aplicativos preferidos"</string> + <string name="permdesc_setPreferredApplications">"Permite que um aplicativo modifique seus aplicativos preferidos. Isso pode permitir que aplicativos maliciosos alterem silenciosamente os aplicativos em execução, falsificando seus aplicativos existentes para coletar seus dados privados."</string> + <string name="permlab_writeSettings">"modificar configurações globais do sistema"</string> + <string name="permdesc_writeSettings">"Permite que um aplicativo modifique os dados da configuração do sistema. Aplicativos maliciosos podem corromper a configuração do sistema."</string> + <string name="permlab_writeSecureSettings">"modificar configurações de segurança do sistema"</string> + <string name="permdesc_writeSecureSettings">"Permite que um aplicativo modifique os dados das configurações de segurança dos sistemas. Não deve ser usado em aplicativos normais."</string> + <string name="permlab_writeGservices">"modificar o mapa de serviços do Google"</string> + <string name="permdesc_writeGservices">"Permite que um aplicativo modifique o mapa de serviços do Google. Não deve ser usado em aplicativos normais."</string> + <string name="permlab_receiveBootCompleted">"iniciar automaticamente na inicialização"</string> + <string name="permdesc_receiveBootCompleted">"Permite que um aplicativo se inicie assim que o sistema termina de inicializar. Isso pode causar uma demora na inicialização do telefone e faz com que todo o telefone fique mais lento pela execução contínua do aplicativo."</string> + <string name="permlab_broadcastSticky">"enviar transmissão complexa"</string> + <string name="permdesc_broadcastSticky">"Permite que um aplicativo envie transmissões persistentes, as quais permanecem após o término da transmissão. Aplicativos maliciosos podem tornar o telefone lento ou instável fazendo com que use muita memória."</string> + <string name="permlab_readContacts">"ler dados de contato"</string> + <string name="permdesc_readContacts">"Permite que um aplicativo leia todos os dados de contato (endereço) armazenados no telefone. Aplicativos maliciosos podem usar isso para enviar seus dados a outras pessoas."</string> + <string name="permlab_writeContacts">"gravar dados de contato"</string> + <string name="permdesc_writeContacts">"Permite que um aplicativo modifique os dados de contato (endereço) armazenados no telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato."</string> + <string name="permlab_writeOwnerData">"gravar dados do proprietário"</string> + <string name="permdesc_writeOwnerData">"Permite que um aplicativo modifique os dados do proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do proprietário."</string> + <string name="permlab_readOwnerData">"ler dados do proprietário"</string> + <string name="permdesc_readOwnerData">"Permite que um aplicativo leia os dados do proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para ler os dados do proprietário."</string> + <string name="permlab_readCalendar">"ler os dados do calendário"</string> + <string name="permdesc_readCalendar">"Permite que um aplicativo leia todos os eventos de calendário armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar os eventos do seu calendário a outras pessoas."</string> + <string name="permlab_writeCalendar">"gravar dados do calendário"</string> + <string name="permdesc_writeCalendar">"Permite que um aplicativo modifique os eventos do calendário armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato."</string> + <string name="permlab_accessMockLocation">"imitar fontes de localização para teste"</string> + <string name="permdesc_accessMockLocation">"Criar imitação de fontes de localização para teste. Os aplicativos maliciosos podem usar isso para sobrescrever o local e/ou status retornado pelas fontes de localização reais como GPS ou provedores de rede."</string> + <string name="permlab_accessLocationExtraCommands">"acessar comandos extra do provedor de localização"</string> + <string name="permdesc_accessLocationExtraCommands">"Acessar comandos extra de fornecedor de localização. Aplicativos maliciosos podem usar isso para interferir com a operação do GPS ou com outras fontes de localização."</string> + <!-- no translation found for permlab_installLocationProvider (6578101199825193873) --> + <skip /> + <!-- no translation found for permdesc_installLocationProvider (5449175116732002106) --> + <skip /> + <string name="permlab_accessFineLocation">"Localização precisa (GPS)"</string> + <string name="permdesc_accessFineLocation">"Acesse fontes de localização precisa como o sistema GPS (Global Positioning System) no telefone, quando estiver disponível. Aplicativos maliciosos podem usar isso para determinar onde você está e também pode consumir energia da bateria."</string> + <string name="permlab_accessCoarseLocation">"Local inadequado (com base na rede)"</string> + <string name="permdesc_accessCoarseLocation">"Acessar fontes de localização aproximada como o banco de dados de rede de celular para determinar a localização aproximada de um telefone, quando houver disponibilidade. Aplicativos maliciosos podem usar isso para determinar sua localização aproximada."</string> + <string name="permlab_accessSurfaceFlinger">"acessar SurfaceFlinger"</string> + <string name="permdesc_accessSurfaceFlinger">"Permite que o aplicativo use os recursos de nível inferior do SurfaceFlinger."</string> + <string name="permlab_readFrameBuffer">"ler buffer do quadro"</string> + <string name="permdesc_readFrameBuffer">"Permite que o aplicativo leia o conteúdo do buffer do quadro."</string> + <string name="permlab_modifyAudioSettings">"alterar as configurações do seu áudio"</string> + <string name="permdesc_modifyAudioSettings">"Permite que o aplicativo modifique as configurações de áudio globais como volume e roteamento."</string> + <string name="permlab_recordAudio">"gravar áudio"</string> + <string name="permdesc_recordAudio">"Permite que o aplicativo acesso o caminho do registro de áudio."</string> + <string name="permlab_camera">"tirar fotos"</string> + <string name="permdesc_camera">"Permite que o aplicativo tire fotos com a câmera. Isso permite que o aplicativo colete imagens exibidas pela câmera a qualquer momento."</string> + <string name="permlab_brick">"desativar permanentemente o telefone"</string> + <string name="permdesc_brick">"Permite que o aplicativo desative todo o telefone permanentemente. Isso é muito perigoso."</string> + <string name="permlab_reboot">"forçar reinicializarão do telefone"</string> + <string name="permdesc_reboot">"Permite que o aplicativo force a reinicialização do telefone."</string> + <string name="permlab_mount_unmount_filesystems">"montar e desmontar sistemas de arquivos"</string> + <string name="permdesc_mount_unmount_filesystems">"Permite que o aplicativo monte e desmonte sistemas de arquivos para armazenamento removível."</string> + <!-- no translation found for permlab_mount_format_filesystems (5523285143576718981) --> + <skip /> + <!-- no translation found for permdesc_mount_format_filesystems (574060044906047386) --> + <skip /> + <string name="permlab_vibrate">"controlar vibrador"</string> + <string name="permdesc_vibrate">"Permite que o aplicativo controle o vibrador."</string> + <string name="permlab_flashlight">"controlar lanterna"</string> + <string name="permdesc_flashlight">"Permite que o aplicativo controle a lanterna."</string> + <string name="permlab_hardware_test">"testar hardware"</string> + <string name="permdesc_hardware_test">"Permite que o aplicativo controle diversos periféricos para teste de hardware."</string> + <string name="permlab_callPhone">"chamar números de telefone diretamente"</string> + <string name="permdesc_callPhone">"Permite que o aplicativo chame números de telefone sem sua intervenção. Aplicativos maliciosos podem causar a aparição de chamadas inesperadas na conta do seu telefone. Observe que isso não permite que o aplicativo ligue para números de emergência."</string> + <string name="permlab_callPrivileged">"chamar quaisquer números de telefone diretamente"</string> + <string name="permdesc_callPrivileged">"Permite que o aplicativo chame qualquer número de telefone, incluindo números de emergência, sem sua intervenção. Aplicativos maliciosos podem fazer chamadas desnecessárias e ilegais para serviços de emergência."</string> + <string name="permlab_locationUpdates">"controlar notificações de atualização de localização"</string> + <string name="permdesc_locationUpdates">"Permite a ativação/desativação das notificações sobre atualização de localização pelo rádio. Não deve ser usado em aplicativos normais."</string> + <string name="permlab_checkinProperties">"acessar propriedades de verificação"</string> + <string name="permdesc_checkinProperties">"Permite acesso de leitura/gravação às propriedades enviadas pelo serviço de verificação. Não deve ser usado em aplicativos normais."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> + <string name="permlab_modifyPhoneState">"modificar estado do telefone"</string> + <string name="permdesc_modifyPhoneState">"Permite que o aplicativo controle os recursos do telefone do dispositivo. Um aplicativo com essa permissão pode alternar entre redes, ligar e desligar o rádio e executar ações parecidas sem o notificar."</string> + <string name="permlab_readPhoneState">"ler estado do telefone"</string> + <string name="permdesc_readPhoneState">"Permite que o aplicativo acesse os recursos do telefone do aparelho. Um aplicativo com essa permissão pode determinar o número deste telefone, se uma chamada está ativa, o número com o qual está chamada está conectada e outras coisas semelhantes."</string> + <string name="permlab_wakeLock">"impedir que o telefone entre em repouso"</string> + <string name="permdesc_wakeLock">"Permite que um aplicativo impeça o telefone de entrar em repouso."</string> + <string name="permlab_devicePower">"ligar ou desligar o telefone"</string> + <string name="permdesc_devicePower">"Permite que o aplicativo ligue ou desligue o telefone."</string> + <string name="permlab_factoryTest">"executar no modo de teste de fábrica"</string> + <string name="permdesc_factoryTest">"Executar como um teste de fabricante de nível inferior, permitindo o acesso completo ao hardware do telefone. Disponível apenas quando um telefone está executando no modo de teste de fábrica."</string> + <string name="permlab_setWallpaper">"definir papel de parede"</string> + <string name="permdesc_setWallpaper">"Permite que o aplicativo defina o papel de parede do sistema."</string> + <string name="permlab_setWallpaperHints">"definir dicas de tamanho de papel de parede"</string> + <string name="permdesc_setWallpaperHints">"Permite que o aplicativo defina as dicas de tamanho do papel de parede do sistema."</string> + <string name="permlab_masterClear">"reiniciar o sistema com o padrão de fábrica"</string> + <string name="permdesc_masterClear">"Permite que um aplicativo reinicie completamente o sistema com suas configurações de fábrica, apagando todos os dados, configuração e aplicativos instalados."</string> + <string name="permlab_setTimeZone">"definir fuso horário"</string> + <string name="permdesc_setTimeZone">"Permite que um aplicativo altere o fuso horário do telefone."</string> + <string name="permlab_getAccounts">"descobrir contas conhecidas"</string> + <string name="permdesc_getAccounts">"Permite que um aplicativo obtenha a lista de contas conhecidas pelo telefone."</string> + <string name="permlab_accessNetworkState">"exibir estado da rede"</string> + <string name="permdesc_accessNetworkState">"Permite que um aplicativo exiba o estado de todas as redes."</string> + <string name="permlab_createNetworkSockets">"acesso total à Internet"</string> + <string name="permdesc_createNetworkSockets">"Permite que um aplicativo crie soquetes de rede."</string> + <string name="permlab_writeApnSettings">"gravar configurações de Nome do ponto de acesso"</string> + <string name="permdesc_writeApnSettings">"Permite que um aplicativo modifique as configurações de APN, como Proxy e a Porta de qualquer APN."</string> + <string name="permlab_changeNetworkState">"alterar conectividade da rede"</string> + <string name="permdesc_changeNetworkState">"Permite que um aplicativo mude o estado da conectividade da rede."</string> + <!-- no translation found for permlab_changeBackgroundDataSetting (1400666012671648741) --> + <skip /> + <!-- no translation found for permdesc_changeBackgroundDataSetting (1001482853266638864) --> + <skip /> + <string name="permlab_accessWifiState">"exibir estado da rede Wi-Fi"</string> + <string name="permdesc_accessWifiState">"Permite que um aplicativo exiba as informações sobre o estado da rede Wi-Fi."</string> + <string name="permlab_changeWifiState">"Alterar estado de Wi-Fi"</string> + <string name="permdesc_changeWifiState">"Permite que um aplicativo se conecte e desconecte dos pontos de acesso Wi-Fi e faça alterações nas redes Wi-Fi configuradas."</string> + <!-- no translation found for permlab_changeWifiMulticastState (1368253871483254784) --> + <skip /> + <!-- no translation found for permdesc_changeWifiMulticastState (8199464507656067553) --> + <skip /> + <string name="permlab_bluetoothAdmin">"administração do bluetooth"</string> + <string name="permdesc_bluetoothAdmin">"Permite que um aplicativo configure o telefone Bluetooth local, além de descobrir e parear com dispositivos remotos."</string> + <string name="permlab_bluetooth">"criar conexões Bluetooth"</string> + <string name="permdesc_bluetooth">"Permite que um aplicativo exiba a configuração do telefone Bluetooth local e faça e aceite conexões com os dispositivos pareados."</string> + <string name="permlab_disableKeyguard">"desativar bloqueio de teclado"</string> + <string name="permdesc_disableKeyguard">"Permite que um aplicativo desative o bloqueio do teclado e qualquer segurança de senha associada. Um exemplo legítimo disso é o telefone desativando o bloqueio do teclado ao receber uma chamada e reativando o bloqueio ao final da chamada."</string> + <string name="permlab_readSyncSettings">"ler configurações de sincronização"</string> + <string name="permdesc_readSyncSettings">"Permite que um aplicativo leia as configurações de sincronização, por exemplo se a sincronização está ativada para Contatos."</string> + <string name="permlab_writeSyncSettings">"gravar configurações de sincronização"</string> + <string name="permdesc_writeSyncSettings">"Permite que um aplicativo modifique as configurações de sincronização, por exemplo se a sincronização está ativada para Contatos."</string> + <string name="permlab_readSyncStats">"ler estatísticas de sincronização"</string> + <string name="permdesc_readSyncStats">"Permite que um aplicativo leia as estatísticas de sincronização; por exemplo, o histórico de sincronizações realizadas."</string> + <string name="permlab_subscribedFeedsRead">"ler feeds inscritos"</string> + <string name="permdesc_subscribedFeedsRead">"Permite que um aplicativo obtenha detalhes sobre os feeds sincronizados atualmente."</string> + <string name="permlab_subscribedFeedsWrite">"gravar feeds inscritos"</string> + <string name="permdesc_subscribedFeedsWrite">"Permite que um aplicativo modifique seus feeds sincronizados recentemente. Isso poderia permitir que um aplicativo malicioso alterasse seus feeds sincronizados."</string> + <!-- no translation found for permlab_readDictionary (432535716804748781) --> + <skip /> + <!-- no translation found for permdesc_readDictionary (1082972603576360690) --> + <skip /> + <!-- no translation found for permlab_writeDictionary (6703109511836343341) --> + <skip /> + <!-- no translation found for permdesc_writeDictionary (2241256206524082880) --> + <skip /> + <!-- no translation found for permlab_sdcardWrite (8079403759001777291) --> + <skip /> + <!-- no translation found for permdesc_sdcardWrite (6643963204976471878) --> + <skip /> + <string-array name="phoneTypes"> + <item>"Página Inicial"</item> + <item>"Celular"</item> + <item>"Trabalho"</item> + <item>"Fax comercial"</item> + <item>"Fax doméstico"</item> + <item>"Pager"</item> + <item>"Outro"</item> + <item>"Personalizar"</item> + </string-array> + <string-array name="emailAddressTypes"> + <item>"Página Inicial"</item> + <item>"Trabalho"</item> + <item>"Outro"</item> + <item>"Personalizar"</item> + </string-array> + <!-- no translation found for mobileEmailTypeName (2858957283716687707) --> + <skip /> + <string-array name="postalAddressTypes"> + <item>"Página Inicial"</item> + <item>"Trabalho"</item> + <item>"Outro"</item> + <item>"Personalizar"</item> + </string-array> + <string-array name="imAddressTypes"> + <item>"Página Inicial"</item> + <item>"Trabalho"</item> + <item>"Outro"</item> + <item>"Personalizar"</item> + </string-array> + <string-array name="organizationTypes"> + <item>"Trabalho"</item> + <item>"Outro"</item> + <item>"Personalizar"</item> + </string-array> + <string-array name="imProtocols"> + <item>"AIM"</item> + <item>"Windows Live"</item> + <item>"Yahoo"</item> + <item>"Skype"</item> + <item>"QQ"</item> + <item>"Google Talk"</item> + <item>"ICQ"</item> + <item>"Jabber"</item> + </string-array> + <string name="keyguard_password_enter_pin_code">"Digite o código PIN"</string> + <string name="keyguard_password_wrong_pin_code">"Código PIN incorreto!"</string> + <string name="keyguard_label_text">"Para desbloquear, pressione Menu e 0."</string> + <string name="emergency_call_dialog_number_for_display">"Número de emergência"</string> + <string name="lockscreen_carrier_default">"(Sem serviço)"</string> + <string name="lockscreen_screen_locked">"Tela bloqueada."</string> + <string name="lockscreen_instructions_when_pattern_enabled">"Pressione Menu para desbloquear ou fazer chamada de emergência."</string> + <string name="lockscreen_instructions_when_pattern_disabled">"Pressione Menu para desbloquear."</string> + <string name="lockscreen_pattern_instructions">"Desenhar padrão para desbloqueio"</string> + <string name="lockscreen_emergency_call">"Chamada de emergência"</string> + <string name="lockscreen_pattern_correct">"Correto!"</string> + <string name="lockscreen_pattern_wrong">"Sentimos muito, tente novamente"</string> + <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> + <skip /> + <string name="lockscreen_low_battery">"Conecte o carregador."</string> + <string name="lockscreen_missing_sim_message_short">"Sem cartão SIM."</string> + <string name="lockscreen_missing_sim_message">"Não há um cartão SIM no telefone."</string> + <string name="lockscreen_missing_sim_instructions">"Insira um cartão SIM."</string> + <string name="lockscreen_network_locked_message">"Rede bloqueada"</string> + <string name="lockscreen_sim_puk_locked_message">"O cartão SIM está bloqueado pelo PUK."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> + <string name="lockscreen_sim_locked_message">"O cartão SIM está bloqueado."</string> + <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando cartão SIM…"</string> + <string name="lockscreen_too_many_failed_attempts_dialog_message">"Você desenhou incorretamente seu padrão de desbloqueio <xliff:g id="NUMBER_0">%d</xliff:g> vezes. "\n\n"Tente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string> + <string name="lockscreen_failed_attempts_almost_glogin">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem êxito, você receberá uma solicitação para desbloquear o telefone usando seu login do Google."\n\n" Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string> + <string name="lockscreen_too_many_failed_attempts_countdown">"Tentar novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string> + <string name="lockscreen_forgot_pattern_button_text">"Esqueceu o padrão?"</string> + <string name="lockscreen_glogin_too_many_attempts">"Muitas tentativas de padrão!"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> + <string name="lockscreen_glogin_username_hint">"Nome de usuário (e-mail)"</string> + <string name="lockscreen_glogin_password_hint">"Senha"</string> + <string name="lockscreen_glogin_submit_button">"Fazer login"</string> + <string name="lockscreen_glogin_invalid_input">"Nome de usuário ou senha inválida."</string> + <!-- no translation found for hour_ampm (4329881288269772723) --> + <skip /> + <!-- no translation found for hour_cap_ampm (1829009197680861107) --> + <skip /> + <string name="status_bar_clear_all_button">"Limpar notificações"</string> + <string name="status_bar_no_notifications_title">"Sem modificações"</string> + <string name="status_bar_ongoing_events_title">"Em andamento"</string> + <string name="status_bar_latest_events_title">"Notificações"</string> + <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> + <skip /> + <string name="battery_status_charging">"Carregando..."</string> + <string name="battery_low_title">"Conecte o carregador"</string> + <string name="battery_low_subtitle">"A carga da bateria está ficando baixa:"</string> + <string name="battery_low_percent_format">"menos de <xliff:g id="NUMBER">%d%%</xliff:g> restantes."</string> + <string name="factorytest_failed">"Falha no teste de fábrica"</string> + <string name="factorytest_not_system">"A ação FACTORY_TEST é suportada apenas para pacotes instalados em /system/app."</string> + <string name="factorytest_no_action">"Nenhum pacote foi encontrado que forneça a ação FACTORY_TEST."</string> + <string name="factorytest_reboot">"Reiniciar"</string> + <!-- no translation found for js_dialog_title (8143918455087008109) --> + <skip /> + <!-- no translation found for js_dialog_title_default (6961903213729667573) --> + <skip /> + <!-- no translation found for js_dialog_before_unload (1901675448179653089) --> + <skip /> + <string name="save_password_label">"Confirmar"</string> + <string name="save_password_message">"Deseja que o navegador se lembre desta senha?"</string> + <string name="save_password_notnow">"Não agora"</string> + <string name="save_password_remember">"Lembre-se"</string> + <string name="save_password_never">"Nunca"</string> + <string name="open_permission_deny">"Você não tem permissão para abrir essa página."</string> + <string name="text_copied">"Texto copiado para a área de transferência."</string> + <string name="more_item_label">"Mais"</string> + <string name="prepend_shortcut_label">"Menu+"</string> + <string name="menu_space_shortcut_label">"espaço"</string> + <string name="menu_enter_shortcut_label">"enter"</string> + <string name="menu_delete_shortcut_label">"excluir"</string> + <string name="search_go">"Procurar"</string> + <string name="oneMonthDurationPast">"1 mês atrás"</string> + <string name="beforeOneMonthDurationPast">"Antes de 1 mês atrás"</string> + <plurals name="num_seconds_ago"> + <item quantity="one">"1 segundo atrás"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g> segundos atrás"</item> + </plurals> + <plurals name="num_minutes_ago"> + <item quantity="one">"1 minute atrás"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g> minutos atrás"</item> + </plurals> + <plurals name="num_hours_ago"> + <item quantity="one">"1 hora trás"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g> horas atrás"</item> + </plurals> + <plurals name="num_days_ago"> + <item quantity="one">"ontem"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g> dias atrás"</item> + </plurals> + <plurals name="in_num_seconds"> + <item quantity="one">"em 1 segundo"</item> + <item quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> segundos"</item> + </plurals> + <plurals name="in_num_minutes"> + <item quantity="one">"em 1 minuto"</item> + <item quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> minutos"</item> + </plurals> + <plurals name="in_num_hours"> + <item quantity="one">"em 1 hora"</item> + <item quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> horas"</item> + </plurals> + <plurals name="in_num_days"> + <item quantity="one">"amanhã"</item> + <item quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> dias"</item> + </plurals> + <!-- no translation found for abbrev_num_seconds_ago:one (1849036840200069118) --> + <!-- no translation found for abbrev_num_seconds_ago:other (3699169366650930415) --> + <!-- no translation found for abbrev_num_minutes_ago:one (6361490147113871545) --> + <!-- no translation found for abbrev_num_minutes_ago:other (851164968597150710) --> + <!-- no translation found for abbrev_num_hours_ago:one (4796212039724722116) --> + <!-- no translation found for abbrev_num_hours_ago:other (6889970745748538901) --> + <!-- no translation found for abbrev_num_days_ago:one (8463161711492680309) --> + <!-- no translation found for abbrev_num_days_ago:other (3453342639616481191) --> + <!-- no translation found for abbrev_in_num_seconds:one (5842225370795066299) --> + <!-- no translation found for abbrev_in_num_seconds:other (5495880108825805108) --> + <!-- no translation found for abbrev_in_num_minutes:one (562786149928284878) --> + <!-- no translation found for abbrev_in_num_minutes:other (4216113292706568726) --> + <!-- no translation found for abbrev_in_num_hours:one (3274708118124045246) --> + <!-- no translation found for abbrev_in_num_hours:other (3705373766798013406) --> + <!-- no translation found for abbrev_in_num_days:one (2178576254385739855) --> + <!-- no translation found for abbrev_in_num_days:other (2973062968038355991) --> + <string name="preposition_for_date">"em %s"</string> + <string name="preposition_for_time">"a %s"</string> + <string name="preposition_for_year">"em %s"</string> + <string name="day">"dia"</string> + <string name="days">"dias"</string> + <string name="hour">"hora"</string> + <string name="hours">"horas"</string> + <string name="minute">"minuto"</string> + <string name="minutes">"minutos"</string> + <string name="second">"segundos"</string> + <string name="seconds">"segundos"</string> + <string name="week">"semana"</string> + <string name="weeks">"semanas"</string> + <string name="year">"ano"</string> + <string name="years">"anos"</string> + <string name="every_weekday">"Todo dia de semana (Seg–Sex)"</string> + <string name="daily">"Diariamente"</string> + <string name="weekly">"Semanalmente em <xliff:g id="DAY">%s</xliff:g>"</string> + <string name="monthly">"Mensalmente"</string> + <string name="yearly">"Anualmente"</string> + <string name="VideoView_error_title">"Não é possível reproduzir o vídeo"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> + <string name="VideoView_error_text_unknown">"Sentimos muito, este vídeo não pode ser reproduzido."</string> + <string name="VideoView_error_button">"OK"</string> + <!-- no translation found for relative_time (1818557177829411417) --> + <skip /> + <string name="noon">"meio-dia"</string> + <string name="Noon">"Meio-dia"</string> + <string name="midnight">"meia-noite"</string> + <string name="Midnight">"Meia-noite"</string> + <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> + <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> + <string name="selectAll">"Selecionar tudo"</string> + <string name="selectText">"Selecionar texto"</string> + <string name="stopSelectingText">"Interromper seleção de texto"</string> + <string name="cut">"Recortar"</string> + <string name="cutAll">"Recortar tudo"</string> + <string name="copy">"Copiar"</string> + <string name="copyAll">"Copiar tudo"</string> + <string name="paste">"Colar"</string> + <string name="copyUrl">"Copiar URL"</string> + <string name="inputMethod">"Método de entrada"</string> + <!-- no translation found for addToDictionary (726256909274177272) --> + <skip /> + <string name="editTextMenuTitle">"Editar texto"</string> + <string name="low_internal_storage_view_title">"Pouco espaço"</string> + <string name="low_internal_storage_view_text">"O espaço de armazenamento do telefone está diminuindo."</string> + <string name="ok">"OK"</string> + <string name="cancel">"Cancelar"</string> + <string name="yes">"OK"</string> + <string name="no">"Cancelar"</string> + <!-- no translation found for dialog_alert_title (2049658708609043103) --> + <skip /> + <string name="capital_on">"LIGAR"</string> + <string name="capital_off">"DESLIGADO"</string> + <string name="whichApplication">"Completar ação usando"</string> + <string name="alwaysUse">"Use por padrão para esta ação."</string> + <string name="clearDefaultHintMsg">"Limpar o padrão nas Configurações da página inicial> Aplicativos > Gerenciar aplicativos."</string> + <string name="chooseActivity">"Selecione uma ação"</string> + <string name="noApplications">"Nenhum aplicativo pode executar essa ação."</string> + <string name="aerr_title">"Sentimos muito."</string> + <string name="aerr_application">"O aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g>(processo <xliff:g id="PROCESS">%2$s</xliff:g>) parou inesperadamente. Tente novamente."</string> + <string name="aerr_process">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> parou inesperadamente. Tente novamente."</string> + <string name="anr_title">"Sentimos muito."</string> + <string name="anr_activity_application">"A atividade <xliff:g id="ACTIVITY">%1$s</xliff:g> (no aplicativo <xliff:g id="APPLICATION">%2$s</xliff:g>) não está respondendo."</string> + <string name="anr_activity_process">"A atividade <xliff:g id="ACTIVITY">%1$s</xliff:g> (<xliff:g id="PROCESS">%2$s</xliff:g> em processamento) não está respondendo."</string> + <string name="anr_application_process">"O aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> (<xliff:g id="PROCESS">%2$s</xliff:g> em processamento) não está respondendo."</string> + <string name="anr_process">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está respondendo."</string> + <string name="force_close">"Forçar fechamento"</string> + <!-- no translation found for report (4060218260984795706) --> + <skip /> + <string name="wait">"Aguarde"</string> + <string name="debug">"Depuração"</string> + <string name="sendText">"Selecione uma ação para texto"</string> + <string name="volume_ringtone">"Volume da campainha"</string> + <string name="volume_music">"Volume da mídia"</string> + <string name="volume_music_hint_playing_through_bluetooth">"Reprodução usando Bluetooth"</string> + <string name="volume_call">"Volume da chamada recebida"</string> + <!-- no translation found for volume_bluetooth_call (2002891926351151534) --> + <skip /> + <string name="volume_alarm">"Volume do alarme"</string> + <string name="volume_notification">"Volume da notificação"</string> + <string name="volume_unknown">"Volume"</string> + <string name="ringtone_default">"Ringtone padrão"</string> + <string name="ringtone_default_with_actual">"Ringtone padrão (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> + <string name="ringtone_silent">"Silencioso"</string> + <string name="ringtone_picker_title">"Ringtones"</string> + <string name="ringtone_unknown">"Ringtone desconhecido"</string> + <plurals name="wifi_available"> + <item quantity="one">"Rede Wi-Fi disponível"</item> + <item quantity="other">"Redes Wi-Fi disponíveis"</item> + </plurals> + <plurals name="wifi_available_detailed"> + <item quantity="one">"Redes Wi-Fi abertas disponíveis"</item> + <item quantity="other">"Redes Wi-Fi abertas disponíveis"</item> + </plurals> + <string name="select_character">"Inserir caractere"</string> + <string name="sms_control_default_app_name">"Aplicativo desconhecido"</string> + <string name="sms_control_title">"Envio de mensagens SMS"</string> + <string name="sms_control_message">"Uma grande quantidade de mensagens SMS está sendo enviada. Selecione \"OK\" para continuar ou \"Cancelar\" para parar de enviar."</string> + <string name="sms_control_yes">"OK"</string> + <string name="sms_control_no">"Cancelar"</string> + <string name="date_time_set">"Definir"</string> + <string name="default_permission_group">"Padrão"</string> + <string name="no_permissions">"Nenhuma permissão é necessária"</string> + <string name="perms_hide"><b>"Ocultar"</b></string> + <string name="perms_show_all"><b>"Mostrar tudo"</b></string> + <string name="googlewebcontenthelper_loading">"Carregando…"</string> + <string name="usb_storage_title">"Conectado via USB"</string> + <string name="usb_storage_message">"Você conectou o telefone ao seu computador via USB. Selecione \"Montar\" se quiser copiar os arquivos entre seu computador e o cartão SD do telefone."</string> + <string name="usb_storage_button_mount">"Montar"</string> + <string name="usb_storage_button_unmount">"Não montar"</string> + <string name="usb_storage_error_message">"Há um problema com o uso do seu cartão SD para armazenamento USB."</string> + <string name="usb_storage_notification_title">"Conectado via USB"</string> + <string name="usb_storage_notification_message">"Selecione para copiar os arquivos para/do computador."</string> + <!-- no translation found for usb_storage_stop_notification_title (2336058396663516017) --> + <skip /> + <!-- no translation found for usb_storage_stop_notification_message (2591813490269841539) --> + <skip /> + <!-- no translation found for usb_storage_stop_title (6014127947456185321) --> + <skip /> + <!-- no translation found for usb_storage_stop_message (2390958966725232848) --> + <skip /> + <!-- no translation found for usb_storage_stop_button_mount (1181858854166273345) --> + <skip /> + <!-- no translation found for usb_storage_stop_button_unmount (3774611918660582898) --> + <skip /> + <!-- no translation found for usb_storage_stop_error_message (3917317248440072084) --> + <skip /> + <!-- no translation found for extmedia_format_title (8663247929551095854) --> + <skip /> + <!-- no translation found for extmedia_format_message (3621369962433523619) --> + <skip /> + <!-- no translation found for extmedia_format_button_format (4131064560127478695) --> + <skip /> + <string name="select_input_method">"Selecionar método de entrada"</string> + <string name="fast_scroll_alphabet">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> + <string name="fast_scroll_numeric_alphabet">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> + <!-- no translation found for candidates_style (4333913089637062257) --> + <skip /> + <!-- no translation found for ext_media_checking_notification_title (5457603418970994050) --> + <skip /> + <!-- no translation found for ext_media_checking_notification_message (4747432538578886744) --> + <skip /> + <!-- no translation found for ext_media_nofs_notification_title (780477838241212997) --> + <skip /> + <!-- no translation found for ext_media_nofs_notification_message (1312266820092958014) --> + <skip /> + <!-- no translation found for ext_media_unmountable_notification_title (6410723906019100189) --> + <skip /> + <!-- no translation found for ext_media_unmountable_notification_message (2679412884290061775) --> + <skip /> + <!-- no translation found for ext_media_badremoval_notification_title (6872152882604407837) --> + <skip /> + <!-- no translation found for ext_media_badremoval_notification_message (7260183293747448241) --> + <skip /> + <!-- no translation found for ext_media_safe_unmount_notification_title (6729801130790616200) --> + <skip /> + <!-- no translation found for ext_media_safe_unmount_notification_message (7613960686747592770) --> + <skip /> + <!-- no translation found for ext_media_nomedia_notification_title (8902518030404381318) --> + <skip /> + <!-- no translation found for ext_media_nomedia_notification_message (4205117227342822275) --> + <skip /> + <!-- no translation found for activity_list_empty (4168820609403385789) --> + <skip /> + <!-- no translation found for permlab_pkgUsageStats (8787352074326748892) --> + <skip /> + <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) --> + <skip /> + <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) --> + <skip /> + <!-- no translation found for gadget_host_error_inflating (2613287218853846830) --> + <skip /> + <!-- no translation found for ime_action_go (8320845651737369027) --> + <skip /> + <!-- no translation found for ime_action_search (658110271822807811) --> + <skip /> + <!-- no translation found for ime_action_send (2316166556349314424) --> + <skip /> + <!-- no translation found for ime_action_next (3138843904009813834) --> + <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> + <!-- no translation found for ime_action_default (2840921885558045721) --> + <skip /> + <!-- no translation found for dial_number_using (5789176425167573586) --> + <skip /> + <!-- no translation found for create_contact_using (4947405226788104538) --> + <skip /> + <!-- no translation found for accessibility_compound_button_selected (5612776946036285686) --> + <skip /> + <!-- no translation found for accessibility_compound_button_unselected (8864512895673924091) --> + <skip /> +</resources> diff --git a/core/res/res/values-ro-rRO/donottranslate-cldr.xml b/core/res/res/values-ro-rRO/donottranslate-cldr.xml new file mode 100644 index 0000000..4622445 --- /dev/null +++ b/core/res/res/values-ro-rRO/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">ianuarie</string> + <string name="month_long_standalone_february">februarie</string> + <string name="month_long_standalone_march">martie</string> + <string name="month_long_standalone_april">aprilie</string> + <string name="month_long_standalone_may">mai</string> + <string name="month_long_standalone_june">iunie</string> + <string name="month_long_standalone_july">iulie</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">septembrie</string> + <string name="month_long_standalone_october">octombrie</string> + <string name="month_long_standalone_november">noiembrie</string> + <string name="month_long_standalone_december">decembrie</string> + + <string name="month_long_january">ianuarie</string> + <string name="month_long_february">februarie</string> + <string name="month_long_march">martie</string> + <string name="month_long_april">aprilie</string> + <string name="month_long_may">mai</string> + <string name="month_long_june">iunie</string> + <string name="month_long_july">iulie</string> + <string name="month_long_august">august</string> + <string name="month_long_september">septembrie</string> + <string name="month_long_october">octombrie</string> + <string name="month_long_november">noiembrie</string> + <string name="month_long_december">decembrie</string> + + <string name="month_medium_january">ian.</string> + <string name="month_medium_february">feb.</string> + <string name="month_medium_march">mar.</string> + <string name="month_medium_april">apr.</string> + <string name="month_medium_may">mai</string> + <string name="month_medium_june">iun.</string> + <string name="month_medium_july">iul.</string> + <string name="month_medium_august">aug.</string> + <string name="month_medium_september">sept.</string> + <string name="month_medium_october">oct.</string> + <string name="month_medium_november">nov.</string> + <string name="month_medium_december">dec.</string> + + <string name="month_shortest_january">I</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">I</string> + <string name="month_shortest_july">I</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">duminică</string> + <string name="day_of_week_long_monday">luni</string> + <string name="day_of_week_long_tuesday">marți</string> + <string name="day_of_week_long_wednesday">miercuri</string> + <string name="day_of_week_long_thursday">joi</string> + <string name="day_of_week_long_friday">vineri</string> + <string name="day_of_week_long_saturday">sâmbătă</string> + + <string name="day_of_week_medium_sunday">Du</string> + <string name="day_of_week_medium_monday">Lu</string> + <string name="day_of_week_medium_tuesday">Ma</string> + <string name="day_of_week_medium_wednesday">Mi</string> + <string name="day_of_week_medium_thursday">Jo</string> + <string name="day_of_week_medium_friday">Vi</string> + <string name="day_of_week_medium_saturday">Sâ</string> + + <string name="day_of_week_short_sunday">Du</string> + <string name="day_of_week_short_monday">Lu</string> + <string name="day_of_week_short_tuesday">Ma</string> + <string name="day_of_week_short_wednesday">Mi</string> + <string name="day_of_week_short_thursday">Jo</string> + <string name="day_of_week_short_friday">Vi</string> + <string name="day_of_week_short_saturday">Sâ</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">L</string> + <string name="day_of_week_shortest_tuesday">M</string> + <string name="day_of_week_shortest_wednesday">M</string> + <string name="day_of_week_shortest_thursday">J</string> + <string name="day_of_week_shortest_friday">V</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">ieri</string> + <string name="today">azi</string> + <string name="tomorrow">mâine</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S, %d.%m.%Y</string> + <string name="date_time">%2$s, %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ru-rRU/donottranslate-cldr.xml b/core/res/res/values-ru-rRU/donottranslate-cldr.xml new file mode 100644 index 0000000..21c06ff --- /dev/null +++ b/core/res/res/values-ru-rRU/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Январь</string> + <string name="month_long_standalone_february">Февраль</string> + <string name="month_long_standalone_march">Март</string> + <string name="month_long_standalone_april">Апрель</string> + <string name="month_long_standalone_may">Май</string> + <string name="month_long_standalone_june">Июнь</string> + <string name="month_long_standalone_july">Июль</string> + <string name="month_long_standalone_august">Август</string> + <string name="month_long_standalone_september">Сентябрь</string> + <string name="month_long_standalone_october">Октябрь</string> + <string name="month_long_standalone_november">Ноябрь</string> + <string name="month_long_standalone_december">Декабрь</string> + + <string name="month_long_january">января</string> + <string name="month_long_february">февраля</string> + <string name="month_long_march">марта</string> + <string name="month_long_april">апреля</string> + <string name="month_long_may">мая</string> + <string name="month_long_june">июня</string> + <string name="month_long_july">июля</string> + <string name="month_long_august">августа</string> + <string name="month_long_september">сентября</string> + <string name="month_long_october">октября</string> + <string name="month_long_november">ноября</string> + <string name="month_long_december">декабря</string> + + <string name="month_medium_january">янв.</string> + <string name="month_medium_february">февр.</string> + <string name="month_medium_march">марта</string> + <string name="month_medium_april">апр.</string> + <string name="month_medium_may">мая</string> + <string name="month_medium_june">июня</string> + <string name="month_medium_july">июля</string> + <string name="month_medium_august">авг.</string> + <string name="month_medium_september">сент.</string> + <string name="month_medium_october">окт.</string> + <string name="month_medium_november">нояб.</string> + <string name="month_medium_december">дек.</string> + + <string name="month_shortest_january">Я</string> + <string name="month_shortest_february">Ф</string> + <string name="month_shortest_march">М</string> + <string name="month_shortest_april">А</string> + <string name="month_shortest_may">М</string> + <string name="month_shortest_june">И</string> + <string name="month_shortest_july">И</string> + <string name="month_shortest_august">А</string> + <string name="month_shortest_september">С</string> + <string name="month_shortest_october">О</string> + <string name="month_shortest_november">Н</string> + <string name="month_shortest_december">Д</string> + + <string name="day_of_week_long_sunday">воскресенье</string> + <string name="day_of_week_long_monday">понедельник</string> + <string name="day_of_week_long_tuesday">вторник</string> + <string name="day_of_week_long_wednesday">среда</string> + <string name="day_of_week_long_thursday">четверг</string> + <string name="day_of_week_long_friday">пятница</string> + <string name="day_of_week_long_saturday">суббота</string> + + <string name="day_of_week_medium_sunday">Вс</string> + <string name="day_of_week_medium_monday">Пн</string> + <string name="day_of_week_medium_tuesday">Вт</string> + <string name="day_of_week_medium_wednesday">Ср</string> + <string name="day_of_week_medium_thursday">Чт</string> + <string name="day_of_week_medium_friday">Пт</string> + <string name="day_of_week_medium_saturday">Сб</string> + + <string name="day_of_week_short_sunday">Вс</string> + <string name="day_of_week_short_monday">Пн</string> + <string name="day_of_week_short_tuesday">Вт</string> + <string name="day_of_week_short_wednesday">Ср</string> + <string name="day_of_week_short_thursday">Чт</string> + <string name="day_of_week_short_friday">Пт</string> + <string name="day_of_week_short_saturday">Сб</string> + + <string name="day_of_week_shortest_sunday">В</string> + <string name="day_of_week_shortest_monday">П</string> + <string name="day_of_week_shortest_tuesday">В</string> + <string name="day_of_week_shortest_wednesday">С</string> + <string name="day_of_week_shortest_thursday">Ч</string> + <string name="day_of_week_shortest_friday">П</string> + <string name="day_of_week_shortest_saturday">С</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Вчера</string> + <string name="today">Сегодня</string> + <string name="tomorrow">Завтра</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y г.</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %2$s-%3$s – %6$s, %7$s-%8$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 - %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 %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_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 - %6$s %5$s</string> + <string name="wday1_date1_wday2_date2">%2$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 %3$s</string> + <string name="wday_date">%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_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_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 %2$s %3$s - %6$s %7$s %8$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">%3$s %2$s - %8$s %7$s %9$s г.</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ru/donottranslate-cldr.xml b/core/res/res/values-ru/donottranslate-cldr.xml new file mode 100644 index 0000000..21c06ff --- /dev/null +++ b/core/res/res/values-ru/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Январь</string> + <string name="month_long_standalone_february">Февраль</string> + <string name="month_long_standalone_march">Март</string> + <string name="month_long_standalone_april">Апрель</string> + <string name="month_long_standalone_may">Май</string> + <string name="month_long_standalone_june">Июнь</string> + <string name="month_long_standalone_july">Июль</string> + <string name="month_long_standalone_august">Август</string> + <string name="month_long_standalone_september">Сентябрь</string> + <string name="month_long_standalone_october">Октябрь</string> + <string name="month_long_standalone_november">Ноябрь</string> + <string name="month_long_standalone_december">Декабрь</string> + + <string name="month_long_january">января</string> + <string name="month_long_february">февраля</string> + <string name="month_long_march">марта</string> + <string name="month_long_april">апреля</string> + <string name="month_long_may">мая</string> + <string name="month_long_june">июня</string> + <string name="month_long_july">июля</string> + <string name="month_long_august">августа</string> + <string name="month_long_september">сентября</string> + <string name="month_long_october">октября</string> + <string name="month_long_november">ноября</string> + <string name="month_long_december">декабря</string> + + <string name="month_medium_january">янв.</string> + <string name="month_medium_february">февр.</string> + <string name="month_medium_march">марта</string> + <string name="month_medium_april">апр.</string> + <string name="month_medium_may">мая</string> + <string name="month_medium_june">июня</string> + <string name="month_medium_july">июля</string> + <string name="month_medium_august">авг.</string> + <string name="month_medium_september">сент.</string> + <string name="month_medium_october">окт.</string> + <string name="month_medium_november">нояб.</string> + <string name="month_medium_december">дек.</string> + + <string name="month_shortest_january">Я</string> + <string name="month_shortest_february">Ф</string> + <string name="month_shortest_march">М</string> + <string name="month_shortest_april">А</string> + <string name="month_shortest_may">М</string> + <string name="month_shortest_june">И</string> + <string name="month_shortest_july">И</string> + <string name="month_shortest_august">А</string> + <string name="month_shortest_september">С</string> + <string name="month_shortest_october">О</string> + <string name="month_shortest_november">Н</string> + <string name="month_shortest_december">Д</string> + + <string name="day_of_week_long_sunday">воскресенье</string> + <string name="day_of_week_long_monday">понедельник</string> + <string name="day_of_week_long_tuesday">вторник</string> + <string name="day_of_week_long_wednesday">среда</string> + <string name="day_of_week_long_thursday">четверг</string> + <string name="day_of_week_long_friday">пятница</string> + <string name="day_of_week_long_saturday">суббота</string> + + <string name="day_of_week_medium_sunday">Вс</string> + <string name="day_of_week_medium_monday">Пн</string> + <string name="day_of_week_medium_tuesday">Вт</string> + <string name="day_of_week_medium_wednesday">Ср</string> + <string name="day_of_week_medium_thursday">Чт</string> + <string name="day_of_week_medium_friday">Пт</string> + <string name="day_of_week_medium_saturday">Сб</string> + + <string name="day_of_week_short_sunday">Вс</string> + <string name="day_of_week_short_monday">Пн</string> + <string name="day_of_week_short_tuesday">Вт</string> + <string name="day_of_week_short_wednesday">Ср</string> + <string name="day_of_week_short_thursday">Чт</string> + <string name="day_of_week_short_friday">Пт</string> + <string name="day_of_week_short_saturday">Сб</string> + + <string name="day_of_week_shortest_sunday">В</string> + <string name="day_of_week_shortest_monday">П</string> + <string name="day_of_week_shortest_tuesday">В</string> + <string name="day_of_week_shortest_wednesday">С</string> + <string name="day_of_week_shortest_thursday">Ч</string> + <string name="day_of_week_shortest_friday">П</string> + <string name="day_of_week_shortest_saturday">С</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Вчера</string> + <string name="today">Сегодня</string> + <string name="tomorrow">Завтра</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y г.</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %d.%m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %2$s-%3$s – %6$s, %7$s-%8$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 - %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 %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_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 - %6$s %5$s</string> + <string name="wday1_date1_wday2_date2">%2$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 %3$s</string> + <string name="wday_date">%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_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_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 %2$s %3$s - %6$s %7$s %8$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">%3$s %2$s - %8$s %7$s %9$s г.</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index fac6cb7..048f6b1 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"Позволяет приложению изменять текущую конфигурацию, например локаль и общий размер шрифта."</string> <string name="permlab_restartPackages">"перезапускать другие приложения"</string> <string name="permdesc_restartPackages">"Разрешает приложению принудительно перезапускать другие приложения."</string> - <string name="permlab_setProcessForeground">"предотвращать остановку"</string> - <string name="permdesc_setProcessForeground">"Разрешает приложению запускать любые процессы на переднем плане так, что их нельзя прекратить. Не требуется обычным приложениям."</string> <string name="permlab_forceBack">"принудительно закрывать приложения"</string> <string name="permdesc_forceBack">"Позволяет приложению принудительно закрывать и переводить в фоновый режим действия, работающие на переднем плане. Не требуется обычным приложениям."</string> <string name="permlab_dump">"получать внутреннее состояние системы"</string> <string name="permdesc_dump">"Разрешает приложениям получать внутреннее состояние системы. Вредоносное ПО может получать множество личной и защищенной информации, которая обычно не была бы им доступна."</string> - <string name="permlab_addSystemService">"публиковать службы низкого уровня"</string> - <string name="permdesc_addSystemService">"Разрешает приложению публиковать собственные системные службы низкого уровня. Вредоносное ПО может взломать систему и украсть или повредить данные в ней."</string> <string name="permlab_runSetActivityWatcher">"наблюдать и управлять запуском всех приложений"</string> <string name="permdesc_runSetActivityWatcher">"Разрешает приложению следить и управлять тем, как система запускает действия. Вредоносное ПО может полностью нарушить работу системы. Это разрешение нужно только для разработки, но не при обычном использовании телефона."</string> <string name="permlab_broadcastPackageRemoved">"отправлять оповещения об удалении пакетов"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"Позволяет приложению контролировать максимальное количество выполняемых процессов. Не требуется обычным приложениям."</string> <string name="permlab_setAlwaysFinish">"закрывать все фоновые приложения"</string> <string name="permdesc_setAlwaysFinish">"Разрешает приложению следить, чтобы действия всегда завершались после перехода в фоновый режим. Не требуется обычным приложениям."</string> - <string name="permlab_fotaUpdate">"автоматически устанавливать системные обновления"</string> - <string name="permdesc_fotaUpdate">"Разрешает приложению получать уведомления о предстоящих обновлениях системы и запускать их установку. Это дает вредоносному ПО возможность повредить систему неавторизованными обновлениями или помешать выполнению обновления."</string> <string name="permlab_batteryStats">"изменять данные о батарее"</string> <string name="permdesc_batteryStats">"Разрешает изменять данные о батарее. Не используется обычными приложениями."</string> <string name="permlab_internalSystemWindow">"отображать неавторизованные окна"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"Пароль"</string> <string name="lockscreen_glogin_submit_button">"Войти"</string> <string name="lockscreen_glogin_invalid_input">"Недействительное имя пользователя или пароль."</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"Очистить уведомления"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"ввод"</string> <string name="menu_delete_shortcut_label">"удалить"</string> <string name="search_go">"Поиск"</string> - <string name="today">"Сегодня"</string> - <string name="yesterday">"Вчера"</string> - <string name="tomorrow">"Завтра"</string> <string name="oneMonthDurationPast">"1 месяц назад"</string> <string name="beforeOneMonthDurationPast">"Больше 1 месяца назад"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"недели"</string> <string name="year">"год"</string> <string name="years">"годы"</string> - <string name="sunday">"воскресенье"</string> - <string name="monday">"понедельник"</string> - <string name="tuesday">"вторник"</string> - <string name="wednesday">"среда"</string> - <string name="thursday">"четверг"</string> - <string name="friday">"пятница"</string> - <string name="saturday">"суббота"</string> <string name="every_weekday">"По рабочим дням (пн-пт)"</string> <string name="daily">"Ежедневно"</string> <string name="weekly">"Еженедельно в: <xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"К сожалению, это видео не подходит для потокового воспроизведения на данном устройстве."</string> <string name="VideoView_error_text_unknown">"К сожалению, это видео нельзя воспроизвести."</string> <string name="VideoView_error_button">"ОК"</string> - <string name="am">"AM"</string> - <string name="pm">"PM"</string> - <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"полдень"</string> <string name="Noon">"Полдень"</string> <string name="midnight">"полночь"</string> <string name="Midnight">"Полночь"</string> - <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> <xliff:g id="MONTH">%B</xliff:g> г."</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g> г."</string> - <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"воскресенье"</string> - <string name="day_of_week_long_monday">"понедельник"</string> - <string name="day_of_week_long_tuesday">"вторник"</string> - <string name="day_of_week_long_wednesday">"среда"</string> - <string name="day_of_week_long_thursday">"четверг"</string> - <string name="day_of_week_long_friday">"пятница"</string> - <string name="day_of_week_long_saturday">"суббота"</string> - <string name="day_of_week_medium_sunday">"вс"</string> - <string name="day_of_week_medium_monday">"пн"</string> - <string name="day_of_week_medium_tuesday">"вт"</string> - <string name="day_of_week_medium_wednesday">"ср"</string> - <string name="day_of_week_medium_thursday">"чт"</string> - <string name="day_of_week_medium_friday">"пт"</string> - <string name="day_of_week_medium_saturday">"сб"</string> - <string name="day_of_week_short_sunday">"вс"</string> - <string name="day_of_week_short_monday">"пн"</string> - <string name="day_of_week_short_tuesday">"вт"</string> - <string name="day_of_week_short_wednesday">"ср"</string> - <string name="day_of_week_short_thursday">"чт"</string> - <string name="day_of_week_short_friday">"пт"</string> - <string name="day_of_week_short_saturday">"сб"</string> - <string name="day_of_week_shorter_sunday">"вс"</string> - <string name="day_of_week_shorter_monday">"пн"</string> - <string name="day_of_week_shorter_tuesday">"вт"</string> - <string name="day_of_week_shorter_wednesday">"с"</string> - <string name="day_of_week_shorter_thursday">"чт"</string> - <string name="day_of_week_shorter_friday">"пт"</string> - <string name="day_of_week_shorter_saturday">"сб"</string> - <string name="day_of_week_shortest_sunday">"в"</string> - <string name="day_of_week_shortest_monday">"п"</string> - <string name="day_of_week_shortest_tuesday">"в"</string> - <string name="day_of_week_shortest_wednesday">"с"</string> - <string name="day_of_week_shortest_thursday">"ч"</string> - <string name="day_of_week_shortest_friday">"п"</string> - <string name="day_of_week_shortest_saturday">"с"</string> - <string name="month_long_january">"январь"</string> - <string name="month_long_february">"февраль"</string> - <string name="month_long_march">"март"</string> - <string name="month_long_april">"апрель"</string> - <string name="month_long_may">"май"</string> - <string name="month_long_june">"июнь"</string> - <string name="month_long_july">"июль"</string> - <string name="month_long_august">"август"</string> - <string name="month_long_september">"сентябрь"</string> - <string name="month_long_october">"октябрь"</string> - <string name="month_long_november">"ноябрь"</string> - <string name="month_long_december">"декабрь"</string> - <string name="month_medium_january">"янв"</string> - <string name="month_medium_february">"фев"</string> - <string name="month_medium_march">"мар"</string> - <string name="month_medium_april">"апр"</string> - <string name="month_medium_may">"май"</string> - <string name="month_medium_june">"июн"</string> - <string name="month_medium_july">"июл"</string> - <string name="month_medium_august">"авг"</string> - <string name="month_medium_september">"сен"</string> - <string name="month_medium_october">"окт"</string> - <string name="month_medium_november">"ноя"</string> - <string name="month_medium_december">"дек"</string> - <string name="month_shortest_january">"Я"</string> - <string name="month_shortest_february">"ф"</string> - <string name="month_shortest_march">"м"</string> - <string name="month_shortest_april">"а"</string> - <string name="month_shortest_may">"м"</string> - <string name="month_shortest_june">"и"</string> - <string name="month_shortest_july">"и"</string> - <string name="month_shortest_august">"а"</string> - <string name="month_shortest_september">"с"</string> - <string name="month_shortest_october">"о"</string> - <string name="month_shortest_november">"н"</string> - <string name="month_shortest_december">"д"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"Выбрать все"</string> diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml new file mode 100644 index 0000000..16239df --- /dev/null +++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">január</string> + <string name="month_long_standalone_february">február</string> + <string name="month_long_standalone_march">marec</string> + <string name="month_long_standalone_april">apríl</string> + <string name="month_long_standalone_may">máj</string> + <string name="month_long_standalone_june">jún</string> + <string name="month_long_standalone_july">júl</string> + <string name="month_long_standalone_august">august</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">október</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januára</string> + <string name="month_long_february">februára</string> + <string name="month_long_march">marca</string> + <string name="month_long_april">apríla</string> + <string name="month_long_may">mája</string> + <string name="month_long_june">júna</string> + <string name="month_long_july">júla</string> + <string name="month_long_august">augusta</string> + <string name="month_long_september">septembra</string> + <string name="month_long_october">októbra</string> + <string name="month_long_november">novembra</string> + <string name="month_long_december">decembra</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">máj</string> + <string name="month_medium_june">jún</string> + <string name="month_medium_july">júl</string> + <string name="month_medium_august">aug</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">j</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">nedeľa</string> + <string name="day_of_week_long_monday">pondelok</string> + <string name="day_of_week_long_tuesday">utorok</string> + <string name="day_of_week_long_wednesday">streda</string> + <string name="day_of_week_long_thursday">štvrtok</string> + <string name="day_of_week_long_friday">piatok</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ne</string> + <string name="day_of_week_medium_monday">po</string> + <string name="day_of_week_medium_tuesday">ut</string> + <string name="day_of_week_medium_wednesday">st</string> + <string name="day_of_week_medium_thursday">št</string> + <string name="day_of_week_medium_friday">pi</string> + <string name="day_of_week_medium_saturday">so</string> + + <string name="day_of_week_short_sunday">ne</string> + <string name="day_of_week_short_monday">po</string> + <string name="day_of_week_short_tuesday">ut</string> + <string name="day_of_week_short_wednesday">st</string> + <string name="day_of_week_short_thursday">št</string> + <string name="day_of_week_short_friday">pi</string> + <string name="day_of_week_short_saturday">so</string> + + <string name="day_of_week_shortest_sunday">N</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">U</string> + <string name="day_of_week_shortest_wednesday">S</string> + <string name="day_of_week_shortest_thursday">Š</string> + <string name="day_of_week_shortest_friday">P</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">dopoludnia</string> + <string name="pm">popoludní</string> + <string name="yesterday">Včera</string> + <string name="today">Dnes</string> + <string name="tomorrow">Zajtra</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-e.%-m.%Y</string> + <string name="numeric_date_format">d.M.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e. %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S %-e.%-m.%Y</string> + <string name="date_time">%2$s %1$s</string> + <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_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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml new file mode 100644 index 0000000..b4ea32f --- /dev/null +++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januar</string> + <string name="month_long_standalone_february">februar</string> + <string name="month_long_standalone_march">marec</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">junij</string> + <string name="month_long_standalone_july">julij</string> + <string name="month_long_standalone_august">avgust</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januar</string> + <string name="month_long_february">februar</string> + <string name="month_long_march">marec</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">junij</string> + <string name="month_long_july">julij</string> + <string name="month_long_august">avgust</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">avg</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">j</string> + <string name="month_shortest_february">f</string> + <string name="month_shortest_march">m</string> + <string name="month_shortest_april">a</string> + <string name="month_shortest_may">m</string> + <string name="month_shortest_june">j</string> + <string name="month_shortest_july">j</string> + <string name="month_shortest_august">a</string> + <string name="month_shortest_september">s</string> + <string name="month_shortest_october">o</string> + <string name="month_shortest_november">n</string> + <string name="month_shortest_december">d</string> + + <string name="day_of_week_long_sunday">nedelja</string> + <string name="day_of_week_long_monday">ponedeljek</string> + <string name="day_of_week_long_tuesday">torek</string> + <string name="day_of_week_long_wednesday">sreda</string> + <string name="day_of_week_long_thursday">četrtek</string> + <string name="day_of_week_long_friday">petek</string> + <string name="day_of_week_long_saturday">sobota</string> + + <string name="day_of_week_medium_sunday">ned</string> + <string name="day_of_week_medium_monday">pon</string> + <string name="day_of_week_medium_tuesday">tor</string> + <string name="day_of_week_medium_wednesday">sre</string> + <string name="day_of_week_medium_thursday">čet</string> + <string name="day_of_week_medium_friday">pet</string> + <string name="day_of_week_medium_saturday">sob</string> + + <string name="day_of_week_short_sunday">ned</string> + <string name="day_of_week_short_monday">pon</string> + <string name="day_of_week_short_tuesday">tor</string> + <string name="day_of_week_short_wednesday">sre</string> + <string name="day_of_week_short_thursday">čet</string> + <string name="day_of_week_short_friday">pet</string> + <string name="day_of_week_short_saturday">sob</string> + + <string name="day_of_week_shortest_sunday">n</string> + <string name="day_of_week_shortest_monday">p</string> + <string name="day_of_week_shortest_tuesday">t</string> + <string name="day_of_week_shortest_wednesday">s</string> + <string name="day_of_week_shortest_thursday">č</string> + <string name="day_of_week_shortest_friday">p</string> + <string name="day_of_week_shortest_saturday">s</string> + + <string name="am">dop.</string> + <string name="pm">pop.</string> + <string name="yesterday">Včeraj</string> + <string name="today">Danes</string> + <string name="tomorrow">Jutri</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e. %m. %Y</string> + <string name="numeric_date_format">d. MM. yyyy</string> + <string name="numeric_date_template">"%s. %s. %s"</string> + <string name="month_day_year">%d. %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e. %b. %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e. %b. %Y</string> + <string name="month_day">%-e. %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e. %b.</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b. %Y</string> + <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., %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-sr-rRS/donottranslate-cldr.xml b/core/res/res/values-sr-rRS/donottranslate-cldr.xml new file mode 100644 index 0000000..55ca968 --- /dev/null +++ b/core/res/res/values-sr-rRS/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">јануар</string> + <string name="month_long_standalone_february">фебруар</string> + <string name="month_long_standalone_march">март</string> + <string name="month_long_standalone_april">април</string> + <string name="month_long_standalone_may">мај</string> + <string name="month_long_standalone_june">јун</string> + <string name="month_long_standalone_july">јул</string> + <string name="month_long_standalone_august">август</string> + <string name="month_long_standalone_september">септембар</string> + <string name="month_long_standalone_october">октобар</string> + <string name="month_long_standalone_november">новембар</string> + <string name="month_long_standalone_december">децембар</string> + + <string name="month_long_january">јануар</string> + <string name="month_long_february">фебруар</string> + <string name="month_long_march">март</string> + <string name="month_long_april">април</string> + <string name="month_long_may">мај</string> + <string name="month_long_june">јун</string> + <string name="month_long_july">јул</string> + <string name="month_long_august">август</string> + <string name="month_long_september">септембар</string> + <string name="month_long_october">октобар</string> + <string name="month_long_november">новембар</string> + <string name="month_long_december">децембар</string> + + <string name="month_medium_january">јан</string> + <string name="month_medium_february">феб</string> + <string name="month_medium_march">мар</string> + <string name="month_medium_april">апр</string> + <string name="month_medium_may">мај</string> + <string name="month_medium_june">јун</string> + <string name="month_medium_july">јул</string> + <string name="month_medium_august">авг</string> + <string name="month_medium_september">сеп</string> + <string name="month_medium_october">окт</string> + <string name="month_medium_november">нов</string> + <string name="month_medium_december">дец</string> + + <string name="month_shortest_january">ј</string> + <string name="month_shortest_february">ф</string> + <string name="month_shortest_march">м</string> + <string name="month_shortest_april">а</string> + <string name="month_shortest_may">м</string> + <string name="month_shortest_june">ј</string> + <string name="month_shortest_july">ј</string> + <string name="month_shortest_august">а</string> + <string name="month_shortest_september">с</string> + <string name="month_shortest_october">о</string> + <string name="month_shortest_november">н</string> + <string name="month_shortest_december">д</string> + + <string name="day_of_week_long_sunday">недеља</string> + <string name="day_of_week_long_monday">понедељак</string> + <string name="day_of_week_long_tuesday">уторак</string> + <string name="day_of_week_long_wednesday">среда</string> + <string name="day_of_week_long_thursday">четвртак</string> + <string name="day_of_week_long_friday">петак</string> + <string name="day_of_week_long_saturday">субота</string> + + <string name="day_of_week_medium_sunday">нед</string> + <string name="day_of_week_medium_monday">пон</string> + <string name="day_of_week_medium_tuesday">уто</string> + <string name="day_of_week_medium_wednesday">сре</string> + <string name="day_of_week_medium_thursday">чет</string> + <string name="day_of_week_medium_friday">пет</string> + <string name="day_of_week_medium_saturday">суб</string> + + <string name="day_of_week_short_sunday">нед</string> + <string name="day_of_week_short_monday">пон</string> + <string name="day_of_week_short_tuesday">уто</string> + <string name="day_of_week_short_wednesday">сре</string> + <string name="day_of_week_short_thursday">чет</string> + <string name="day_of_week_short_friday">пет</string> + <string name="day_of_week_short_saturday">суб</string> + + <string name="day_of_week_shortest_sunday">н</string> + <string name="day_of_week_shortest_monday">п</string> + <string name="day_of_week_shortest_tuesday">у</string> + <string name="day_of_week_shortest_wednesday">с</string> + <string name="day_of_week_shortest_thursday">ч</string> + <string name="day_of_week_shortest_friday">п</string> + <string name="day_of_week_shortest_saturday">с</string> + + <string name="am">пре подне</string> + <string name="pm">поподне</string> + <string name="yesterday">јуче</string> + <string name="today">данас</string> + <string name="tomorrow">сутра</string> + + <string name="hour_minute_24">%H.%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH.mm</string> + <string name="numeric_date">%-e.%-m.%Y.</string> + <string name="numeric_date_format">d.M.yyyy.</string> + <string name="numeric_date_template">"%s.%s.%s."</string> + <string name="month_day_year">%d. %B %Y.</string> + <string name="time_of_day">%H.%M.%S</string> + <string name="date_and_time">%H.%M.%S %d.%m.%Y.</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d.%m.%Y.</string> + <string name="month_day">%B %-e.</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%b %-e.</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b. %Y</string> + <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, %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_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="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">%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 %3$s. %2$s - %6$s %8$s. %7$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 %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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-sv-rSE/donottranslate-cldr.xml b/core/res/res/values-sv-rSE/donottranslate-cldr.xml new file mode 100644 index 0000000..a6ffc9a --- /dev/null +++ b/core/res/res/values-sv-rSE/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januari</string> + <string name="month_long_standalone_february">februari</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">augusti</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januari</string> + <string name="month_long_february">februari</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">augusti</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">aug</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">söndag</string> + <string name="day_of_week_long_monday">måndag</string> + <string name="day_of_week_long_tuesday">tisdag</string> + <string name="day_of_week_long_wednesday">onsdag</string> + <string name="day_of_week_long_thursday">torsdag</string> + <string name="day_of_week_long_friday">fredag</string> + <string name="day_of_week_long_saturday">lördag</string> + + <string name="day_of_week_medium_sunday">sön</string> + <string name="day_of_week_medium_monday">mån</string> + <string name="day_of_week_medium_tuesday">tis</string> + <string name="day_of_week_medium_wednesday">ons</string> + <string name="day_of_week_medium_thursday">tors</string> + <string name="day_of_week_medium_friday">fre</string> + <string name="day_of_week_medium_saturday">lör</string> + + <string name="day_of_week_short_sunday">sön</string> + <string name="day_of_week_short_monday">mån</string> + <string name="day_of_week_short_tuesday">tis</string> + <string name="day_of_week_short_wednesday">ons</string> + <string name="day_of_week_short_thursday">tors</string> + <string name="day_of_week_short_friday">fre</string> + <string name="day_of_week_short_saturday">lör</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">O</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">f.m.</string> + <string name="pm">e.m.</string> + <string name="yesterday">igår</string> + <string name="today">idag</string> + <string name="tomorrow">imorgon</string> + + <string name="hour_minute_24">%-k.%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H.mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y %b</string> + <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">%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">%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 %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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-sv/donottranslate-cldr.xml b/core/res/res/values-sv/donottranslate-cldr.xml new file mode 100644 index 0000000..a6ffc9a --- /dev/null +++ b/core/res/res/values-sv/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">januari</string> + <string name="month_long_standalone_february">februari</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">april</string> + <string name="month_long_standalone_may">maj</string> + <string name="month_long_standalone_june">juni</string> + <string name="month_long_standalone_july">juli</string> + <string name="month_long_standalone_august">augusti</string> + <string name="month_long_standalone_september">september</string> + <string name="month_long_standalone_october">oktober</string> + <string name="month_long_standalone_november">november</string> + <string name="month_long_standalone_december">december</string> + + <string name="month_long_january">januari</string> + <string name="month_long_february">februari</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">april</string> + <string name="month_long_may">maj</string> + <string name="month_long_june">juni</string> + <string name="month_long_july">juli</string> + <string name="month_long_august">augusti</string> + <string name="month_long_september">september</string> + <string name="month_long_october">oktober</string> + <string name="month_long_november">november</string> + <string name="month_long_december">december</string> + + <string name="month_medium_january">jan</string> + <string name="month_medium_february">feb</string> + <string name="month_medium_march">mar</string> + <string name="month_medium_april">apr</string> + <string name="month_medium_may">maj</string> + <string name="month_medium_june">jun</string> + <string name="month_medium_july">jul</string> + <string name="month_medium_august">aug</string> + <string name="month_medium_september">sep</string> + <string name="month_medium_october">okt</string> + <string name="month_medium_november">nov</string> + <string name="month_medium_december">dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">söndag</string> + <string name="day_of_week_long_monday">måndag</string> + <string name="day_of_week_long_tuesday">tisdag</string> + <string name="day_of_week_long_wednesday">onsdag</string> + <string name="day_of_week_long_thursday">torsdag</string> + <string name="day_of_week_long_friday">fredag</string> + <string name="day_of_week_long_saturday">lördag</string> + + <string name="day_of_week_medium_sunday">sön</string> + <string name="day_of_week_medium_monday">mån</string> + <string name="day_of_week_medium_tuesday">tis</string> + <string name="day_of_week_medium_wednesday">ons</string> + <string name="day_of_week_medium_thursday">tors</string> + <string name="day_of_week_medium_friday">fre</string> + <string name="day_of_week_medium_saturday">lör</string> + + <string name="day_of_week_short_sunday">sön</string> + <string name="day_of_week_short_monday">mån</string> + <string name="day_of_week_short_tuesday">tis</string> + <string name="day_of_week_short_wednesday">ons</string> + <string name="day_of_week_short_thursday">tors</string> + <string name="day_of_week_short_friday">fre</string> + <string name="day_of_week_short_saturday">lör</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">O</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">L</string> + + <string name="am">f.m.</string> + <string name="pm">e.m.</string> + <string name="yesterday">igår</string> + <string name="today">idag</string> + <string name="tomorrow">imorgon</string> + + <string name="hour_minute_24">%-k.%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H.mm</string> + <string name="numeric_date">%Y-%m-%d</string> + <string name="numeric_date_format">yyyy-MM-dd</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%Y %B</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y %b</string> + <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">%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">%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 %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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-th-rTH/donottranslate-cldr.xml b/core/res/res/values-th-rTH/donottranslate-cldr.xml new file mode 100644 index 0000000..b3c76a3 --- /dev/null +++ b/core/res/res/values-th-rTH/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">มกราคม</string> + <string name="month_long_standalone_february">กุมภาพันธ์</string> + <string name="month_long_standalone_march">มีนาคม</string> + <string name="month_long_standalone_april">เมษายน</string> + <string name="month_long_standalone_may">พฤษภาคม</string> + <string name="month_long_standalone_june">มิถุนายน</string> + <string name="month_long_standalone_july">กรกฎาคม</string> + <string name="month_long_standalone_august">สิงหาคม</string> + <string name="month_long_standalone_september">กันยายน</string> + <string name="month_long_standalone_october">ตุลาคม</string> + <string name="month_long_standalone_november">พฤศจิกายน</string> + <string name="month_long_standalone_december">ธันวาคม</string> + + <string name="month_long_january">มกราคม</string> + <string name="month_long_february">กุมภาพันธ์</string> + <string name="month_long_march">มีนาคม</string> + <string name="month_long_april">เมษายน</string> + <string name="month_long_may">พฤษภาคม</string> + <string name="month_long_june">มิถุนายน</string> + <string name="month_long_july">กรกฎาคม</string> + <string name="month_long_august">สิงหาคม</string> + <string name="month_long_september">กันยายน</string> + <string name="month_long_october">ตุลาคม</string> + <string name="month_long_november">พฤศจิกายน</string> + <string name="month_long_december">ธันวาคม</string> + + <string name="month_medium_january">ม.ค.</string> + <string name="month_medium_february">ก.พ.</string> + <string name="month_medium_march">มี.ค.</string> + <string name="month_medium_april">เม.ย.</string> + <string name="month_medium_may">พ.ค.</string> + <string name="month_medium_june">มิ.ย.</string> + <string name="month_medium_july">ก.ค.</string> + <string name="month_medium_august">ส.ค.</string> + <string name="month_medium_september">ก.ย.</string> + <string name="month_medium_october">ต.ค.</string> + <string name="month_medium_november">พ.ย.</string> + <string name="month_medium_december">ธ.ค.</string> + + <string name="month_shortest_january">ม.ค.</string> + <string name="month_shortest_february">ก.พ.</string> + <string name="month_shortest_march">มี.ค.</string> + <string name="month_shortest_april">เม.ย.</string> + <string name="month_shortest_may">พ.ค.</string> + <string name="month_shortest_june">มิ.ย.</string> + <string name="month_shortest_july">ก.ค.</string> + <string name="month_shortest_august">ส.ค.</string> + <string name="month_shortest_september">ก.ย.</string> + <string name="month_shortest_october">ต.ค.</string> + <string name="month_shortest_november">พ.ย.</string> + <string name="month_shortest_december">ธ.ค.</string> + + <string name="day_of_week_long_sunday">วันอาทิตย์</string> + <string name="day_of_week_long_monday">วันจันทร์</string> + <string name="day_of_week_long_tuesday">วันอังคาร</string> + <string name="day_of_week_long_wednesday">วันพุธ</string> + <string name="day_of_week_long_thursday">วันพฤหัสบดี</string> + <string name="day_of_week_long_friday">วันศุกร์</string> + <string name="day_of_week_long_saturday">วันเสาร์</string> + + <string name="day_of_week_medium_sunday">อา.</string> + <string name="day_of_week_medium_monday">จ.</string> + <string name="day_of_week_medium_tuesday">อ.</string> + <string name="day_of_week_medium_wednesday">พ.</string> + <string name="day_of_week_medium_thursday">พฤ.</string> + <string name="day_of_week_medium_friday">ศ.</string> + <string name="day_of_week_medium_saturday">ส.</string> + + <string name="day_of_week_short_sunday">อา.</string> + <string name="day_of_week_short_monday">จ.</string> + <string name="day_of_week_short_tuesday">อ.</string> + <string name="day_of_week_short_wednesday">พ.</string> + <string name="day_of_week_short_thursday">พฤ.</string> + <string name="day_of_week_short_friday">ศ.</string> + <string name="day_of_week_short_saturday">ส.</string> + + <string name="day_of_week_shortest_sunday">อ</string> + <string name="day_of_week_shortest_monday">จ</string> + <string name="day_of_week_shortest_tuesday">อ</string> + <string name="day_of_week_shortest_wednesday">พ</string> + <string name="day_of_week_shortest_thursday">พ</string> + <string name="day_of_week_shortest_friday">ศ</string> + <string name="day_of_week_shortest_saturday">ส</string> + + <string name="am">ก่อนเที่ยง</string> + <string name="pm">หลังเที่ยง</string> + <string name="yesterday">เมื่อวาน</string> + <string name="today">วันนี้</string> + <string name="tomorrow">พรุ่งนี้</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%-e/%-m/%Y</string> + <string name="numeric_date_format">d/M/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%-e %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%M:%S, %-e %b %Y</string> + <string name="date_time">%2$s, %1$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-tr-rTR/donottranslate-cldr.xml b/core/res/res/values-tr-rTR/donottranslate-cldr.xml new file mode 100644 index 0000000..d612305 --- /dev/null +++ b/core/res/res/values-tr-rTR/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Ocak</string> + <string name="month_long_standalone_february">Şubat</string> + <string name="month_long_standalone_march">Mart</string> + <string name="month_long_standalone_april">Nisan</string> + <string name="month_long_standalone_may">Mayıs</string> + <string name="month_long_standalone_june">Haziran</string> + <string name="month_long_standalone_july">Temmuz</string> + <string name="month_long_standalone_august">Ağustos</string> + <string name="month_long_standalone_september">Eylül</string> + <string name="month_long_standalone_october">Ekim</string> + <string name="month_long_standalone_november">Kasım</string> + <string name="month_long_standalone_december">Aralık</string> + + <string name="month_long_january">Ocak</string> + <string name="month_long_february">Şubat</string> + <string name="month_long_march">Mart</string> + <string name="month_long_april">Nisan</string> + <string name="month_long_may">Mayıs</string> + <string name="month_long_june">Haziran</string> + <string name="month_long_july">Temmuz</string> + <string name="month_long_august">Ağustos</string> + <string name="month_long_september">Eylül</string> + <string name="month_long_october">Ekim</string> + <string name="month_long_november">Kasım</string> + <string name="month_long_december">Aralık</string> + + <string name="month_medium_january">Oca</string> + <string name="month_medium_february">Şub</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Nis</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Haz</string> + <string name="month_medium_july">Tem</string> + <string name="month_medium_august">Ağu</string> + <string name="month_medium_september">Eyl</string> + <string name="month_medium_october">Eki</string> + <string name="month_medium_november">Kas</string> + <string name="month_medium_december">Ara</string> + + <string name="month_shortest_january">O</string> + <string name="month_shortest_february">Ş</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">N</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">H</string> + <string name="month_shortest_july">T</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">E</string> + <string name="month_shortest_october">E</string> + <string name="month_shortest_november">K</string> + <string name="month_shortest_december">A</string> + + <string name="day_of_week_long_sunday">Pazar</string> + <string name="day_of_week_long_monday">Pazartesi</string> + <string name="day_of_week_long_tuesday">Salı</string> + <string name="day_of_week_long_wednesday">Çarşamba</string> + <string name="day_of_week_long_thursday">Perşembe</string> + <string name="day_of_week_long_friday">Cuma</string> + <string name="day_of_week_long_saturday">Cumartesi</string> + + <string name="day_of_week_medium_sunday">Paz</string> + <string name="day_of_week_medium_monday">Pzt</string> + <string name="day_of_week_medium_tuesday">Sal</string> + <string name="day_of_week_medium_wednesday">Çar</string> + <string name="day_of_week_medium_thursday">Per</string> + <string name="day_of_week_medium_friday">Cum</string> + <string name="day_of_week_medium_saturday">Cmt</string> + + <string name="day_of_week_short_sunday">Paz</string> + <string name="day_of_week_short_monday">Pzt</string> + <string name="day_of_week_short_tuesday">Sal</string> + <string name="day_of_week_short_wednesday">Çar</string> + <string name="day_of_week_short_thursday">Per</string> + <string name="day_of_week_short_friday">Cum</string> + <string name="day_of_week_short_saturday">Cmt</string> + + <string name="day_of_week_shortest_sunday">P</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">S</string> + <string name="day_of_week_shortest_wednesday">Ç</string> + <string name="day_of_week_shortest_thursday">P</string> + <string name="day_of_week_shortest_friday">C</string> + <string name="day_of_week_shortest_saturday">C</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Dün</string> + <string name="today">Bugün</string> + <string name="tomorrow">Yarın</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d %m %Y</string> + <string name="numeric_date_format">dd MM yyyy</string> + <string name="numeric_date_template">"%s %s %s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d %b %Y</string> + <string name="month_day">%d %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%d %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$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">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$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 %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string> + <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 %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> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s %1$s - %8$s %7$s y %6$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-tr/donottranslate-cldr.xml b/core/res/res/values-tr/donottranslate-cldr.xml new file mode 100644 index 0000000..d612305 --- /dev/null +++ b/core/res/res/values-tr/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Ocak</string> + <string name="month_long_standalone_february">Şubat</string> + <string name="month_long_standalone_march">Mart</string> + <string name="month_long_standalone_april">Nisan</string> + <string name="month_long_standalone_may">Mayıs</string> + <string name="month_long_standalone_june">Haziran</string> + <string name="month_long_standalone_july">Temmuz</string> + <string name="month_long_standalone_august">Ağustos</string> + <string name="month_long_standalone_september">Eylül</string> + <string name="month_long_standalone_october">Ekim</string> + <string name="month_long_standalone_november">Kasım</string> + <string name="month_long_standalone_december">Aralık</string> + + <string name="month_long_january">Ocak</string> + <string name="month_long_february">Şubat</string> + <string name="month_long_march">Mart</string> + <string name="month_long_april">Nisan</string> + <string name="month_long_may">Mayıs</string> + <string name="month_long_june">Haziran</string> + <string name="month_long_july">Temmuz</string> + <string name="month_long_august">Ağustos</string> + <string name="month_long_september">Eylül</string> + <string name="month_long_october">Ekim</string> + <string name="month_long_november">Kasım</string> + <string name="month_long_december">Aralık</string> + + <string name="month_medium_january">Oca</string> + <string name="month_medium_february">Şub</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Nis</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Haz</string> + <string name="month_medium_july">Tem</string> + <string name="month_medium_august">Ağu</string> + <string name="month_medium_september">Eyl</string> + <string name="month_medium_october">Eki</string> + <string name="month_medium_november">Kas</string> + <string name="month_medium_december">Ara</string> + + <string name="month_shortest_january">O</string> + <string name="month_shortest_february">Ş</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">N</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">H</string> + <string name="month_shortest_july">T</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">E</string> + <string name="month_shortest_october">E</string> + <string name="month_shortest_november">K</string> + <string name="month_shortest_december">A</string> + + <string name="day_of_week_long_sunday">Pazar</string> + <string name="day_of_week_long_monday">Pazartesi</string> + <string name="day_of_week_long_tuesday">Salı</string> + <string name="day_of_week_long_wednesday">Çarşamba</string> + <string name="day_of_week_long_thursday">Perşembe</string> + <string name="day_of_week_long_friday">Cuma</string> + <string name="day_of_week_long_saturday">Cumartesi</string> + + <string name="day_of_week_medium_sunday">Paz</string> + <string name="day_of_week_medium_monday">Pzt</string> + <string name="day_of_week_medium_tuesday">Sal</string> + <string name="day_of_week_medium_wednesday">Çar</string> + <string name="day_of_week_medium_thursday">Per</string> + <string name="day_of_week_medium_friday">Cum</string> + <string name="day_of_week_medium_saturday">Cmt</string> + + <string name="day_of_week_short_sunday">Paz</string> + <string name="day_of_week_short_monday">Pzt</string> + <string name="day_of_week_short_tuesday">Sal</string> + <string name="day_of_week_short_wednesday">Çar</string> + <string name="day_of_week_short_thursday">Per</string> + <string name="day_of_week_short_friday">Cum</string> + <string name="day_of_week_short_saturday">Cmt</string> + + <string name="day_of_week_shortest_sunday">P</string> + <string name="day_of_week_shortest_monday">P</string> + <string name="day_of_week_shortest_tuesday">S</string> + <string name="day_of_week_shortest_wednesday">Ç</string> + <string name="day_of_week_shortest_thursday">P</string> + <string name="day_of_week_shortest_friday">C</string> + <string name="day_of_week_shortest_saturday">C</string> + + <string name="am">AM</string> + <string name="pm">PM</string> + <string name="yesterday">Dün</string> + <string name="today">Bugün</string> + <string name="tomorrow">Yarın</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%d %m %Y</string> + <string name="numeric_date_format">dd MM yyyy</string> + <string name="numeric_date_template">"%s %s %s"</string> + <string name="month_day_year">%d %B %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %d %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%d %b %Y</string> + <string name="month_day">%d %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%d %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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 %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> + <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$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">%3$s %2$s - %8$s %7$s</string> + <string name="same_year_wday1_md1_wday2_md2">%3$s %2$s %1$s - %8$s %7$s %6$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 %3$s %2$s %1$s - %10$s %8$s %7$s %6$s</string> + <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 %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> + <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s %1$s - %8$s %7$s y %6$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml new file mode 100644 index 0000000..c51f8d1 --- /dev/null +++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">Січень</string> + <string name="month_long_standalone_february">Лютий</string> + <string name="month_long_standalone_march">Березень</string> + <string name="month_long_standalone_april">Квітень</string> + <string name="month_long_standalone_may">Травень</string> + <string name="month_long_standalone_june">Червень</string> + <string name="month_long_standalone_july">Липень</string> + <string name="month_long_standalone_august">Серпень</string> + <string name="month_long_standalone_september">Вересень</string> + <string name="month_long_standalone_october">Жовтень</string> + <string name="month_long_standalone_november">Листопад</string> + <string name="month_long_standalone_december">Грудень</string> + + <string name="month_long_january">січня</string> + <string name="month_long_february">лютого</string> + <string name="month_long_march">березня</string> + <string name="month_long_april">квітня</string> + <string name="month_long_may">травня</string> + <string name="month_long_june">червня</string> + <string name="month_long_july">липня</string> + <string name="month_long_august">серпня</string> + <string name="month_long_september">вересня</string> + <string name="month_long_october">жовтня</string> + <string name="month_long_november">листопада</string> + <string name="month_long_december">грудня</string> + + <string name="month_medium_january">січ.</string> + <string name="month_medium_february">лют.</string> + <string name="month_medium_march">бер.</string> + <string name="month_medium_april">квіт.</string> + <string name="month_medium_may">трав.</string> + <string name="month_medium_june">черв.</string> + <string name="month_medium_july">лип.</string> + <string name="month_medium_august">серп.</string> + <string name="month_medium_september">вер.</string> + <string name="month_medium_october">жовт.</string> + <string name="month_medium_november">лист.</string> + <string name="month_medium_december">груд.</string> + + <string name="month_shortest_january">С</string> + <string name="month_shortest_february">Л</string> + <string name="month_shortest_march">Б</string> + <string name="month_shortest_april">К</string> + <string name="month_shortest_may">Т</string> + <string name="month_shortest_june">Ч</string> + <string name="month_shortest_july">Л</string> + <string name="month_shortest_august">С</string> + <string name="month_shortest_september">В</string> + <string name="month_shortest_october">Ж</string> + <string name="month_shortest_november">Л</string> + <string name="month_shortest_december">Г</string> + + <string name="day_of_week_long_sunday">Неділя</string> + <string name="day_of_week_long_monday">Понеділок</string> + <string name="day_of_week_long_tuesday">Вівторок</string> + <string name="day_of_week_long_wednesday">Середа</string> + <string name="day_of_week_long_thursday">Четвер</string> + <string name="day_of_week_long_friday">Пʼятниця</string> + <string name="day_of_week_long_saturday">Субота</string> + + <string name="day_of_week_medium_sunday">Нд</string> + <string name="day_of_week_medium_monday">Пн</string> + <string name="day_of_week_medium_tuesday">Вт</string> + <string name="day_of_week_medium_wednesday">Ср</string> + <string name="day_of_week_medium_thursday">Чт</string> + <string name="day_of_week_medium_friday">Пт</string> + <string name="day_of_week_medium_saturday">Сб</string> + + <string name="day_of_week_short_sunday">Нд</string> + <string name="day_of_week_short_monday">Пн</string> + <string name="day_of_week_short_tuesday">Вт</string> + <string name="day_of_week_short_wednesday">Ср</string> + <string name="day_of_week_short_thursday">Чт</string> + <string name="day_of_week_short_friday">Пт</string> + <string name="day_of_week_short_saturday">Сб</string> + + <string name="day_of_week_shortest_sunday">Н</string> + <string name="day_of_week_shortest_monday">П</string> + <string name="day_of_week_shortest_tuesday">В</string> + <string name="day_of_week_shortest_wednesday">С</string> + <string name="day_of_week_shortest_thursday">Ч</string> + <string name="day_of_week_shortest_friday">П</string> + <string name="day_of_week_shortest_saturday">С</string> + + <string name="am">дп</string> + <string name="pm">пп</string> + <string name="yesterday">Вчора</string> + <string name="today">Сьогодні</string> + <string name="tomorrow">Завтра</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d.%m.%Y</string> + <string name="numeric_date_format">dd.MM.yyyy</string> + <string name="numeric_date_template">"%s.%s.%s"</string> + <string name="month_day_year">%-e %B %Y р.</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %-e %b %Y</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%-e %b %Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%-B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%-b %Y</string> + <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, %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="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">%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_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_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_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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml new file mode 100644 index 0000000..72ff8b6 --- /dev/null +++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">tháng một</string> + <string name="month_long_standalone_february">tháng hai</string> + <string name="month_long_standalone_march">tháng ba</string> + <string name="month_long_standalone_april">tháng tư</string> + <string name="month_long_standalone_may">tháng năm</string> + <string name="month_long_standalone_june">tháng sáu</string> + <string name="month_long_standalone_july">tháng bảy</string> + <string name="month_long_standalone_august">tháng tám</string> + <string name="month_long_standalone_september">tháng chín</string> + <string name="month_long_standalone_october">tháng mười</string> + <string name="month_long_standalone_november">tháng mười một</string> + <string name="month_long_standalone_december">tháng mười hai</string> + + <string name="month_long_january">tháng một</string> + <string name="month_long_february">tháng hai</string> + <string name="month_long_march">tháng ba</string> + <string name="month_long_april">tháng tư</string> + <string name="month_long_may">tháng năm</string> + <string name="month_long_june">tháng sáu</string> + <string name="month_long_july">tháng bảy</string> + <string name="month_long_august">tháng tám</string> + <string name="month_long_september">tháng chín</string> + <string name="month_long_october">tháng mười</string> + <string name="month_long_november">tháng mười một</string> + <string name="month_long_december">tháng mười hai</string> + + <string name="month_medium_january">thg 1</string> + <string name="month_medium_february">thg 2</string> + <string name="month_medium_march">thg 3</string> + <string name="month_medium_april">thg 4</string> + <string name="month_medium_may">thg 5</string> + <string name="month_medium_june">thg 6</string> + <string name="month_medium_july">thg 7</string> + <string name="month_medium_august">thg 8</string> + <string name="month_medium_september">thg 9</string> + <string name="month_medium_october">thg 10</string> + <string name="month_medium_november">thg 11</string> + <string name="month_medium_december">thg 12</string> + + <string name="month_shortest_january">1</string> + <string name="month_shortest_february">2</string> + <string name="month_shortest_march">3</string> + <string name="month_shortest_april">4</string> + <string name="month_shortest_may">5</string> + <string name="month_shortest_june">6</string> + <string name="month_shortest_july">7</string> + <string name="month_shortest_august">8</string> + <string name="month_shortest_september">9</string> + <string name="month_shortest_october">10</string> + <string name="month_shortest_november">11</string> + <string name="month_shortest_december">12</string> + + <string name="day_of_week_long_sunday">Chủ nhật</string> + <string name="day_of_week_long_monday">Thứ hai</string> + <string name="day_of_week_long_tuesday">Thứ ba</string> + <string name="day_of_week_long_wednesday">Thứ tư</string> + <string name="day_of_week_long_thursday">Thứ năm</string> + <string name="day_of_week_long_friday">Thứ sáu</string> + <string name="day_of_week_long_saturday">Thứ bảy</string> + + <string name="day_of_week_medium_sunday">CN</string> + <string name="day_of_week_medium_monday">Th 2</string> + <string name="day_of_week_medium_tuesday">Th 3</string> + <string name="day_of_week_medium_wednesday">Th 4</string> + <string name="day_of_week_medium_thursday">Th 5</string> + <string name="day_of_week_medium_friday">Th 6</string> + <string name="day_of_week_medium_saturday">Th 7</string> + + <string name="day_of_week_short_sunday">CN</string> + <string name="day_of_week_short_monday">Th 2</string> + <string name="day_of_week_short_tuesday">Th 3</string> + <string name="day_of_week_short_wednesday">Th 4</string> + <string name="day_of_week_short_thursday">Th 5</string> + <string name="day_of_week_short_friday">Th 6</string> + <string name="day_of_week_short_saturday">Th 7</string> + + <string name="day_of_week_shortest_sunday">1</string> + <string name="day_of_week_shortest_monday">2</string> + <string name="day_of_week_shortest_tuesday">3</string> + <string name="day_of_week_shortest_wednesday">4</string> + <string name="day_of_week_shortest_thursday">5</string> + <string name="day_of_week_shortest_friday">6</string> + <string name="day_of_week_shortest_saturday">7</string> + + <string name="am">SA</string> + <string name="pm">CH</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%-l:%M %p</string> + <string name="hour_minute_cap_ampm">%-l:%M %^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%d/%m/%Y</string> + <string name="numeric_date_format">dd/MM/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">Ngày %d tháng %-m năm %Y</string> + <string name="time_of_day">%H:%M:%S</string> + <string name="date_and_time">%d-%m-%Y %H:%M:%S</string> + <string name="date_time">%1$s %2$s</string> + <string name="time_date">%3$s %1$s</string> + <string name="abbrev_month_day_year">%d-%m-%Y</string> + <string name="month_day">%-e %B</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%-e %b</string> + <string name="abbrev_month">%b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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="date1_time1_date2_time2">%2$s %3$s - %5$s %6$s</string> + <string name="time_wday_date">%2$s %3$s %1$s</string> + <string name="wday_date">%2$s %3$s</string> + <string name="time_wday">%2$s %1$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_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 %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">Ngày %3$s tháng %2$s năm %4$s %5$s - 'Ngày %8$s tháng %7$s năm %9$s %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">Ngày %3$s tháng %2$s năm %4$s %5$s - 'Ngày %8$s tháng %7$s năm %9$s %10$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">Ngày %3$s tháng %2$s - Ngày %8$s tháng %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">Ngày %3$s tháng %2$s - Ngày %8$s tháng %7$s năm %9$s</string> + <string name="same_month_mdy1_mdy2">Ngày %3$s tháng %2$s - Ngày %8$s tháng M năm %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, ngày %3$s %2$s - %6$s, ngày %8$s %7$s năm %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml new file mode 100644 index 0000000..6d52d70 --- /dev/null +++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">一月</string> + <string name="month_long_standalone_february">二月</string> + <string name="month_long_standalone_march">三月</string> + <string name="month_long_standalone_april">四月</string> + <string name="month_long_standalone_may">五月</string> + <string name="month_long_standalone_june">六月</string> + <string name="month_long_standalone_july">七月</string> + <string name="month_long_standalone_august">八月</string> + <string name="month_long_standalone_september">九月</string> + <string name="month_long_standalone_october">十月</string> + <string name="month_long_standalone_november">十一月</string> + <string name="month_long_standalone_december">十二月</string> + + <string name="month_long_january">1月</string> + <string name="month_long_february">2月</string> + <string name="month_long_march">3月</string> + <string name="month_long_april">4月</string> + <string name="month_long_may">5月</string> + <string name="month_long_june">6月</string> + <string name="month_long_july">7月</string> + <string name="month_long_august">8月</string> + <string name="month_long_september">9月</string> + <string name="month_long_october">10月</string> + <string name="month_long_november">11月</string> + <string name="month_long_december">12月</string> + + <string name="month_medium_january">1月</string> + <string name="month_medium_february">2月</string> + <string name="month_medium_march">3月</string> + <string name="month_medium_april">4月</string> + <string name="month_medium_may">5月</string> + <string name="month_medium_june">6月</string> + <string name="month_medium_july">7月</string> + <string name="month_medium_august">8月</string> + <string name="month_medium_september">9月</string> + <string name="month_medium_october">10月</string> + <string name="month_medium_november">11月</string> + <string name="month_medium_december">12月</string> + + <string name="month_shortest_january">1月</string> + <string name="month_shortest_february">2月</string> + <string name="month_shortest_march">3月</string> + <string name="month_shortest_april">4月</string> + <string name="month_shortest_may">5月</string> + <string name="month_shortest_june">6月</string> + <string name="month_shortest_july">7月</string> + <string name="month_shortest_august">8月</string> + <string name="month_shortest_september">9月</string> + <string name="month_shortest_october">10月</string> + <string name="month_shortest_november">11月</string> + <string name="month_shortest_december">12月</string> + + <string name="day_of_week_long_sunday">星期日</string> + <string name="day_of_week_long_monday">星期一</string> + <string name="day_of_week_long_tuesday">星期二</string> + <string name="day_of_week_long_wednesday">星期三</string> + <string name="day_of_week_long_thursday">星期四</string> + <string name="day_of_week_long_friday">星期五</string> + <string name="day_of_week_long_saturday">星期六</string> + + <string name="day_of_week_medium_sunday">周日</string> + <string name="day_of_week_medium_monday">周一</string> + <string name="day_of_week_medium_tuesday">周二</string> + <string name="day_of_week_medium_wednesday">周三</string> + <string name="day_of_week_medium_thursday">周四</string> + <string name="day_of_week_medium_friday">周五</string> + <string name="day_of_week_medium_saturday">周六</string> + + <string name="day_of_week_short_sunday">周日</string> + <string name="day_of_week_short_monday">周一</string> + <string name="day_of_week_short_tuesday">周二</string> + <string name="day_of_week_short_wednesday">周三</string> + <string name="day_of_week_short_thursday">周四</string> + <string name="day_of_week_short_friday">周五</string> + <string name="day_of_week_short_saturday">周六</string> + + <string name="day_of_week_shortest_sunday">日</string> + <string name="day_of_week_shortest_monday">一</string> + <string name="day_of_week_shortest_tuesday">二</string> + <string name="day_of_week_shortest_wednesday">三</string> + <string name="day_of_week_shortest_thursday">四</string> + <string name="day_of_week_shortest_friday">五</string> + <string name="day_of_week_shortest_saturday">六</string> + + <string name="am">上午</string> + <string name="pm">下午</string> + <string name="yesterday">昨天</string> + <string name="today">今天</string> + <string name="tomorrow">明天</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%p%-l:%M</string> + <string name="hour_minute_cap_ampm">%p%-l:%M</string> + <string name="twelve_hour_time_format">ah:mm</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%-m-%-e</string> + <string name="numeric_date_format">yyyy-M-d</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%Y年%-m月%-e日</string> + <string name="time_of_day">%p%I:%M:%S</string> + <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y-%-m-%-e</string> + <string name="month_day">%B%-e日</string> + <string name="month">%-B</string> + <string name="month_year">%Y年%B</string> + <string name="abbrev_month_day">%b%-e日</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y年%b</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 54b0b97..3be8aa0 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -166,14 +166,10 @@ <string name="permdesc_changeConfiguration">"允许应用程序更改当前配置,例如语言设置或整体的字体大小。"</string> <string name="permlab_restartPackages">"重新启动其他应用程序"</string> <string name="permdesc_restartPackages">"允许应用程序强制重新启动其他应用程序。"</string> - <string name="permlab_setProcessForeground">"防止停止"</string> - <string name="permdesc_setProcessForeground">"允许应用程序在前台运行任何进程,因此该进程不能被终止。普通应用程序从不需要使用此权限。"</string> <string name="permlab_forceBack">"强制应用程序关闭"</string> <string name="permdesc_forceBack">"允许应用程序强制前台的任何活动关闭和重新开始。普通应用程序从不需要使用此权限。"</string> <string name="permlab_dump">"检索系统内部状态"</string> <string name="permdesc_dump">"允许应用程序检索系统的内部状态。恶意应用程序可能会借此检索通常它们本不需要的各种私有和安全信息。"</string> - <string name="permlab_addSystemService">"发布低级服务"</string> - <string name="permdesc_addSystemService">"允许应用程序发布自己的低级系统服务。恶意应用程序可能会借此攻击系统,以及盗取或破坏系统中的任何数据。"</string> <string name="permlab_runSetActivityWatcher">"监视和控制所有应用程序启动"</string> <string name="permdesc_runSetActivityWatcher">"允许应用程序监视和控制系统启动活动的方式。恶意应用程序可能会借此彻底损坏系统。此权限仅在开发时才需要,普通的手机应用不需要。"</string> <string name="permlab_broadcastPackageRemoved">"发送包删除的广播"</string> @@ -186,8 +182,6 @@ <string name="permdesc_setProcessLimit">"允许应用程序控制运行的进程数上限。普通应用程序从不需要使用此权限。"</string> <string name="permlab_setAlwaysFinish">"关闭所有后台应用程序"</string> <string name="permdesc_setAlwaysFinish">"允许应用程序控制活动是否始终是一转至后台就完成。普通应用程序从不需要使用此权限。"</string> - <string name="permlab_fotaUpdate">"自动安装系统更新"</string> - <string name="permdesc_fotaUpdate">"允许应用程序接收有关未决系统更新的通知并安装这些更新。恶意应用程序可能会借此通过未经授权的更新破坏系统,通常情况下,它们会干扰更新过程。"</string> <string name="permlab_batteryStats">"修改电池统计信息"</string> <string name="permdesc_batteryStats">"允许修改收集的电池统计信息。普通应用程序不能使用此权限。"</string> <string name="permlab_internalSystemWindow">"显示未授权的窗口"</string> @@ -424,9 +418,6 @@ <string name="lockscreen_glogin_password_hint">"密码"</string> <string name="lockscreen_glogin_submit_button">"登录"</string> <string name="lockscreen_glogin_invalid_input">"用户名或密码无效。"</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="AMPM">%P</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string> <string name="hour_cap_ampm">"<xliff:g id="AMPM">%p</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string> <string name="status_bar_clear_all_button">"清除通知"</string> @@ -458,9 +449,6 @@ <string name="menu_enter_shortcut_label">"Enter 键"</string> <string name="menu_delete_shortcut_label">"删除"</string> <string name="search_go">"搜索"</string> - <string name="today">"今天"</string> - <string name="yesterday">"昨天"</string> - <string name="tomorrow">"明天"</string> <string name="oneMonthDurationPast">"1 个月前"</string> <string name="beforeOneMonthDurationPast">"1 个月前"</string> <plurals name="num_seconds_ago"> @@ -542,13 +530,6 @@ <string name="weeks">"周"</string> <string name="year">"年"</string> <string name="years">"年"</string> - <string name="sunday">"周日"</string> - <string name="monday">"周一"</string> - <string name="tuesday">"周二"</string> - <string name="wednesday">"周三"</string> - <string name="thursday">"周四"</string> - <string name="friday">"周五"</string> - <string name="saturday">"周六"</string> <string name="every_weekday">"每个工作日(周一到周五)"</string> <string name="daily">"每天"</string> <string name="weekly">"每周的<xliff:g id="DAY">%s</xliff:g>"</string> @@ -558,137 +539,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"抱歉,该视频不适合在此设备上播放。"</string> <string name="VideoView_error_text_unknown">"很抱歉,此视频不能播放。"</string> <string name="VideoView_error_button">"确定"</string> - <string name="am">"上午"</string> - <string name="pm">"下午"</string> - <string name="numeric_date">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%m</xliff:g> 月 <xliff:g id="DAY">%d</xliff:g> 日"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> 至 <xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g><xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="DATE2">%5$s</xliff:g><xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g> <xliff:g id="TIME1">%3$s</xliff:g> 至 <xliff:g id="DATE2">%5$s</xliff:g> <xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g>至 <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> 至 <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g> <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="DAY">d</xliff:g>' 月 '<xliff:g id="MONTH">MMM</xliff:g>' 日'"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"中午"</string> <string name="Noon">"中午"</string> <string name="midnight">"午夜"</string> <string name="Midnight">"午夜"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string> - <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日 <xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至<xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日至 <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g>至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> 月 <xliff:g id="DAY1_0">%3$s</xliff:g> 日<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> 至 <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> 月 <xliff:g id="DAY2_1">%8$s</xliff:g> 日<xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string> - <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> 月"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"周日"</string> - <string name="day_of_week_long_monday">"周一"</string> - <string name="day_of_week_long_tuesday">"周二"</string> - <string name="day_of_week_long_wednesday">"周三"</string> - <string name="day_of_week_long_thursday">"周四"</string> - <string name="day_of_week_long_friday">"周五"</string> - <string name="day_of_week_long_saturday">"周六"</string> - <string name="day_of_week_medium_sunday">"周日"</string> - <string name="day_of_week_medium_monday">"周一"</string> - <string name="day_of_week_medium_tuesday">"周二"</string> - <string name="day_of_week_medium_wednesday">"周三"</string> - <string name="day_of_week_medium_thursday">"周四"</string> - <string name="day_of_week_medium_friday">"周五"</string> - <string name="day_of_week_medium_saturday">"周六"</string> - <string name="day_of_week_short_sunday">"周日"</string> - <string name="day_of_week_short_monday">"周一"</string> - <string name="day_of_week_short_tuesday">"周二"</string> - <string name="day_of_week_short_wednesday">"周三"</string> - <string name="day_of_week_short_thursday">"周四"</string> - <string name="day_of_week_short_friday">"周五"</string> - <string name="day_of_week_short_saturday">"周六"</string> - <string name="day_of_week_shorter_sunday">"周日"</string> - <string name="day_of_week_shorter_monday">"周一"</string> - <string name="day_of_week_shorter_tuesday">"周二"</string> - <string name="day_of_week_shorter_wednesday">"周三"</string> - <string name="day_of_week_shorter_thursday">"周四"</string> - <string name="day_of_week_shorter_friday">"周五"</string> - <string name="day_of_week_shorter_saturday">"周六"</string> - <string name="day_of_week_shortest_sunday">"周日"</string> - <string name="day_of_week_shortest_monday">"周一"</string> - <string name="day_of_week_shortest_tuesday">"周二"</string> - <string name="day_of_week_shortest_wednesday">"周三"</string> - <string name="day_of_week_shortest_thursday">"周四"</string> - <string name="day_of_week_shortest_friday">"周五"</string> - <string name="day_of_week_shortest_saturday">"周六"</string> - <string name="month_long_january">"1 月"</string> - <string name="month_long_february">"2 月"</string> - <string name="month_long_march">"3 月"</string> - <string name="month_long_april">"4 月"</string> - <string name="month_long_may">"5 月"</string> - <string name="month_long_june">"6 月"</string> - <string name="month_long_july">"7 月"</string> - <string name="month_long_august">"8 月"</string> - <string name="month_long_september">"9 月"</string> - <string name="month_long_october">"10 月"</string> - <string name="month_long_november">"11 月"</string> - <string name="month_long_december">"12 月"</string> - <string name="month_medium_january">"1 月"</string> - <string name="month_medium_february">"2 月"</string> - <string name="month_medium_march">"3 月"</string> - <string name="month_medium_april">"4 月"</string> - <string name="month_medium_may">"5 月"</string> - <string name="month_medium_june">"6 月"</string> - <string name="month_medium_july">"7 月"</string> - <string name="month_medium_august">"8 月"</string> - <string name="month_medium_september">"9 月"</string> - <string name="month_medium_october">"10 月"</string> - <string name="month_medium_november">"11 月"</string> - <string name="month_medium_december">"12 月"</string> - <string name="month_shortest_january">"1 月"</string> - <string name="month_shortest_february">"2 月"</string> - <string name="month_shortest_march">"3 月"</string> - <string name="month_shortest_april">"4 月"</string> - <string name="month_shortest_may">"5 月"</string> - <string name="month_shortest_june">"6 月"</string> - <string name="month_shortest_july">"7 月"</string> - <string name="month_shortest_august">"8 月"</string> - <string name="month_shortest_september">"9 月"</string> - <string name="month_shortest_october">"10 月"</string> - <string name="month_shortest_november">"11 月"</string> - <string name="month_shortest_december">"12 月"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"全选"</string> diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml new file mode 100644 index 0000000..6d52d70 --- /dev/null +++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">一月</string> + <string name="month_long_standalone_february">二月</string> + <string name="month_long_standalone_march">三月</string> + <string name="month_long_standalone_april">四月</string> + <string name="month_long_standalone_may">五月</string> + <string name="month_long_standalone_june">六月</string> + <string name="month_long_standalone_july">七月</string> + <string name="month_long_standalone_august">八月</string> + <string name="month_long_standalone_september">九月</string> + <string name="month_long_standalone_october">十月</string> + <string name="month_long_standalone_november">十一月</string> + <string name="month_long_standalone_december">十二月</string> + + <string name="month_long_january">1月</string> + <string name="month_long_february">2月</string> + <string name="month_long_march">3月</string> + <string name="month_long_april">4月</string> + <string name="month_long_may">5月</string> + <string name="month_long_june">6月</string> + <string name="month_long_july">7月</string> + <string name="month_long_august">8月</string> + <string name="month_long_september">9月</string> + <string name="month_long_october">10月</string> + <string name="month_long_november">11月</string> + <string name="month_long_december">12月</string> + + <string name="month_medium_january">1月</string> + <string name="month_medium_february">2月</string> + <string name="month_medium_march">3月</string> + <string name="month_medium_april">4月</string> + <string name="month_medium_may">5月</string> + <string name="month_medium_june">6月</string> + <string name="month_medium_july">7月</string> + <string name="month_medium_august">8月</string> + <string name="month_medium_september">9月</string> + <string name="month_medium_october">10月</string> + <string name="month_medium_november">11月</string> + <string name="month_medium_december">12月</string> + + <string name="month_shortest_january">1月</string> + <string name="month_shortest_february">2月</string> + <string name="month_shortest_march">3月</string> + <string name="month_shortest_april">4月</string> + <string name="month_shortest_may">5月</string> + <string name="month_shortest_june">6月</string> + <string name="month_shortest_july">7月</string> + <string name="month_shortest_august">8月</string> + <string name="month_shortest_september">9月</string> + <string name="month_shortest_october">10月</string> + <string name="month_shortest_november">11月</string> + <string name="month_shortest_december">12月</string> + + <string name="day_of_week_long_sunday">星期日</string> + <string name="day_of_week_long_monday">星期一</string> + <string name="day_of_week_long_tuesday">星期二</string> + <string name="day_of_week_long_wednesday">星期三</string> + <string name="day_of_week_long_thursday">星期四</string> + <string name="day_of_week_long_friday">星期五</string> + <string name="day_of_week_long_saturday">星期六</string> + + <string name="day_of_week_medium_sunday">周日</string> + <string name="day_of_week_medium_monday">周一</string> + <string name="day_of_week_medium_tuesday">周二</string> + <string name="day_of_week_medium_wednesday">周三</string> + <string name="day_of_week_medium_thursday">周四</string> + <string name="day_of_week_medium_friday">周五</string> + <string name="day_of_week_medium_saturday">周六</string> + + <string name="day_of_week_short_sunday">周日</string> + <string name="day_of_week_short_monday">周一</string> + <string name="day_of_week_short_tuesday">周二</string> + <string name="day_of_week_short_wednesday">周三</string> + <string name="day_of_week_short_thursday">周四</string> + <string name="day_of_week_short_friday">周五</string> + <string name="day_of_week_short_saturday">周六</string> + + <string name="day_of_week_shortest_sunday">日</string> + <string name="day_of_week_shortest_monday">一</string> + <string name="day_of_week_shortest_tuesday">二</string> + <string name="day_of_week_shortest_wednesday">三</string> + <string name="day_of_week_shortest_thursday">四</string> + <string name="day_of_week_shortest_friday">五</string> + <string name="day_of_week_shortest_saturday">六</string> + + <string name="am">上午</string> + <string name="pm">下午</string> + <string name="yesterday">昨天</string> + <string name="today">今天</string> + <string name="tomorrow">明天</string> + + <string name="hour_minute_24">%-k:%M</string> + <string name="hour_minute_ampm">%p%-l:%M</string> + <string name="hour_minute_cap_ampm">%p%-l:%M</string> + <string name="twelve_hour_time_format">ah:mm</string> + <string name="twenty_four_hour_time_format">H:mm</string> + <string name="numeric_date">%Y-%-m-%-e</string> + <string name="numeric_date_format">yyyy-M-d</string> + <string name="numeric_date_template">"%s-%s-%s"</string> + <string name="month_day_year">%Y年%-m月%-e日</string> + <string name="time_of_day">%p%I:%M:%S</string> + <string name="date_and_time">%p%I:%M:%S %Y-%-m-%-e</string> + <string name="date_time">%2$s %1$s</string> + <string name="time_date">%1$s %3$s</string> + <string name="abbrev_month_day_year">%Y-%-m-%-e</string> + <string name="month_day">%B%-e日</string> + <string name="month">%-B</string> + <string name="month_year">%Y年%B</string> + <string name="abbrev_month_day">%b%-e日</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%Y年%b</string> + <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 %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> + <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 %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">%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 %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 %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">%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> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 514e304..8cace66 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -161,14 +161,10 @@ <string name="permdesc_changeConfiguration">"允許應用程式變更目前設定,例如:地區設定或字型大小。"</string> <string name="permlab_restartPackages">"重新啟動其他應用程式"</string> <string name="permdesc_restartPackages">"允許應用程式強制重新啟動其他應用程式。"</string> - <string name="permlab_setProcessForeground">"保持已停止狀態"</string> - <string name="permdesc_setProcessForeground">"允許應用程式在前端執行任何程序 (無法中止)。一般應用程式不需要此功能。"</string> <string name="permlab_forceBack">"強制關閉應用程式"</string> <string name="permdesc_forceBack">"允許應用程式強制關閉在前端運作的活動並返回。一般應用程式不需要此功能。"</string> <string name="permlab_dump">"接收系統內部狀態"</string> <string name="permdesc_dump">"允許應用程式取得系統內部狀態。請注意:惡意程式可能利用此功能,不當取得私人或安全性資料。"</string> - <string name="permlab_addSystemService">"發行低階服務"</string> - <string name="permdesc_addSystemService">"允許應用程式發行自有低階系統服務。請注意:惡意程式可能利用此功能綁架系統或偷取、竄改資料內容。"</string> <string name="permlab_runSetActivityWatcher">"監視控制所有應用程式啟動狀態。"</string> <string name="permdesc_runSetActivityWatcher">"允許應用程式監控管理系統啟動活動。請注意:惡意程式可能因此癱瘓整個系統。此權限只在開發時需要,一般手機使用不需要此權限。"</string> <string name="permlab_broadcastPackageRemoved">"傳送程式已移除廣播"</string> @@ -181,8 +177,6 @@ <string name="permdesc_setProcessLimit">"允許應用程式控制可使用的最大執行緒。一般應用程式不需要此功能。"</string> <string name="permlab_setAlwaysFinish">"關閉所有背景程式"</string> <string name="permdesc_setAlwaysFinish">"允許應用程式控制哪些活動在被移到背景執行時,儘速結束。一般應用程式不需要此功能。"</string> - <string name="permlab_fotaUpdate">"自動安裝系統更新"</string> - <string name="permdesc_fotaUpdate">"允許應用程式接收可安裝系統更新的通知,並啟動安裝。請注意:惡意程式可能透過未授權的更新竄改系統,或干擾更新程序。"</string> <string name="permlab_batteryStats">"編輯電池狀態"</string> <string name="permdesc_batteryStats">"允許修改電池狀態。一般應用程式不會使用此功能。"</string> <string name="permlab_internalSystemWindow">"顯示未授權視窗"</string> @@ -418,9 +412,6 @@ <string name="lockscreen_glogin_password_hint">"密碼"</string> <string name="lockscreen_glogin_submit_button">"登入"</string> <string name="lockscreen_glogin_invalid_input">"使用者名稱或密碼錯誤。"</string> - <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string> - <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> - <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string> <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="status_bar_clear_all_button">"清除通知"</string> @@ -452,9 +443,6 @@ <string name="menu_enter_shortcut_label">"輸入"</string> <string name="menu_delete_shortcut_label">"刪除"</string> <string name="search_go">"搜尋"</string> - <string name="today">"今天"</string> - <string name="yesterday">"昨天"</string> - <string name="tomorrow">"明天"</string> <string name="oneMonthDurationPast">"1 個月以前"</string> <string name="beforeOneMonthDurationPast">"1 個月前"</string> <plurals name="num_seconds_ago"> @@ -536,13 +524,6 @@ <string name="weeks">"週"</string> <string name="year">"年"</string> <string name="years">"年"</string> - <string name="sunday">"星期日"</string> - <string name="monday">"星期一"</string> - <string name="tuesday">"星期二"</string> - <string name="wednesday">"星期三"</string> - <string name="thursday">"星期四"</string> - <string name="friday">"星期五"</string> - <string name="saturday">"星期六"</string> <string name="every_weekday">"每天 (週一至週五)"</string> <string name="daily">"每天"</string> <string name="weekly">"每週<xliff:g id="DAY">%s</xliff:g>"</string> @@ -552,137 +533,15 @@ <string name="VideoView_error_text_invalid_progressive_playback">"很抱歉,影片格式無效,裝置無法進行串流處理。"</string> <string name="VideoView_error_text_unknown">"很抱歉,此影片無法播放。"</string> <string name="VideoView_error_button">"確定"</string> - <string name="am">"上午"</string> - <string name="pm">"下午"</string> - <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="WEEKDAY2">%4$s</xliff:g>,<xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="wday1_date1_wday2_date2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="WEEKDAY2">%4$s</xliff:g>"</string> - <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>,<xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>,<xliff:g id="TIME2">%6$s</xliff:g>"</string> - <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string> - <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string> - <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g>,<xliff:g id="WEEKDAY">%2$s</xliff:g>,<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g>,<xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> - <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>,<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>,<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>' 日'"</string> - <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> - <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>' 日'"</string> - <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"中午"</string> <string name="Noon">"中午"</string> <string name="midnight">"午夜"</string> <string name="Midnight">"午夜"</string> - <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string> <!-- no translation found for month (7026169712234774086) --> <skip /> - <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string> - <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年<xliff:g id="MONTH">%B</xliff:g>"</string> - <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日,<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string> - <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_mdy1_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>,<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>,<xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_mdy1_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 – <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_mdy1_mdy2">"<xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 – <xliff:g id="DAY2">%8$s</xliff:g> 日"</string> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>"</string> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> 日 <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g> 日 <xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="YEAR1">%4$s</xliff:g> 年 <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> 日,<xliff:g id="WEEKDAY1">%1$s</xliff:g>,<xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="YEAR2">%9$s</xliff:g> 年 <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> 日,<xliff:g id="WEEKDAY2">%6$s</xliff:g>,<xliff:g id="TIME2">%10$s</xliff:g>"</string> - <string name="abbrev_month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string> - <string name="abbrev_month_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%b</xliff:g>"</string> - <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g> 日"</string> <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> - <string name="day_of_week_long_sunday">"星期日"</string> - <string name="day_of_week_long_monday">"星期一"</string> - <string name="day_of_week_long_tuesday">"星期二"</string> - <string name="day_of_week_long_wednesday">"星期三"</string> - <string name="day_of_week_long_thursday">"星期四"</string> - <string name="day_of_week_long_friday">"星期五"</string> - <string name="day_of_week_long_saturday">"星期六"</string> - <string name="day_of_week_medium_sunday">"週日"</string> - <string name="day_of_week_medium_monday">"週一"</string> - <string name="day_of_week_medium_tuesday">"週二"</string> - <string name="day_of_week_medium_wednesday">"週三"</string> - <string name="day_of_week_medium_thursday">"週四"</string> - <string name="day_of_week_medium_friday">"五"</string> - <string name="day_of_week_medium_saturday">"週六"</string> - <string name="day_of_week_short_sunday">"日"</string> - <string name="day_of_week_short_monday">"一"</string> - <string name="day_of_week_short_tuesday">"二"</string> - <string name="day_of_week_short_wednesday">"三"</string> - <string name="day_of_week_short_thursday">"週四"</string> - <string name="day_of_week_short_friday">"五"</string> - <string name="day_of_week_short_saturday">"六"</string> - <string name="day_of_week_shorter_sunday">"日"</string> - <string name="day_of_week_shorter_monday">"一"</string> - <string name="day_of_week_shorter_tuesday">"二"</string> - <string name="day_of_week_shorter_wednesday">"三"</string> - <string name="day_of_week_shorter_thursday">"四"</string> - <string name="day_of_week_shorter_friday">"五"</string> - <string name="day_of_week_shorter_saturday">"六"</string> - <string name="day_of_week_shortest_sunday">"日"</string> - <string name="day_of_week_shortest_monday">"一"</string> - <string name="day_of_week_shortest_tuesday">"二"</string> - <string name="day_of_week_shortest_wednesday">"三"</string> - <string name="day_of_week_shortest_thursday">"四"</string> - <string name="day_of_week_shortest_friday">"五"</string> - <string name="day_of_week_shortest_saturday">"六"</string> - <string name="month_long_january">"1 月"</string> - <string name="month_long_february">"2 月"</string> - <string name="month_long_march">"3 月"</string> - <string name="month_long_april">"4 月"</string> - <string name="month_long_may">"5 月"</string> - <string name="month_long_june">"6 月"</string> - <string name="month_long_july">"7 月"</string> - <string name="month_long_august">"8 月"</string> - <string name="month_long_september">"9 月"</string> - <string name="month_long_october">"10 月"</string> - <string name="month_long_november">"11 月"</string> - <string name="month_long_december">"12 月"</string> - <string name="month_medium_january">"1 月"</string> - <string name="month_medium_february">"2 月"</string> - <string name="month_medium_march">"3 月"</string> - <string name="month_medium_april">"4 月"</string> - <string name="month_medium_may">"5 月"</string> - <string name="month_medium_june">"6 月"</string> - <string name="month_medium_july">"7 月"</string> - <string name="month_medium_august">"8 月"</string> - <string name="month_medium_september">"9 月"</string> - <string name="month_medium_october">"10 月"</string> - <string name="month_medium_november">"11 月"</string> - <string name="month_medium_december">"12 月"</string> - <string name="month_shortest_january">"1"</string> - <string name="month_shortest_february">"2"</string> - <string name="month_shortest_march">"3"</string> - <string name="month_shortest_april">"4"</string> - <string name="month_shortest_may">"5"</string> - <string name="month_shortest_june">"6"</string> - <string name="month_shortest_july">"7"</string> - <string name="month_shortest_august">"8"</string> - <string name="month_shortest_september">"9"</string> - <string name="month_shortest_october">"10"</string> - <string name="month_shortest_november">"11"</string> - <string name="month_shortest_december">"12"</string> <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll">"全部選取"</string> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index 7db73f0..66f0e82 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -110,7 +110,10 @@ <item><xliff:g id="id">alarm_clock</xliff:g></item> <item><xliff:g id="id">battery</xliff:g></item> <item><xliff:g id="id">phone_signal</xliff:g></item> + <item><xliff:g id="id">phone_evdo_signal</xliff:g></item> <item><xliff:g id="id">data_connection</xliff:g></item> + <item><xliff:g id="id">cdma_eri</xliff:g></item> + <item><xliff:g id="id">tty</xliff:g></item> <item><xliff:g id="id">volume</xliff:g></item> <item><xliff:g id="id">mute</xliff:g></item> <item><xliff:g id="id">speakerphone</xliff:g></item> @@ -122,4 +125,14 @@ <item><xliff:g id="id">sync_failing</xliff:g></item> <item><xliff:g id="id">ime</xliff:g></item> </string-array> + + <!-- Do not translate. Each string points to the component name of an ACTION_WEB_SEARCH + handling activity. On startup if there were no preferred ACTION_WEB_SEARCH handlers, + the first component from this list which is found to be installed is set as the + preferred activity. --> + <string-array name="default_web_search_providers"> + <item>com.google.android.providers.enhancedgooglesearch/.Launcher</item> + <item>com.android.googlesearch/.GoogleSearch</item> + <item>com.android.websearch/.Search.1</item> + </string-array> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 633a831..6f2a5d3 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4,9 +4,9 @@ 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. @@ -64,10 +64,13 @@ <!-- Inverse hint text color --> <attr name="textColorHintInverse" format="reference|color" /> - + <!-- Bright text color. Only differentiates based on the disabled state. --> <attr name="textColorPrimaryDisableOnly" format="reference|color" /> + <!-- Bright inverse text color. Only differentiates based on the disabled state. --> + <attr name="textColorPrimaryInverseDisableOnly" format="reference|color" /> + <!-- Bright text color. This does not differentiate the disabled state. As an example, buttons use this since they display the disabled state via the background and not the foreground text color. --> @@ -80,6 +83,11 @@ <!-- Dim inverse text color. This does not differentiate the disabled state. --> <attr name="textColorSecondaryInverseNoDisable" format="reference|color" /> + <!-- Text color for urls in search suggestions, used by things like global search and the browser. @hide --> + <attr name="textColorSearchUrl" format="reference|color" /> + <!-- Search widget more corpus result item background. --> + <attr name="searchWidgetCorpusItemBackground" format="reference|color" /> + <!-- Text color, typeface, size, and style for "large" text. Defaults to primary text color. --> <attr name="textAppearanceLarge" format="reference" /> <!-- Text color, typeface, size, and style for "medium" text. Defaults to primary text color. --> @@ -94,27 +102,28 @@ <!-- Text color, typeface, size, and style for "small" inverse text. Defaults to secondary inverse text color. --> <attr name="textAppearanceSmallInverse" format="reference" /> - <!-- Text color, typeface, size, and style for system search result title. Defaults to primary inverse text color. @hide --> - <attr name="textAppearanceSearchResultTitle" format="reference" /> - <!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. @hide --> + <!-- Text color, typeface, size, and style for system search result title. Defaults to primary inverse text color. @hide --> + <attr name="textAppearanceSearchResultTitle" format="reference" /> + <!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. @hide --> <attr name="textAppearanceSearchResultSubtitle" format="reference" /> + <!-- Text color, typeface, size, and style for the text inside of a button. --> <attr name="textAppearanceButton" format="reference" /> - + <!-- A styled string, specifying the style to be used for showing inline candidate text when composing with an input method. The text itself will be ignored, but the style spans will be applied to the candidate text as it is edited. --> <attr name="candidatesTextStyleSpans" format="reference|string" /> - + <!-- Drawable to use for check marks --> <attr name="textCheckMark" format="reference" /> <attr name="textCheckMarkInverse" format="reference" /> <!-- Drawable to use for multiple choice indicators--> <attr name="listChoiceIndicatorMultiple" format="reference" /> - + <!-- Drawable to use for single choice indicators--> <attr name="listChoiceIndicatorSingle" format="reference" /> @@ -139,7 +148,7 @@ <!-- Gallery styles --> <!-- ============== --> <eat-comment /> - + <!-- The preferred background for gallery items. This should be set as the background of any Views you provide from the Adapter. --> <attr name="galleryItemBackground" format="reference" /> @@ -152,27 +161,27 @@ <!-- The preferred list item height --> <attr name="listPreferredItemHeight" format="dimension" /> <!-- The drawable for the list divider --> - <!-- The list item height for search results. @hide --> - <attr name="searchResultListItemHeight" format="dimension" /> + <!-- The list item height for search results. @hide --> + <attr name="searchResultListItemHeight" format="dimension" /> <attr name="listDivider" format="reference" /> <!-- TextView style for list separators. --> <attr name="listSeparatorTextViewStyle" format="reference" /> <!-- The preferred left padding for an expandable list item (for child-specific layouts, use expandableListPreferredChildPaddingLeft). This takes into account - the indicator that will be shown to next to the item. --> + the indicator that will be shown to next to the item. --> <attr name="expandableListPreferredItemPaddingLeft" format="dimension" /> <!-- The preferred left padding for an expandable list item that is a child. - If this is not provided, it defaults to the expandableListPreferredItemPaddingLeft. --> + If this is not provided, it defaults to the expandableListPreferredItemPaddingLeft. --> <attr name="expandableListPreferredChildPaddingLeft" format="dimension" /> <!-- The preferred left bound for an expandable list item's indicator. For a child-specific - indicator, use expandableListPreferredChildIndicatorLeft. --> + indicator, use expandableListPreferredChildIndicatorLeft. --> <attr name="expandableListPreferredItemIndicatorLeft" format="dimension" /> <!-- The preferred right bound for an expandable list item's indicator. For a child-specific - indicator, use expandableListPreferredChildIndicatorRight. --> + indicator, use expandableListPreferredChildIndicatorRight. --> <attr name="expandableListPreferredItemIndicatorRight" format="dimension" /> - <!-- The preferred left bound for an expandable list child's indicator. --> + <!-- The preferred left bound for an expandable list child's indicator. --> <attr name="expandableListPreferredChildIndicatorLeft" format="dimension" /> - <!-- The preferred right bound for an expandable list child's indicator. --> + <!-- The preferred right bound for an expandable list child's indicator. --> <attr name="expandableListPreferredChildIndicatorRight" format="dimension" /> <!-- ============= --> @@ -221,7 +230,7 @@ any of the attributes defined by {@link android.R.styleable#WindowAnimation}. --> <attr name="windowAnimationStyle" format="reference" /> - + <!-- Defines the default soft input state that this window would like when it is displayed. --> <attr name="windowSoftInputMode"> @@ -243,7 +252,7 @@ <!-- Always make the soft input area visible when this window has input focus. --> <flag name="stateAlwaysVisible" value="5" /> - + <!-- The window resize/pan adjustment has not been specified, the system will automatically select between resize and pan modes, depending @@ -270,7 +279,7 @@ use the window's theme to show a preview of it before your actual instance is shown to the user. --> <attr name="windowDisablePreview" format="boolean" /> - + <!-- Flag indicating that this window should not be displayed at all. The default value is false; if set to true, and this window is the main window of an Activity, then it will never actually @@ -278,13 +287,13 @@ must immediately quit without waiting for user interaction, because there will be no such interaction coming. --> <attr name="windowNoDisplay" format="boolean" /> - + <!-- ============ --> <!-- Alert Dialog styles --> <!-- ============ --> <eat-comment /> <attr name="alertDialogStyle" format="reference" /> - + <!-- ============ --> <!-- Panel styles --> <!-- ============ --> @@ -320,6 +329,8 @@ <attr name="expandableListViewStyle" format="reference" /> <!-- Default Gallery style. --> <attr name="galleryStyle" format="reference" /> + <!-- Default GestureOverlayView style. --> + <attr name="gestureOverlayViewStyle" format="reference" /> <!-- Default GridView style. --> <attr name="gridViewStyle" format="reference" /> <!-- The style resource to use for an ImageButton --> @@ -342,6 +353,12 @@ <attr name="progressBarStyleSmallTitle" format="reference" /> <!-- Large ProgressBar style. This is a large circular progress bar. --> <attr name="progressBarStyleLarge" format="reference" /> + <!-- Inverse ProgressBar style. This is a medium circular progress bar. --> + <attr name="progressBarStyleInverse" format="reference" /> + <!-- Small inverse ProgressBar style. This is a small circular progress bar. --> + <attr name="progressBarStyleSmallInverse" format="reference" /> + <!-- Large inverse ProgressBar style. This is a large circular progress bar. --> + <attr name="progressBarStyleLargeInverse" format="reference" /> <!-- Default SeekBar style. --> <attr name="seekBarStyle" format="reference" /> <!-- Default RatingBar style. --> @@ -381,7 +398,7 @@ <!-- Preference styles --> <!-- =================== --> <eat-comment /> - + <!-- Default style for PreferenceScreen. --> <attr name="preferenceScreenStyle" format="reference" /> <!-- Default style for PreferenceCategory. --> @@ -402,7 +419,7 @@ <attr name="ringtonePreferenceStyle" format="reference" /> <!-- The preference layout that has the child/tabbed effect. --> <attr name="preferenceLayoutChild" format="reference" /> - + </declare-styleable> <!-- **************************************************************** --> @@ -420,7 +437,7 @@ </ul> --> <attr name="textSize" format="dimension" /> - + <!-- Default text typeface. --> <attr name="typeface"> <enum name="normal" value="0" /> @@ -428,26 +445,26 @@ <enum name="serif" value="2" /> <enum name="monospace" value="3" /> </attr> - + <!-- Default text typeface style. --> <attr name="textStyle"> <flag name="normal" value="0" /> <flag name="bold" value="1" /> <flag name="italic" value="2" /> </attr> - + <!-- Color of text (usually same as colorForeground). --> <attr name="textColor" format="reference|color" /> - + <!-- Color of highlighted text. --> <attr name="textColorHighlight" format="reference|color" /> - + <!-- Color of hint text (displayed when the field is empty). --> <attr name="textColorHint" format="reference|color" /> - + <!-- Color of link text (URLs). --> <attr name="textColorLink" format="reference|color" /> - + <!-- Where to ellipsize text. --> <attr name="ellipsize"> <enum name="none" value="0" /> @@ -456,7 +473,7 @@ <enum name="end" value="3" /> <enum name="marquee" value="4" /> </attr> - + <!-- The type of data being placed in a text field, used to help an input method decide how to let the user enter text. The constants here correspond to those defined by @@ -663,9 +680,9 @@ <attr name="x" format="dimension" /> <!-- A coordinate in the Y dimension. --> <attr name="y" format="dimension" /> - - <!-- Specifies how to place an object, both - its x and y axis, within a larger containing object. --> + + <!-- Specifies how to place the content of an object, both + on the x and y axis, within the object itself. --> <attr name="gravity"> <!-- Push object to the top of its container, not changing its size. --> <flag name="top" value="0x30" /> @@ -721,8 +738,7 @@ <attr name="entries" format="reference" /> <!-- Standard gravity constant that a child can supply to its parent. - Defines how to place an object, both - its x and y axis, within a larger containing object. --> + Defines how to place the view, both its x and y axis, within its parent view group. --> <attr name="layout_gravity"> <!-- Push object to the top of its container, not changing its size. --> <flag name="top" value="0x30" /> @@ -769,11 +785,11 @@ <!-- ========================== --> <eat-comment /> - <!-- This enum provides the same keycode values as can be found in + <!-- This enum provides the same keycode values as can be found in {@link android.view.KeyEvent} --> <attr name="keycode"> <enum name="KEYCODE_UNKNOWN" value="0" /> - <enum name="KEYCODE_SOFT_LEFT" value="1" /> + <enum name="KEYCODE_SOFT_LEFT" value="1" /> <enum name="KEYCODE_SOFT_RIGHT" value="2" /> <enum name="KEYCODE_HOME" value="3" /> <enum name="KEYCODE_BACK" value="4" /> @@ -906,7 +922,7 @@ <attr name="bottomMedium" format="reference|color" /> <attr name="centerMedium" format="reference|color" /> </declare-styleable> - + <!-- Window animation class attributes. --> <declare-styleable name="WindowAnimation"> <!-- The animation used when a window is being added. --> @@ -950,7 +966,7 @@ allows you to later retrieve the view with <code>findViewById(R.id.my_id)</code>. --> <attr name="id" format="reference" /> - + <!-- Supply a tag for this view containing a String, to be retrieved later with {@link android.view.View#getTag View.getTag()} or searched for with {@link android.view.View#findViewWithTag @@ -958,7 +974,7 @@ IDs (through the android:id attribute) instead of tags because they are faster and allow for compile-time type checking. --> <attr name="tag" format="string" /> - + <!-- The initial horizontal scroll offset, in pixels.--> <attr name="scrollX" format="dimension" /> @@ -972,7 +988,7 @@ <attr name="background" format="reference|color" /> <!-- Sets the padding, in pixels, of all four edges. Padding is defined as - space between the edges of the view and the view's content. A views size + space between the edges of the view and the view's content. A views size will include it's padding. If a {@link android.R.attr#background} is provided, the padding will initially be set to that (0 if the drawable does not have padding). Explicitly setting a padding value @@ -1027,12 +1043,12 @@ </attr> <!-- Controls the scrollbar style and position. The scrollbars can be overlaid or - inset. When inset, they add to the padding of the view. And the - scrollbars can be drawn inside the padding area or on the edge of - the view. For example, if a view has a background drawable and you - want to draw the scrollbars inside the padding specified by the - drawable, you can use insideOverlay or insideInset. If you want them - to appear at the edge of the view, ignoring the padding, then you can + inset. When inset, they add to the padding of the view. And the + scrollbars can be drawn inside the padding area or on the edge of + the view. For example, if a view has a background drawable and you + want to draw the scrollbars inside the padding specified by the + drawable, you can use insideOverlay or insideInset. If you want them + to appear at the edge of the view, ignoring the padding, then you can use outsideOverlay or outsideInset.--> <attr name="scrollbarStyle"> <!-- Inside the padding and overlaid --> @@ -1044,14 +1060,14 @@ <!-- Edge of the view and inset --> <enum name="outsideInset" value="0x03000000" /> </attr> - + <!-- Set this if the view will serve as a scrolling container, meaing that it can be resized to shrink its overall window so that there will be space for an input method. If not set, the default value will be true if "scrollbars" has the vertical scrollbar set, else it will be false. --> <attr name="isScrollContainer" format="boolean" /> - + <!-- Sets the width of vertical scrollbars and height of horizontal scrollbars. --> <attr name="scrollbarSize" format="dimension" /> <!-- Defines the horizontal scrollbar thumb drawable. --> @@ -1113,10 +1129,10 @@ <!-- Defines whether this view reacts to click events. --> <attr name="clickable" format="boolean" /> - + <!-- Defines whether this view reacts to long click events. --> <attr name="longClickable" format="boolean" /> - + <!-- If unset, no state will be saved for this view when it is being frozen. The default is true, allowing the view to be saved (however it also must have an ID assigned to it for its @@ -1124,7 +1140,7 @@ state for this view, not for its children which may still be saved. --> <attr name="saveEnabled" format="boolean" /> - + <!-- Defines the quality of translucent drawing caches. This property is used only when the drawing cache is enabled and translucent. The default value is auto. --> <attr name="drawingCacheQuality"> @@ -1142,16 +1158,16 @@ <!-- Controls whether the view's window should keep the screen on while visible. --> <attr name="keepScreenOn" format="boolean" /> - + <!-- When this attribute is set to true, the view gets its drawable state (focused, pressed, etc.) from its direct parent rather than from itself. --> <attr name="duplicateParentState" format="boolean" /> - + <!-- Defines the minimum height of the view. It is not guaranteed the view will be able to achieve this minimum height (for example, if its parent layout constrains it with less available height). --> <attr name="minHeight" /> - + <!-- Defines the minimum width of the view. It is not guaranteed the view will be able to achieve this minimum width (for example, if its parent layout constrains it with less available width). --> @@ -1165,6 +1181,11 @@ enabled for events such as long presses. --> <attr name="hapticFeedbackEnabled" format="boolean" /> + <!-- Defines text that briefly describes content of the view. This property is used + primarily for accessibility. Since some views do not have textual + representation this attribute can be used for providing such. --> + <attr name="contentDescription" format="string" localization="suggested" /> + <!-- Name of the method in this View's context to invoke when the view is clicked. This name must correspond to a public method that takes exactly one parameter of type View. For instance, if you specify @@ -1208,7 +1229,7 @@ <flag name="animation" value="0x1" /> <!-- The drawing cache is persisted after a scroll. --> <flag name="scrolling" value="0x2" /> - <!-- The drawing cache is always persisted. --> + <!-- The drawing cache is always persisted. --> <flag name="all" value="0x3" /> </attr> <!-- Defines whether the ViewGroup should always draw its children using their @@ -1321,7 +1342,7 @@ method should be considered an option as the default. --> <attr name="isDefault" format="boolean" /> </declare-styleable> - + <!-- =============================== --> <!-- Widget package class attributes --> <!-- =============================== --> @@ -1330,7 +1351,7 @@ <declare-styleable name="AbsListView"> <!-- Drawable used to indicate the currently selected item in the list. --> <attr name="listSelector" format="color|reference" /> - <!-- When set to true, the selector will be drawn over the selected item. + <!-- When set to true, the selector will be drawn over the selected item. Otherwise the selector is drawn behind the selected item. The default value is false. --> <attr name="drawSelectorOnTop" format="boolean" /> @@ -1353,13 +1374,13 @@ already visible on screen. --> <enum name="normal" value="1" /> <!-- The list will automatically scroll to the bottom, no matter what items - are currently visible. --> + are currently visible. --> <enum name="alwaysScroll" value="2" /> </attr> <!-- Indicates that this list will always be drawn on top of solid, single-color opaque background. This allows the list to optimize drawing. --> <attr name="cacheColorHint" format="color" /> - <!-- Enables the fast scroll thumb that can be dragged to quickly scroll through + <!-- Enables the fast scroll thumb that can be dragged to quickly scroll through the list. --> <attr name="fastScrollEnabled" format="boolean" /> <!-- When set to true, the list will use a more refined calculation @@ -1448,7 +1469,7 @@ <!-- Defines whether the foreground drawable should be drawn inside the padding. This property is turned on by default. --> <attr name="foregroundInsidePadding" format="boolean" /> - <!-- Determines whether to measure all children or just those in + <!-- Determines whether to measure all children or just those in the VISIBLE or INVISIBLE state when measuring. Defaults to false. --> <attr name="measureAllChildren" format="boolean" /> </declare-styleable> @@ -1458,14 +1479,14 @@ <!-- Indicator shown beside the child View. This can be a stateful Drawable. --> <attr name="childIndicator" format="reference" /> <!-- The left bound for an item's indicator. To specify a left bound specific to children, - use childIndicatorLeft. --> + use childIndicatorLeft. --> <attr name="indicatorLeft" format="dimension" /> <!-- The right bound for an item's indicator. To specify a right bound specific to children, - use childIndicatorRight. --> + use childIndicatorRight. --> <attr name="indicatorRight" format="dimension" /> - <!-- The left bound for a child's indicator. --> + <!-- The left bound for a child's indicator. --> <attr name="childIndicatorLeft" format="dimension" /> - <!-- The right bound for a child's indicator. --> + <!-- The right bound for a child's indicator. --> <attr name="childIndicatorRight" format="dimension" /> <!-- Drawable or color that is used as a divider for children. (It will drawn below and above child items.) The height of this will be the same as @@ -1516,10 +1537,10 @@ <!-- Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable. --> <attr name="adjustViewBounds" format="boolean" /> - <!-- An optional argument to supply a maximum width for this view. + <!-- An optional argument to supply a maximum width for this view. See {see android.widget.ImageView#setMaxWidth} for details. --> <attr name="maxWidth" format="dimension" /> - <!-- An optional argument to supply a maximum height for this view. + <!-- An optional argument to supply a maximum height for this view. See {see android.widget.ImageView#setMaxHeight} for details. --> <attr name="maxHeight" format="dimension" /> <!-- Set a tinting color for the image --> @@ -1573,9 +1594,9 @@ <!-- Height of the divider. Will use the intrinsic height of the divider if this is not specified. --> <attr name="dividerHeight" format="dimension" /> - <!-- Defines the choice behavior for the List. By default, Lists do not have + <!-- Defines the choice behavior for the ListView. By default, lists do not have any choice behavior. By setting the choiceMode to singleChoice, the List - allows up to one item to be in a chosen state. By setting the choiceMode to + allows up to one item to be in a chosen state. By setting the choiceMode to multipleChoice, the list allows any number of items to be chosen. --> <attr name="choiceMode"> <!-- Normal list that does not indicate choices --> @@ -1620,7 +1641,7 @@ <!-- 'More' icon --> <attr name="moreIcon" format="reference" /> </declare-styleable> - + <declare-styleable name="ProgressBar"> <!-- Defines the maximum value the progress can take. --> <attr name="max" format="integer" /> @@ -1653,27 +1674,27 @@ <attr name="maxWidth" /> <attr name="minHeight" format="dimension" /> <attr name="maxHeight" /> - <attr name="interpolator" format="reference" /> + <attr name="interpolator" format="reference" /> </declare-styleable> - + <declare-styleable name="SeekBar"> - <!-- Draws the thumb on a seekbar --> + <!-- Draws the thumb on a seekbar --> <attr name="thumb" format="reference" /> <!-- An offset for the thumb that allows it to extend out of the range of the track. --> - <attr name="thumbOffset" format="dimension" /> + <attr name="thumbOffset" format="dimension" /> </declare-styleable> - + <declare-styleable name="RatingBar"> - <!-- The number of stars (or rating items) to show. --> - <attr name="numStars" format="integer" /> - <!-- The rating to set by default. --> - <attr name="rating" format="float" /> - <!-- The step size of the rating. --> - <attr name="stepSize" format="float" /> - <!-- Whether this rating bar is an indicator (and non-changeable by the user). --> - <attr name="isIndicator" format="boolean" /> + <!-- The number of stars (or rating items) to show. --> + <attr name="numStars" format="integer" /> + <!-- The rating to set by default. --> + <attr name="rating" format="float" /> + <!-- The step size of the rating. --> + <attr name="stepSize" format="float" /> + <!-- Whether this rating bar is an indicator (and non-changeable by the user). --> + <attr name="isIndicator" format="boolean" /> </declare-styleable> - + <declare-styleable name="RadioGroup"> <!-- The id of the child radio button that should be checked by default within this radio group. --> @@ -1695,7 +1716,7 @@ indices are ignored. You can shrink all columns by using the value "*" instead. Note that a column can be marked stretchable and shrinkable at the same time. --> - <attr name="shrinkColumns" format="string" /> + <attr name="shrinkColumns" format="string" /> <!-- The 0 based index of the columns to collapse. The column indices must be separated by a comma: 1, 2, 5. Illegal and duplicate indices are ignored. --> @@ -1796,7 +1817,7 @@ <attr name="minEms" format="integer" min="0" /> <!-- Makes the TextView be at least this many pixels wide --> <attr name="minWidth" /> - <!-- Specifies how to align the text by the view's x and/or y axis + <!-- Specifies how to align the text by the view's x and/or y axis when the text is smaller than the view. --> <attr name="gravity" /> <!-- Whether the text is allowed to be wider than the view (and @@ -1814,10 +1835,10 @@ attribute. (If both singleLine and inputType are supplied, the inputType flags will override the value of singleLine.) {@deprecated This attribute is deprecated and is replaced by the textMultiLine flag - in the inputType attribute. Use caution when altering existing layouts, as the - default value of singeLine is false (multi-line mode), but if you specify any - value for inputType, the default is single-line mode. (If both singleLine and - inputType attributes are found, the inputType flags will override the value of + in the inputType attribute. Use caution when altering existing layouts, as the + default value of singeLine is false (multi-line mode), but if you specify any + value for inputType, the default is single-line mode. (If both singleLine and + inputType attributes are found, the inputType flags will override the value of singleLine.) } --> <attr name="singleLine" format="boolean" /> <!-- {@deprecated Use state_enabled instead.} --> @@ -1921,7 +1942,7 @@ <attr name="lineSpacingExtra" format="dimension" /> <!-- Extra spacing between lines of text, as a multiplier. --> <attr name="lineSpacingMultiplier" format="float" /> - <!-- The number of times to repeat the marquee animation. Only applied if the + <!-- The number of times to repeat the marquee animation. Only applied if the TextView has marquee enabled. --> <attr name="marqueeRepeatLimit" format="integer"> <!-- Indicates that marquee should repeat indefinitely --> @@ -1986,6 +2007,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"> @@ -2012,7 +2043,7 @@ <!-- The prompt to display when the spinner's dialog is shown. --> <attr name="prompt" format="reference" /> </declare-styleable> - <declare-styleable name="DatePicker"> + <declare-styleable name="DatePicker"> <!-- The first year (inclusive) i.e. 1940 --> <attr name="startYear" format="integer" /> <!-- The last year (inclusive) i.e. 2010 --> @@ -2053,6 +2084,44 @@ <attr name="animateOnClick" format="boolean" /> </declare-styleable> + <!-- GestureOverlayView specific attributes. These attributes are used to configure + a GestureOverlayView from XML. --> + <declare-styleable name="GestureOverlayView"> + <!-- Width of the stroke used to draw the gesture. --> + <attr name="gestureStrokeWidth" format="float" /> + <!-- Color used to draw a gesture. --> + <attr name="gestureColor" format="color" /> + <!-- Color used to draw the user's strokes until we are sure it's a gesture. --> + <attr name="uncertainGestureColor" format="color" /> + <!-- Time, in milliseconds, to wait before the gesture fades out after the user + is done drawing it. --> + <attr name="fadeOffset" format="integer" /> + <!-- Duration, in milliseconds, of the fade out effect after the user is done + drawing a gesture. --> + <attr name="fadeDuration" format="integer" /> + <!-- Defines the type of strokes that define a gesture. --> + <attr name="gestureStrokeType"> + <!-- A gesture is made of only one stroke. --> + <enum name="single" value="0" /> + <!-- A gesture is made of multiple strokes. --> + <enum name="multiple" value="1" /> + </attr> + <!-- Minimum length of a stroke before it is recognized as a gesture. --> + <attr name="gestureStrokeLengthThreshold" format="float" /> + <!-- Squareness threshold of a stroke before it is recognized as a gesture. --> + <attr name="gestureStrokeSquarenessThreshold" format="float" /> + <!-- Minimum curve angle a stroke must contain before it is recognized as a gesture. --> + <attr name="gestureStrokeAngleThreshold" format="float" /> + <!-- Defines whether the overlay should intercept the motion events when a gesture + is recognized. --> + <attr name="eventsInterceptionEnabled" format="boolean" /> + <!-- Defines whether the gesture will automatically fade out after being recognized. --> + <attr name="fadeEnabled" format="boolean" /> + <!-- Indicates whether horizontal (when the orientation is vertical) or vertical + (when orientation is horizontal) strokes automatically define a gesture. --> + <attr name="orientation" /> + </declare-styleable> + <!-- ======================================= --> <!-- Widget package parent layout attributes --> <!-- ======================================= --> @@ -2136,7 +2205,7 @@ {@link android.graphics.drawable.Drawable#setVisible} --> <attr name="visible" format="boolean" /> </declare-styleable> - + <declare-styleable name="StateListDrawable"> <attr name="visible" /> <!-- If true, allows the drawable's padding to change based on the @@ -2152,7 +2221,7 @@ current state. --> <attr name="constantSize" format="boolean" /> </declare-styleable> - + <declare-styleable name="AnimationDrawable"> <attr name="visible" /> <attr name="variablePadding" /> @@ -2161,15 +2230,15 @@ restarting at the first frame after the last has finished. --> <attr name="oneshot" format="boolean" /> </declare-styleable> - + <declare-styleable name="AnimationDrawableItem"> <!-- Amount of time (in milliseconds) to display this frame. --> - <attr name="duration" format="integer" /> + <attr name="duration" format="integer" /> <!-- Reference to a drawable resource to use for the frame. If not given, the drawable must be defined by the first child tag. --> <attr name="drawable" format="reference" /> </declare-styleable> - + <declare-styleable name="GradientDrawable"> <attr name="visible" /> <attr name="shape"> @@ -2192,18 +2261,18 @@ <attr name="thickness" format="dimension" /> <attr name="useLevel" /> </declare-styleable> - + <declare-styleable name="GradientDrawableSize"> <attr name="width" /> <attr name="height" /> </declare-styleable> - + <declare-styleable name="GradientDrawableGradient"> <attr name="startColor" format="color" /> <!-- Optional center color. For linear gradients, use centerX or centerY to place the center color. --> <attr name="centerColor" format="color" /> <attr name="endColor" format="color" /> - <attr name="useLevel" format="boolean" /> + <attr name="useLevel" format="boolean" /> <attr name="angle" format="float" /> <attr name="type"> <enum name="linear" value="0" /> @@ -2214,18 +2283,18 @@ <attr name="centerY" format="float|fraction" /> <attr name="gradientRadius" format="float|fraction" /> </declare-styleable> - + <declare-styleable name="GradientDrawableSolid"> <attr name="color" format="color" /> </declare-styleable> - + <declare-styleable name="GradientDrawableStroke"> <attr name="width" /> <attr name="color" /> <attr name="dashWidth" format="dimension" /> <attr name="dashGap" format="dimension" /> </declare-styleable> - + <declare-styleable name="DrawableCorners"> <attr name="radius" format="dimension" /> <attr name="topLeftRadius" format="dimension" /> @@ -2233,14 +2302,14 @@ <attr name="bottomLeftRadius" format="dimension" /> <attr name="bottomRightRadius" format="dimension" /> </declare-styleable> - + <declare-styleable name="GradientDrawablePadding"> <attr name="left" format="dimension" /> <attr name="top" format="dimension" /> <attr name="right" format="dimension" /> <attr name="bottom" format="dimension" /> </declare-styleable> - + <declare-styleable name="LayerDrawableItem"> <attr name="left" /> <attr name="top" /> @@ -2249,7 +2318,7 @@ <attr name="drawable" /> <attr name="id" /> </declare-styleable> - + <declare-styleable name="LevelListDrawableItem"> <!-- The minimum level allowed for this item. --> <attr name="minLevel" format="integer" /> @@ -2257,7 +2326,7 @@ <attr name="maxLevel" format="integer" /> <attr name="drawable" /> </declare-styleable> - + <declare-styleable name="RotateDrawable"> <attr name="visible" /> <attr name="fromDegrees" format="float" /> @@ -2267,6 +2336,15 @@ <attr name="drawable" /> </declare-styleable> + <declare-styleable name="AnimatedRotateDrawable"> + <attr name="visible" /> + <attr name="frameDuration" format="integer" /> + <attr name="framesCount" format="integer" /> + <attr name="pivotX" /> + <attr name="pivotY" /> + <attr name="drawable" /> + </declare-styleable> + <declare-styleable name="InsetDrawable"> <attr name="visible" /> <attr name="drawable" /> @@ -2413,7 +2491,7 @@ <declare-styleable name="AnimationSet"> <attr name="shareInterpolator" format="boolean" /> </declare-styleable> - + <declare-styleable name="Animation"> <!-- Defines the interpolator used to smooth the animation movement in time. --> <attr name="interpolator" /> @@ -2456,14 +2534,14 @@ <enum name="bottom" value="-1" /> </attr> </declare-styleable> - + <declare-styleable name="RotateAnimation"> <attr name="fromDegrees" /> <attr name="toDegrees" /> <attr name="pivotX" /> <attr name="pivotY" /> </declare-styleable> - + <declare-styleable name="ScaleAnimation"> <attr name="fromXScale" format="float" /> <attr name="toXScale" format="float" /> @@ -2472,14 +2550,14 @@ <attr name="pivotX" /> <attr name="pivotY" /> </declare-styleable> - + <declare-styleable name="TranslateAnimation"> <attr name="fromXDelta" format="float|fraction" /> <attr name="toXDelta" format="float|fraction" /> <attr name="fromYDelta" format="float|fraction" /> <attr name="toYDelta" format="float|fraction" /> </declare-styleable> - + <declare-styleable name="AlphaAnimation"> <attr name="fromAlpha" format="float" /> <attr name="toAlpha" format="float" /> @@ -2541,12 +2619,12 @@ <!-- This is the amount of deceleration to add when easing in. --> <attr name="factor" format="float" /> </declare-styleable> - + <declare-styleable name="DecelerateInterpolator"> <!-- This is the amount of acceleration to add when easing out. --> <attr name="factor" /> </declare-styleable> - + <declare-styleable name="CycleInterpolator"> <attr name="cycles" format="float" /> </declare-styleable> @@ -2656,18 +2734,18 @@ </declare-styleable> <!-- State array representing an expandable list child's indicator. --> <declare-styleable name="ExpandableListChildIndicatorState"> - <!-- State identifier indicating the child is the last child within its group. --> + <!-- State identifier indicating the child is the last child within its group. --> <attr name="state_last" /> </declare-styleable> <!-- State array representing an expandable list group's indicator. --> <declare-styleable name="ExpandableListGroupIndicatorState"> - <!-- State identifier indicating the group is expanded. --> + <!-- State identifier indicating the group is expanded. --> <attr name="state_expanded" format="boolean" /> - <!-- State identifier indicating the group is empty (has no children). --> + <!-- State identifier indicating the group is empty (has no children). --> <attr name="state_empty" format="boolean" /> </declare-styleable> <declare-styleable name="PopupWindowBackgroundState"> - <!-- State identifier indicating the popup will be above the anchor. --> + <!-- State identifier indicating the popup will be above the anchor. --> <attr name="state_above_anchor" format="boolean" /> </declare-styleable> @@ -2677,7 +2755,7 @@ <eat-comment /> <!-- Searchable activities and applications must provide search configuration information - in an XML file, typically called searchable.xml. This file is referenced in your manifest. + in an XML file, typically called searchable.xml. This file is referenced in your manifest. For a more in-depth discussion of search configuration, please refer to {@link android.app.SearchManager}. --> <declare-styleable name="Searchable"> @@ -2686,29 +2764,29 @@ plain text. This is a reference to a drawable (icon) resource. <i>Optional attribute.</i> --> <attr name="icon" /> - <!-- This is the user-displayed name of the searchable activity. <i>Required + <!-- This is the user-displayed name of the searchable activity. <i>Required attribute.</i> --> <attr name="label" /> - <!-- If supplied, this string will be displayed as a hint to the user. <i>Optional + <!-- If supplied, this string will be displayed as a hint to the user. <i>Optional attribute.</i> --> <attr name="hint" /> <!-- If supplied, this string will be displayed as the text of the "Search" button. - <i>Optional attribute.</i> + <i>Optional attribute.</i> {@deprecated This will create a non-standard UI appearance, because the search bar UI is changing to use only icons for its buttons.}--> <attr name="searchButtonText" format="string" /> <attr name="inputType" /> <attr name="imeOptions" /> - + <!-- Additional features are controlled by mode bits in this field. Omitting - this field, or setting to zero, provides default behavior. <i>Optional attribute.</i> + this field, or setting to zero, provides default behavior. <i>Optional attribute.</i> --> <attr name="searchMode"> <!-- If set, this flag enables the display of the search target (label) within the search bar. If neither bad mode is selected, no badge will be shown. --> <flag name="showSearchLabelAsBadge" value="0x04" /> <!-- If set, this flag enables the display of the search target (icon) within the - search bar. (Note, overrides showSearchLabel) If neither bad mode is selected, + search bar. (Note, overrides showSearchLabel) If neither bad mode is selected, no badge will be shown.--> <flag name="showSearchIconAsBadge" value="0x08" /> <!-- If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA to @@ -2722,11 +2800,11 @@ values are not suitable for user inspection and editing. --> <flag name="queryRewriteFromText" value="0x20" /> </attr> - + <!-- Voice search features are controlled by mode bits in this field. Omitting this field, or setting to zero, provides default behavior. If showVoiceSearchButton is set, then launchWebSearch or launchRecognizer must - also be set. <i>Optional attribute.</i> + also be set. <i>Optional attribute.</i> --> <attr name="voiceSearchMode"> <!-- If set, display a voice search button. This only takes effect if voice search is @@ -2745,9 +2823,9 @@ </attr> <!-- If provided, this specifies the language model that should be used by the - voice recognition system. See - {@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL } for more information. - If not provided, the default value + voice recognition system. See + {@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL } for more information. + If not provided, the default value {@link android.speech.RecognizerIntent#LANGUAGE_MODEL_FREE_FORM } will be used. --> <attr name="voiceLanguageModel" format="string" /> <!-- If provided, this specifies a prompt that will be displayed during voice input. --> @@ -2757,14 +2835,14 @@ <attr name="voiceLanguage" format="string" /> <!-- If provided, enforces the maximum number of results to return, including the "best" result which will always be provided as the SEARCH intent's primary query. Must be one - or greater. If not provided, the recognizer will choose how many results to return. + or greater. If not provided, the recognizer will choose how many results to return. --> <attr name="voiceMaxResults" format="integer" /> <!-- If provided, this is the trigger indicating that the searchable activity provides suggestions as well. The value must be a fully-qualified content provider - authority (e.g. "com.example.android.apis.SuggestionProvider") and should match the - "android:authorities" tag in your content provider's manifest entry. <i>Optional + authority (e.g. "com.example.android.apis.SuggestionProvider") and should match the + "android:authorities" tag in your content provider's manifest entry. <i>Optional attribute.</i> --> <attr name="searchSuggestAuthority" format="string" /> <!-- If provided, this will be inserted in the suggestions query Uri, after the authority @@ -2772,31 +2850,44 @@ --> <attr name="searchSuggestPath" format="string" /> <!-- If provided, suggestion queries will be passed into your query function - as the <i>selection</i> parameter. Typically this will be a WHERE clause for your - database, and will contain a single question mark, which represents the actual query + as the <i>selection</i> parameter. Typically this will be a WHERE clause for your + database, and will contain a single question mark, which represents the actual query string that has been typed by the user. If not provided, then the user query text - will be appended to the query Uri (after an additional "/".) <i>Optional + will be appended to the query Uri (after an additional "/".) <i>Optional attribute.</i> --> <attr name="searchSuggestSelection" format="string" /> - <!-- If provided, and not overridden by an action in the selected suggestion, this + <!-- If provided, and not overridden by an action in the selected suggestion, this string will be placed in the action field of the {@link android.content.Intent Intent} when the user clicks a suggestion. <i>Optional attribute.</i> --> <attr name="searchSuggestIntentAction" format="string" /> - <!-- If provided, and not overridden by an action in the selected suggestion, this - string will be placed in the data field of the {@link android.content.Intent Intent} + <!-- If provided, and not overridden by an action in the selected suggestion, this + string will be placed in the data field of the {@link android.content.Intent Intent} when the user clicks a suggestion. <i>Optional attribute.</i> --> <attr name="searchSuggestIntentData" format="string" /> - + <!-- If provided, this is the minimum number of characters needed to trigger search suggestions. The default value is 0. <i>Optional attribute.</i> --> <attr name="searchSuggestThreshold" format="integer" /> - + <!-- If provided and <code>true</code>, this searchable activity will be included in any global lists of search targets. The default value is <code>false</code>. <i>Optional attribute.</i>. --> <attr name="includeInGlobalSearch" format="boolean" /> + + <!-- If provided and <code>true</code>, this searchable activity will be invoked for all + queries in a particular session. If set to <code>false</code> and the activity + returned zero results for a query, it will not be invoked again in that session for + supersets of that zero-results query. For example, if the activity returned zero + results for "bo", it would not be queried again for "bob". + The default value is <code>false</code>. <i>Optional attribute.</i>. --> + <attr name="queryAfterZeroResults" format="boolean" /> + <!-- If provided, this string will be used to describe the searchable item in the + searchable items settings within system search settings. <i>Optional + attribute.</i> --> + <attr name="searchSettingsDescription" format="string" /> + </declare-styleable> <!-- In order to process special action keys during search, you must define them using @@ -2806,70 +2897,70 @@ <declare-styleable name="SearchableActionKey"> <!-- This attribute denotes the action key you wish to respond to. Note that not all action keys are actually supported using this mechanism, as many of them are - used for typing, navigation, or system functions. This will be added to the + used for typing, navigation, or system functions. This will be added to the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your - searchable activity. To examine the key code, use + searchable activity. To examine the key code, use {@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}. - <p>Note, in addition to the keycode, you must also provide one or more of the action + <p>Note, in addition to the keycode, you must also provide one or more of the action specifier attributes. <i>Required attribute.</i> --> <attr name="keycode" /> - + <!-- If you wish to handle an action key during normal search query entry, you - must define an action string here. This will be added to the + must define an action string here. This will be added to the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your - searchable activity. To examine the string, use + searchable activity. To examine the string, use {@link android.content.Intent#getStringExtra getStringExtra(SearchManager.ACTION_MSG)}. <i>Optional attribute.</i> --> <attr name="queryActionMsg" format="string" /> - + <!-- If you wish to handle an action key while a suggestion is being displayed <i>and selected</i>, there are two ways to handle this. If <i>all</i> of your suggestions - can handle the action key, you can simply define the action message using this - attribute. This will be added to the + can handle the action key, you can simply define the action message using this + attribute. This will be added to the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your - searchable activity. To examine the string, use + searchable activity. To examine the string, use {@link android.content.Intent#getStringExtra getStringExtra(SearchManager.ACTION_MSG)}. <i>Optional attribute.</i> --> <attr name="suggestActionMsg" format="string" /> - + <!-- If you wish to handle an action key while a suggestion is being displayed <i>and - selected</i>, but you do not wish to enable this action key for every suggestion, + selected</i>, but you do not wish to enable this action key for every suggestion, then you can use this attribute to control it on a suggestion-by-suggestion basis. - First, you must define a column (and name it here) where your suggestions will include + First, you must define a column (and name it here) where your suggestions will include the action string. Then, in your content provider, you must provide this column, and when desired, provide data in this column. - The search manager will look at your suggestion cursor, using the string - provided here in order to select a column, and will use that to select a string from - the cursor. That string will be added to the - {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to - your searchable activity. To examine the string, use - {@link android.content.Intent#getStringExtra + The search manager will look at your suggestion cursor, using the string + provided here in order to select a column, and will use that to select a string from + the cursor. That string will be added to the + {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to + your searchable activity. To examine the string, use + {@link android.content.Intent#getStringExtra getStringExtra(SearchManager.ACTION_MSG)}. <i>If the data does not exist for the selection suggestion, the action key will be ignored.</i><i>Optional attribute.</i> --> <attr name="suggestActionMsgColumn" format="string" /> </declare-styleable> - + <!-- ***************************************************************** --> <!-- Support for MapView. --> <!-- ***************************************************************** --> <eat-comment /> - + <!-- The set of attributes for a MapView. --> <declare-styleable name="MapView"> <!-- Value is a string that specifies the Maps API Key to use. --> <attr name="apiKey" format="string" /> </declare-styleable> - + <!-- **************************************************************** --> <!-- Menu XML inflation. --> <!-- **************************************************************** --> <eat-comment /> - + <!-- Base attributes that are available to all Menu objects. --> <declare-styleable name="Menu"> </declare-styleable> - + <!-- Base attributes that are available to all groups. --> <declare-styleable name="MenuGroup"> @@ -2888,11 +2979,11 @@ <!-- Items are alternative actions. --> <enum name="alternative" value="0x00040000" /> </attr> - + <!-- The order within the category applied to all items within this group. (This will be or'ed with the category attribute.) --> <attr name="orderInCategory" format="integer" /> - + <!-- Whether the items are capable of displaying a check mark. --> <attr name="checkableBehavior"> <!-- The items are not checkable. --> @@ -2903,7 +2994,7 @@ this group. --> <enum name="single" value="2" /> </attr> - + <!-- Whether the items are shown/visible. --> <attr name="visible" /> @@ -2917,7 +3008,7 @@ <!-- The ID of the item. --> <attr name="id" /> - + <!-- The category applied to the item. (This will be or'ed with the orderInCategory attribute.) --> <attr name="menuCategory" /> @@ -2928,15 +3019,15 @@ <!-- The title associated with the item. --> <attr name="title" format="string" /> - + <!-- The condensed title associated with the item. This is used in situations where the normal title may be too long to be displayed. --> <attr name="titleCondensed" format="string" /> <!-- The icon associated with this item. This icon will not always be shown, so - the title should be sufficient in describing this item. --> + the title should be sufficient in describing this item. --> <attr name="icon" /> - + <!-- The alphabetic shortcut key. This is the shortcut when using a keyboard with alphabetic keys. --> <attr name="alphabeticShortcut" format="string" /> @@ -2944,14 +3035,14 @@ <!-- The numeric shortcut key. This is the shortcut when using a numeric (e.g., 12-key) keyboard. --> <attr name="numericShortcut" format="string" /> - + <!-- Whether the item is capable of displaying a check mark. --> <attr name="checkable" format="boolean" /> - - <!-- Whether the item is checked. Note that you must first have enabled checking with + + <!-- Whether the item is checked. Note that you must first have enabled checking with the checkable attribute or else the check mark will not appear. --> <attr name="checked" /> - + <!-- Whether the item is shown/visible. --> <attr name="visible" /> @@ -2977,7 +3068,7 @@ with a View's attributes. Some subclasses (e.g., EditTextPreference) proxy all attributes to its EditText widget. --> <eat-comment /> - + <!-- Base attributes available to Preference. --> <declare-styleable name="Preference"> <!-- The key to store the Preference value. --> @@ -3106,7 +3197,7 @@ it had previously been shown. --> <attr name="imeExtractExitAnimation" format="reference" /> </declare-styleable> - + <declare-styleable name="KeyboardView"> <!-- Default KeyboardView style. --> <attr name="keyboardViewStyle" format="reference" /> @@ -3139,13 +3230,13 @@ <!-- Layout resource for popup keyboards --> <attr name="popupLayout" format="reference" /> - + <attr name="shadowColor" /> <attr name="shadowRadius" /> </declare-styleable> - + <declare-styleable name="KeyboardViewPreviewState"> - <!-- State for {@link android.inputmethodservice.KeyboardView KeyboardView} + <!-- State for {@link android.inputmethodservice.KeyboardView KeyboardView} key preview background --> <attr name="state_long_pressable" format="boolean" /> </declare-styleable> @@ -3228,7 +3319,7 @@ If not supplied, then no activity will be launched. --> <attr name="configure" format="string" /> </declare-styleable> - - + + </resources> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 7b48267..7571e24 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -512,6 +512,9 @@ <!-- The screen orientation has changed, that is the user has rotated the device. --> <flag name="orientation" value="0x0080" /> + <!-- The screen orientation has changed, that is the user has + rotated the device. --> + <flag name="screenLayout" value="0x0100" /> <!-- The font scaling factor has changed, that is the user has selected a new global font size. --> <flag name="fontScale" value="0x40000000" /> @@ -570,6 +573,15 @@ <!-- Application's requirement for five way navigation --> <attr name="reqFiveWayNav" format="boolean" /> + <!-- The name of the class implementing <code>BackupAgent</code> to manage + backup and restore of the application's settings to external storage. --> + <attr name="backupAgent" format="string" /> + + <!-- Whether the application allows its data to be backed up at all. This + attribute defaults to 'true': unless the application opts out, the + user will be able to back up its data to desktop storage. --> + <attr name="allowBackup" format="boolean" /> + <!-- The <code>manifest</code> tag is the root of an <code>AndroidManifest.xml</code> file, describing the contents of an Android package (.apk) file. One @@ -587,7 +599,8 @@ {@link #AndroidManifestUsesPermission uses-permission}, {@link #AndroidManifestUsesConfiguration uses-configuration}, {@link #AndroidManifestApplication application}, - {@link #AndroidManifestInstrumentation instrumentation}. --> + {@link #AndroidManifestInstrumentation instrumentation}, + {@link #AndroidManifestUsesFeature uses-feature}. --> <declare-styleable name="AndroidManifest"> <attr name="versionCode" /> <attr name="versionName" /> @@ -643,6 +656,8 @@ <attr name="manageSpaceActivity" /> <attr name="allowClearUserData" /> <attr name="testOnly" /> + <attr name="backupAgent" /> + <attr name="allowBackup" /> </declare-styleable> <!-- The <code>permission</code> tag declares a security permission that can be @@ -754,6 +769,22 @@ <attr name="reqFiveWayNav" /> </declare-styleable> + <!-- The <code>uses-feature</code> tag specifies + a specific feature used by the application. + For example an application might specify that it requires + specific version of open gl. Multiple such attribute + values can be specified by the application. + + <p>This appears as a child tag of the root + {@link #AndroidManifest manifest} tag. --> + <declare-styleable name="AndroidManifestUsesFeature" parent="AndroidManifest"> + <!-- The GLES driver version number needed by an application. + The higher 16 bits represent the major number and the lower 16 bits + represent the minor number. For example for GL 1.2 referring to + 0x00000102, the actual value should be set as 0x00010002. --> + <attr name="glEsVersion" format="integer"/> + </declare-styleable> + <!-- The <code>uses-sdk</code> tag describes the SDK features that the containing package must be running on to operate correctly. @@ -799,10 +830,68 @@ <!-- The <code>supports-density</code> specifies a screen density that this package supports. Application can specify multiple densities it supports. <p>This appears as a child tag of the - {@link #AndroidManifestApplication application} tag. --> - <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifestApplication"> - <!-- Required value of the density in dip (device independent pixel). --> - <attr name="density" format="integer" /> + {@link #AndroidManifest manifest} tag. --> + <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifest"> + <!-- Required value of the density in dip (device independent pixel). + You should use one of the pre-defined constants for the standard + screen densities defined here. + --> + <attr name="density" format="integer"> + <!-- A low density screen, such as a QVGA or WQVGA screen in a + typical hand-held phone. The constant for this is 120. --> + <enum name="low" value="120" /> + <!-- A medium density screen, such as an HVGA screen in a + typical hand-held phone. The constant for this is 160. --> + <enum name="medium" value="160" /> + <!-- A high density screen, such as a VGA or WVGA screen in a + typical hand-held phone. The constant for this is 240. --> + <enum name="high" value="240" /> + </attr> + </declare-styleable> + + <!-- The <code>supports-screens</code> specifies the screen dimensions an + application supports. By default a modern application supports all + screen sizes and must explicitly disable certain screen sizes here; + older applications are assumed to only support the traditional normal + (HVGA) screen size. Note that screen size is a separate axis from + density, and is determined as the available pixels to an application + after density scaling has been applied. + + <p>This appears as a child tag of the + {@link #AndroidManifest manifest} tag. --> + <declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest"> + <!-- Indicates whether the application supports smaller screen form-factors. + A small screen is defined as one with a smaller aspect ratio than + the traditional HVGA screen; that is, for a portrait screen, less + tall than an HVGA screen. In practice, this means a QVGA low + density or VGA high density screen. An application that does + not support small screens <em>will not be available</em> for + small screen devices, since there is little the platform can do + to make such an application work on a smaller screen. --> + <attr name="smallScreens" format="boolean" /> + <!-- Indicates whether an application supports the normal screen + form-factors. Traditionally this is an HVGA normal density + screen, but WQVGA low density and WVGA high density are also + considered to be normal. This attribute is true by default, + and applications currently should leave it that way. --> + <attr name="normalScreens" format="boolean" /> + <!-- Indicates whether the application supports larger screen form-factors. + A large screen is defined as a screen that is significantly larger + than a normal phone screen, and thus may require some special care + on the application's part to make good use of it. An example would + be a VGA <em>normal density</em> screen, though even larger screens + are certainly possible. An application that does not support + large screens will be placed as a postage stamp on such a + screen, so that it retains the dimensions it was originally + designed for. --> + <attr name="largeScreens" format="boolean" /> + </declare-styleable> + + <!-- The <code>expandable</code> specifies if this package supports screen metrics + other than 320x480 dip. + <p>This appears as a child tag of the + {@link #AndroidManifest manifest} tag. --> + <declare-styleable name="AndroidManifestExpandable" parent="AndroidManifest"> </declare-styleable> <!-- The <code>provider</code> tag declares a diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 8150067..d284d0f 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -18,7 +18,7 @@ */ --> <resources> - <drawable name="screen_background_light">#ffffffff</drawable> + <drawable name="screen_background_light">#fff9f9f9</drawable> <drawable name="screen_background_dark">#ff1a1a1a</drawable> <drawable name="status_bar_closed_default_background">#ff000000</drawable> <drawable name="status_bar_opened_default_background">#ff000000</drawable> @@ -37,7 +37,7 @@ <color name="dim_foreground_dark_inverse">#323232</color> <color name="dim_foreground_dark_inverse_disabled">#80323232</color> <color name="hint_foreground_dark">#808080</color> - <color name="background_light">#ffffffff</color> + <color name="background_light">#fff9f9f9</color> <color name="bright_foreground_light">#ff000000</color> <color name="bright_foreground_light_inverse">#ffffffff</color> <color name="bright_foreground_light_disabled">#80000000</color> @@ -58,7 +58,7 @@ <drawable name="editbox_dropdown_dark_frame">@drawable/editbox_dropdown_background_dark</drawable> <drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable> - <drawable name="input_method_fullscreen_background">#ffffffff</drawable> + <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable> <!-- For date picker widget --> <drawable name="selected_day_background">#ff0092f4</drawable> @@ -73,5 +73,9 @@ <color name="perms_normal_grp_color">#eeeeee</color> <color name="perms_normal_perm_color">#c0c0c0</color> + <!-- For search-related UIs --> + <color name="search_url_text">#7fa87f</color> + <color name="search_widget_corpus_item_background">@android:color/lighter_gray</color> + </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 83ac8e2..7215685 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -34,4 +34,8 @@ <!-- The duration (in milliseconds) of a long animation. --> <integer name="config_longAnimTime">300</integer> + + <!-- Flag indicating whether Last Name comes before First Name. + This becomes true in Japan, for example.--> + <bool name="config_lastname_comes_before_firstname">false</bool> </resources> diff --git a/core/res/res/values/donottranslate-cldr.xml b/core/res/res/values/donottranslate-cldr.xml new file mode 100644 index 0000000..286cc0e --- /dev/null +++ b/core/res/res/values/donottranslate-cldr.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="month_long_standalone_january">January</string> + <string name="month_long_standalone_february">February</string> + <string name="month_long_standalone_march">March</string> + <string name="month_long_standalone_april">April</string> + <string name="month_long_standalone_may">May</string> + <string name="month_long_standalone_june">June</string> + <string name="month_long_standalone_july">July</string> + <string name="month_long_standalone_august">August</string> + <string name="month_long_standalone_september">September</string> + <string name="month_long_standalone_october">October</string> + <string name="month_long_standalone_november">November</string> + <string name="month_long_standalone_december">December</string> + + <string name="month_long_january">January</string> + <string name="month_long_february">February</string> + <string name="month_long_march">March</string> + <string name="month_long_april">April</string> + <string name="month_long_may">May</string> + <string name="month_long_june">June</string> + <string name="month_long_july">July</string> + <string name="month_long_august">August</string> + <string name="month_long_september">September</string> + <string name="month_long_october">October</string> + <string name="month_long_november">November</string> + <string name="month_long_december">December</string> + + <string name="month_medium_january">Jan</string> + <string name="month_medium_february">Feb</string> + <string name="month_medium_march">Mar</string> + <string name="month_medium_april">Apr</string> + <string name="month_medium_may">May</string> + <string name="month_medium_june">Jun</string> + <string name="month_medium_july">Jul</string> + <string name="month_medium_august">Aug</string> + <string name="month_medium_september">Sep</string> + <string name="month_medium_october">Oct</string> + <string name="month_medium_november">Nov</string> + <string name="month_medium_december">Dec</string> + + <string name="month_shortest_january">J</string> + <string name="month_shortest_february">F</string> + <string name="month_shortest_march">M</string> + <string name="month_shortest_april">A</string> + <string name="month_shortest_may">M</string> + <string name="month_shortest_june">J</string> + <string name="month_shortest_july">J</string> + <string name="month_shortest_august">A</string> + <string name="month_shortest_september">S</string> + <string name="month_shortest_october">O</string> + <string name="month_shortest_november">N</string> + <string name="month_shortest_december">D</string> + + <string name="day_of_week_long_sunday">Sunday</string> + <string name="day_of_week_long_monday">Monday</string> + <string name="day_of_week_long_tuesday">Tuesday</string> + <string name="day_of_week_long_wednesday">Wednesday</string> + <string name="day_of_week_long_thursday">Thursday</string> + <string name="day_of_week_long_friday">Friday</string> + <string name="day_of_week_long_saturday">Saturday</string> + + <string name="day_of_week_medium_sunday">Sun</string> + <string name="day_of_week_medium_monday">Mon</string> + <string name="day_of_week_medium_tuesday">Tue</string> + <string name="day_of_week_medium_wednesday">Wed</string> + <string name="day_of_week_medium_thursday">Thu</string> + <string name="day_of_week_medium_friday">Fri</string> + <string name="day_of_week_medium_saturday">Sat</string> + + <string name="day_of_week_short_sunday">Su</string> + <string name="day_of_week_short_monday">Mo</string> + <string name="day_of_week_short_tuesday">Tu</string> + <string name="day_of_week_short_wednesday">We</string> + <string name="day_of_week_short_thursday">Th</string> + <string name="day_of_week_short_friday">Fr</string> + <string name="day_of_week_short_saturday">Sa</string> + + <string name="day_of_week_shortest_sunday">S</string> + <string name="day_of_week_shortest_monday">M</string> + <string name="day_of_week_shortest_tuesday">T</string> + <string name="day_of_week_shortest_wednesday">W</string> + <string name="day_of_week_shortest_thursday">T</string> + <string name="day_of_week_shortest_friday">F</string> + <string name="day_of_week_shortest_saturday">S</string> + + <string name="am">am</string> + <string name="pm">pm</string> + <string name="yesterday">Yesterday</string> + <string name="today">Today</string> + <string name="tomorrow">Tomorrow</string> + + <string name="hour_minute_24">%H:%M</string> + <string name="hour_minute_ampm">%-l:%M%p</string> + <string name="hour_minute_cap_ampm">%-l:%M%^p</string> + <string name="twelve_hour_time_format">h:mm a</string> + <string name="twenty_four_hour_time_format">HH:mm</string> + <string name="numeric_date">%-m/%-e/%Y</string> + <string name="numeric_date_format">M/d/yyyy</string> + <string name="numeric_date_template">"%s/%s/%s"</string> + <string name="month_day_year">%B %-e, %Y</string> + <string name="time_of_day">%-l:%M:%S %p</string> + <string name="date_and_time">%b %-e, %Y, %-l:%M:%S %p</string> + <string name="date_time">%1$s, %2$s</string> + <string name="time_date">%1$s, %3$s</string> + <string name="abbrev_month_day_year">%b %-e, %Y</string> + <string name="month_day">%B %-e</string> + <string name="month">%-B</string> + <string name="month_year">%B %Y</string> + <string name="abbrev_month_day">%b %-e</string> + <string name="abbrev_month">%-b</string> + <string name="abbrev_month_year">%b %Y</string> + <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">%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">%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_mdy1_time1_mdy2_time2">%2$s/%3$s/%4$s, %5$s – %7$s/%8$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="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">%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_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_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string> + <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$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_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_year_mdy1_mdy2">%2$s %3$s – %7$s %8$s, %9$s</string> + <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string> + <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string> + <string name="short_format_month">%b</string> +</resources> diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml new file mode 100644 index 0000000..6def3bf --- /dev/null +++ b/core/res/res/values/donottranslate.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Default text encoding for WebSettings. --> + <string name="default_text_encoding">Latin-1</string> +</resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f90c6b8..32c6937 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1091,22 +1091,73 @@ =============================================================== --> <eat-comment /> - <public type="attr" name="tension" id="0x0101026a" /> - <public type="attr" name="extraTension" id="0x0101026b" /> - <public type="attr" name="density" id="0x0101026c" /> - <public type="attr" name="searchSuggestThreshold" id="0x0101026d" /> - <public type="attr" name="includeInGlobalSearch" id="0x0101026e" /> - <public type="attr" name="onClick" id="0x0101026f" /> - <public type="attr" name="targetSdkVersion" id="0x01010270" /> - <public type="attr" name="maxSdkVersion" id="0x01010271" /> - <public type="attr" name="testOnly" id="0x01010272" /> + <public type="attr" name="tension" id="0x0101026a" /> + <public type="attr" name="extraTension" /> + <public type="attr" name="density" /> + <public type="attr" name="searchSuggestThreshold" /> + <public type="attr" name="includeInGlobalSearch" /> + <public type="attr" name="onClick" /> + <public type="attr" name="targetSdkVersion" /> + <public type="attr" name="maxSdkVersion" /> + <public type="attr" name="testOnly" /> + <public type="attr" name="contentDescription" /> + <public type="attr" name="gestureStrokeWidth" /> + <public type="attr" name="gestureColor" /> + <public type="attr" name="uncertainGestureColor" /> + <public type="attr" name="fadeOffset" /> + <public type="attr" name="fadeDuration" /> + <public type="attr" name="gestureStrokeType" /> + <public type="attr" name="gestureStrokeLengthThreshold" /> + <public type="attr" name="gestureStrokeSquarenessThreshold" /> + <public type="attr" name="gestureStrokeAngleThreshold" /> + <public type="attr" name="eventsInterceptionEnabled" /> + <public type="attr" name="fadeEnabled" /> + <public type="attr" name="backupAgent" /> + <public type="attr" name="allowBackup" /> + <public type="attr" name="glEsVersion" /> + <public type="attr" name="queryAfterZeroResults" /> + <public type="attr" name="dropDownHeight" /> + <public type="attr" name="smallScreens" /> + <public type="attr" name="normalScreens" /> + <public type="attr" name="largeScreens" /> + <public type="attr" name="progressBarStyleInverse" /> + <public type="attr" name="progressBarStyleSmallInverse" /> + <public type="attr" name="progressBarStyleLargeInverse" /> + <public type="attr" name="searchSettingsDescription" /> + <public type="attr" name="textColorPrimaryInverseDisableOnly" /> - <public type="anim" name="anticipate_interpolator" id="0x010a0007" /> - <public type="anim" name="overshoot_interpolator" id="0x010a0008" /> - <public type="anim" name="anticipate_overshoot_interpolator" id="0x010a0009" /> - <public type="anim" name="bounce_interpolator" id="0x010a000a" /> + <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" /> - <public type="drawable" name="stat_sys_vp_phone_call" id="0x0108022d" /> - <public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x0108022e" /> + <public-padding type="id" name="donut_resource_pad" end="0x01020040" /> + + <public type="style" name="Widget.ProgressBar.Inverse" id="0x0103005b" /> + <public type="style" name="Widget.ProgressBar.Large.Inverse" id="0x0103005c" /> + <public type="style" name="Widget.ProgressBar.Small.Inverse" id="0x0103005d" /> + <public-padding type="style" name="donut_resource_pad" end="0x01030070" /> + + <public-padding type="string" name="donut_resource_pad" end="0x01040030" /> + + <public-padding type="dimen" name="donut_resource_pad" end="0x01050010" /> + <public-padding type="color" name="donut_resource_pad" end="0x01060030" /> + + <public-padding type="array" name="donut_resource_pad" end="0x01070010" /> + + <public type="drawable" name="stat_sys_vp_phone_call" /> + <public type="drawable" name="stat_sys_vp_phone_call_on_hold" /> + + <public-padding type="drawable" name="donut_resource_pad" end="0x010800d0" /> + + <public-padding type="layout" name="donut_resource_pad" end="0x01090020" /> + + <public type="anim" name="anticipate_interpolator" /> + <public type="anim" name="overshoot_interpolator" /> + <public type="anim" name="anticipate_overshoot_interpolator" /> + <public type="anim" name="bounce_interpolator" /> + <public type="anim" name="linear_interpolator" /> + + <public-padding type="anim" name="donut_resource_pad" end="0x010a0020" /> + + <public-padding type="integer" name="donut_resource_pad" end="0x010e0010" /> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 331ef1a..9b9ba68 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -30,6 +30,11 @@ <string name="terabyteShort">TB</string> <!-- Suffix added to a number to signify size in petabytes. --> <string name="petabyteShort">PB</string> + <!-- Format string used to add a suffix like "KB" or "MB" to a number + to display a size in kilobytes, megabytes, or other size units. + Some languages (like French) will want to add a space between + the placeholders. --> + <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g><xliff:g id="unit" example="KB">%2$s</xliff:g></string> <!-- Used in Contacts for a field that has no label and in Note Pad for a note with no name. --> @@ -148,6 +153,24 @@ <!-- Meaning: unknown. Example: Service was enabled for: Voice, PAD --> <string name="serviceClassPAD">PAD</string> + <!-- CDMA Roaming Indicator Strings (non ERI)--> <skip /> + <!-- Default roaming indicator text --> + <string name="roamingText0">Roaming Indicator On</string> + <string name="roamingText1">Roaming Indicator Off</string> + <string name="roamingText2">Roaming Indicator Flashing</string> + <string name="roamingText3">Out of Neighborhood</string> + <string name="roamingText4">Out of Building</string> + <string name="roamingText5">Roaming - Preferred System</string> + <string name="roamingText6">Roaming - Available System</string> + <string name="roamingText7">Roaming - Alliance Partner</string> + <string name="roamingText8">Roaming - Premium Partner</string> + <string name="roamingText9">Roaming - Full Service Functionality</string> + <string name="roamingText10">Roaming - Partial Service Functionality</string> + <string name="roamingText11">Roaming Banner On</string> + <string name="roamingText12">Roaming Banner Off</string> + <string name="roamingTextSearching">Searching for Service</string> + + <!-- {0} is one of "bearerServiceCode*" {1} is dialing number @@ -205,6 +228,8 @@ <string name="httpErrorFileNotFound">The requested file was not found.</string> <!-- Displayed when a request failed because there are too many requests right now. --> <string name="httpErrorTooManyRequests">Too many requests are being processed. Try again later.</string> + <!-- Displayed a toast that a certificate is saved in the keystore --> + <string name="certificateSaved">The certificate is saved in the system\'s key store.</string> <!-- Sync notifications --> <skip /> <!-- A notification is shown when there is a sync error. This is the text that will scroll through the notification bar (will be seen by the user as he uses another application). --> @@ -438,13 +463,6 @@ forcibly restart other applications.</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_setProcessForeground">keep from being stopped</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_setProcessForeground">Allows an application to make - any process run in the foreground, so it can\'t be killed. - Should never be needed for normal applications.</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_forceBack">force application to close</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_forceBack">Allows an application to force any @@ -460,19 +478,18 @@ never normally need.</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_addSystemService">publish low-level services</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_addSystemService">Allows application to publish - its own low-level system services. Malicious applications may hijack - the system, and steal or corrupt any data on it.</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_shutdown">partial shutdown</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_shutdown">Puts the activity manager into a shutdown state. Does not perform a complete shutdown.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_stopAppSwitches">prevent app switches</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_stopAppSwitches">Prevents the user from switching to + another application.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_runSetActivityWatcher">monitor and control all application launching</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_runSetActivityWatcher">Allows an application to @@ -519,21 +536,17 @@ go to the background. Never needed for normal applications.</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_fotaUpdate">automatically install system updates</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_fotaUpdate">Allows an application to receive - notifications about pending system updates and trigger their - installation. Malicious applications may use this to corrupt the system - with unauthorized updates, or generally interfere with the update - process.</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_batteryStats">modify battery statistics</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_batteryStats">Allows the modification of collected battery statistics. Not for use by normal applications.</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_backup">control system backup and restore</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_backup">Allows the application to control the system's backup and restore mechanism. Not for use by normal applications.</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_internalSystemWindow">display unauthorized windows</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_internalSystemWindow">Allows the creation of @@ -763,13 +776,7 @@ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_installLocationProvider">Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real - location sources such as GPS or Network providers.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_installLocationCollector">permission to install a location collector</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_installLocationCollector">Create mock location sources for testing. - Malicious applications can use this to monitor and report your location to an external source.</string> + location sources such as GPS or Network providers or monitor and report your location to an external source.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_accessFineLocation">fine (GPS) location</string> @@ -887,7 +894,6 @@ properties uploaded by the checkin service. Not for use by normal applications.</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_bindGadget">choose widgets</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> @@ -1006,6 +1012,15 @@ configured Wi-Fi networks.</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_changeWifiMulticastState">allow Wi-Fi Multicast + reception</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_changeWifiMulticastState">Allows an application to + receive packets not directly addressed to your device. This can be + useful when discovering services offered near by. It uses more power + than the non-multicast mode.</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_bluetoothAdmin">bluetooth administration</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_bluetoothAdmin">Allows an application to configure @@ -1070,7 +1085,7 @@ user dictionary.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_sdcardWrite">write to SD card</string> + <string name="permlab_sdcardWrite">modify/delete SD card contents</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string> @@ -1096,6 +1111,9 @@ <item>Custom</item> </string-array> + <!-- String which means the type "mobile phone". --> + <string name="mobileEmailTypeName">Mobile</string> + <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Postal address types from android.provider.Contacts. This could be used when adding a new address for a contact, for example. --> <string-array name="postalAddressTypes"> @@ -1174,9 +1192,12 @@ <!-- On the unlock pattern screen, shown when the user enters the wrong lock pattern and must try again. --> <string name="lockscreen_pattern_wrong">Sorry, try again</string> - <!-- When the lock screen is showing and the phone plugged in, show the current - charge %. --> + <!-- When the lock screen is showing and the phone plugged in, and the battery + is not fully charged, show the current charge %. --> <string name="lockscreen_plugged_in">Charging (<xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g>)</string> + <!-- When the lock screen is showing, the phone is plugged in and the battery is fully + charged, say that it is charged. --> + <string name="lockscreen_charged">Charged.</string> <!-- When the lock screen is showing and the battery is low, warn user to plug in the phone soon. --> @@ -1245,15 +1266,6 @@ <!-- Displayed to the user when unlocking the phone with a username and password fails. --> <string name="lockscreen_glogin_invalid_input">Invalid username or password.</string> - <!-- A format string for 12-hour time of day (example: "12:30 PM"). --> - <string name="status_bar_time_format">"<xliff:g id="hour" example="12">h</xliff:g>:<xliff:g id="minute" example="30">mm</xliff:g> <xliff:g id="ampm" example="AM">AA</xliff:g>"</string> - - <!-- A format string for 12-hour time of day, with lower-case "am" or "pm" (example: "12:30pm"). --> - <string name="hour_minute_ampm">"<xliff:g id="hour" example="12">%-l</xliff:g>:<xliff:g id="minute" example="30">%M</xliff:g><xliff:g id="ampm" example="am">%P</xliff:g>"</string> - - <!-- A format string for 12-hour time of day, with capital "AM" or "PM" (example: "12:30PM"). --> - <string name="hour_minute_cap_ampm">"<xliff:g id="hour" example="12">%-l</xliff:g>:<xliff:g id="minute" example="30">%M</xliff:g><xliff:g id="ampm" example="AM">%p</xliff:g>"</string> - <!-- A format string for 12-hour time of day, just the hour, not the minute, with lower-case "am" or "pm" (example: "3pm"). --> <string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string> @@ -1262,7 +1274,7 @@ <!-- The text for the button in the notification window-shade that clears all of the currently visible notifications. --> - <string name="status_bar_clear_all_button">Clear notifications</string> + <string name="status_bar_clear_all_button">Clear</string> <!-- The label in the bar at the top of the status bar when there are no notifications showing. --> @@ -1295,6 +1307,9 @@ <string name="battery_low_percent_format">less than <xliff:g id="number">%d%%</xliff:g> remaining.</string> + <!-- When the battery is low, this is the label of the button to go to the + power usage activity to find out what drained the battery. --> + <string name="battery_low_why">Why?</string> <!-- Title of the alert when something went wrong in the factory test. --> <string name="factorytest_failed">Factory test failed</string> @@ -1321,7 +1336,23 @@ <!-- 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. --> @@ -1354,12 +1385,6 @@ It is also used by the home screen's search "widget". It should be short --> <string name="search_go">Search</string> - <!-- String used to display the date. This is shown instead of a date if the date is today's date. --> - <string name="today">Today</string> - <!-- String used to display the date. This is shown instead of a date if the date is yesterday's date. --> - <string name="yesterday">Yesterday</string> - <!-- String used to display the date. This is shown instead of a date if the date is tomorrow's date. --> - <string name="tomorrow">Tomorrow</string> <!-- String used to display the date. This is the string to say something happened 1 month ago. --> <string name="oneMonthDurationPast">1 month ago</string> <!-- String used to display the date. This is the string to say something happened more than 1 month ago. --> @@ -1493,21 +1518,6 @@ <!-- Appened to express the value is this unit of time. --> <string name="years">years</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="sunday">Sunday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="monday">Monday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="tuesday">Tuesday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="wednesday">Wednesday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="thursday">Thursday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="friday">Friday</string> - <!-- Used in the list of which days of the week a calendar event recurrs on --> - <string name="saturday">Saturday</string> - <!-- Calendar spinner item, to select that an event recurs every weekday. --> <string name="every_weekday">"Every weekday (Mon\u2013Fri)"</string> <!-- Calendar spinner item, to select that an event recurs every day. --> @@ -1530,95 +1540,12 @@ <string name="VideoView_error_button">OK</string> - <!-- AM - as in morning - as in 10:30 AM --> - <string name="am">"AM"</string> - - <!-- PM - as in afternoon - as in 10:30 PM --> - <string name="pm">"PM"</string> - - - <!-- Numeric form of the day. Example: "12/31/2007" --> - <string name="numeric_date">"<xliff:g id="month" example="12">%m</xliff:g>/<xliff:g id="day" example="31">%d</xliff:g>/<xliff:g id="year" example="2008">%Y</xliff:g>"</string> - - <!-- Format indicating a range of time, from a time on one day to a time on another day. - Example: "Mon, Dec 31, 2007, 8am - Tue, Jan 1, 2008, 5pm" --> - <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="weekday1" example="Monday">%1$s</xliff:g>, <xliff:g id="date1" example="December 31, 2007">%2$s</xliff:g>, <xliff:g id="time1" example="8am">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Tuesday">%4$s</xliff:g>, <xliff:g id="date2" example="January 1, 2008">%5$s</xliff:g>, <xliff:g id="time2" example="5pm">%6$s</xliff:g>"</string> - - <!-- Format indicating a range of dates, from one date to another. - Example: "Mon, Dec 31, 2007 - Tue, Jan 1, 2008" --> - <string name="wday1_date1_wday2_date2">"<xliff:g id="weekday1" example="Monday">%1$s</xliff:g>, <xliff:g id="date1" example="Dec 31, 2007">%2$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Thursday">%4$s</xliff:g>, <xliff:g id="date2" example="Jan 1, 2008">%5$s</xliff:g>"</string> - <!-- Format indicating a range of time, from a time on one day to a time on another day. - Example: "Dec 31, 2007, 8am - Jan 1, 2008, 5pm" --> - <string name="date1_time1_date2_time2">"<xliff:g id="date1" example="Dec 31, 2007">%2$s</xliff:g>, <xliff:g id="time1" example="8am">%3$s</xliff:g> \u2013 <xliff:g id="date2" example="Jan 1, 2008">%5$s</xliff:g>, <xliff:g id="time2" example="5pm">%6$s</xliff:g>"</string> - - <!-- Format indicating a range of dates, from one date to another. - Example: "Dec 31, 2007 - Jan 1, 2008" --> - <string name="date1_date2">"<xliff:g id="date1" example="Dec 31, 2007">%2$s</xliff:g> \u2013 <xliff:g id="date2" example="Jan 1, 2008">%5$s</xliff:g>"</string> - - <!-- Format indicating a range of times, from one time to another. - Example: "10:00 - 11:00 am" --> - <string name="time1_time2">"<xliff:g id="time1" example="10:00">%1$s</xliff:g> \u2013 <xliff:g id="time2" example="11:00">%2$s</xliff:g>"</string> - - <!-- Format indicating a range of times on a particular date. - Example: "8:00 - 11:00 am, Mon, Dec 31, 2007" --> - <string name="time_wday_date">"<xliff:g id="time_range" example="8:00 - 11:00 am">%1$s</xliff:g>, <xliff:g id="weekday" example="Mon">%2$s</xliff:g>, <xliff:g id="date" example="Dec 31, 2007">%3$s</xliff:g>"</string> - - <!-- Format indicating a weekday and date. - Example: "Mon, Dec 31, 2007" --> - <string name="wday_date">"<xliff:g id="weekday" example="Monday">%2$s</xliff:g>, <xliff:g id="date" example="Dec 31, 2007">%3$s</xliff:g>"</string> - - <!-- Format indicating a range of times on a particular date. - Example: "8:00 - 11:00 am, Dec 31, 2007" --> - <string name="time_date">"<xliff:g id="time_range" example="8:00 - 11:00 am">%1$s</xliff:g>, <xliff:g id="date" example="Dec 31, 2007">%3$s</xliff:g>"</string> - - <!-- Format indicating a specific date and time. - Example: "Dec 31, 2007, 11:00 am" --> - <string name="date_time">"<xliff:g id="date" example="Dec 31, 2007">%1$s</xliff:g>, <xliff:g id="time" example="11:00 am">%2$s</xliff:g>"</string> <!-- Format indicating a relative expression and time. Example: "4 hours ago, 11:00 am" --> <string name="relative_time">"<xliff:g id="date" example="4 hours ago">%1$s</xliff:g>, <xliff:g id="time" example="11:00 am">%2$s</xliff:g>"</string> - <!-- Format indicating a range of times on a particular day of the week. - Example: "8:00 - 11:00 am, Mon" --> - <string name="time_wday">"<xliff:g id="time_range" example="8:00 - 11:00 am">%1$s</xliff:g>, <xliff:g id="weekday" example="Mon">%2$s</xliff:g>"</string> - - <!-- Date format string used in contexts where the user has said they - want the month first, as used in the USA, with the month fully - spelled out. You can remove the comma or add a period, - or make other punctuation changes appropriate for your locale. --> - <string name="full_date_month_first" format="date"><xliff:g id="month" example="December">MMMM</xliff:g> <xliff:g id="day" example="31">d</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string> - - <!-- Date format string used in contexts where the user has said they - want the day of the month first, as used in Europe, with the month - fully spelled out. You can remove the comma or add a period, - or make other punctuation changes appropriate for your locale. --> - <string name="full_date_day_first" format="date"><xliff:g id="day" example="31">d</xliff:g> <xliff:g id="month" example="December">MMMM</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string> - - <!-- Date format string used in contexts where the user has said they - want the month first, as used in the USA, with the month - abbreviated. You can remove the comma or add a period, - or make other punctuation changes appropriate for your locale. --> - <string name="medium_date_month_first" format="date"><xliff:g id="month" example="Dec.">MMM</xliff:g> <xliff:g id="day" example="31">d</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string> - - <!-- Date format string used in contexts where the user has said they - want the day of the month first, as used in Europe, with the month - abbreviated. You can remove the comma or add a period, - or make other punctuation changes appropriate for your locale. --> - <string name="medium_date_day_first" format="date"><xliff:g id="day" example="31">d</xliff:g> <xliff:g id="month" example="December">MMM</xliff:g>, <xliff:g id="year" example="1972">yyyy</xliff:g></string> - - <!-- Time format string used in the status bar when the user has said they - want a 12-hour clock with AM and PM. - You can remove the colon - or make other punctuation changes appropriate for your locale. --> - <string name="twelve_hour_time_format" format="date"><xliff:g id="hour" example="11">h</xliff:g>:<xliff:g id="minute" example="59">mm</xliff:g> <xliff:g id="ampm" example="AM">a</xliff:g></string> - - <!-- Time format string used in the status bar when the user has said they - want a 24-hour clock. - You can remove the colon - or make other punctuation changes appropriate for your locale. --> - <string name="twenty_four_hour_time_format" format="date"><xliff:g id="hour" example="23">HH</xliff:g>:<xliff:g id="minute" example="59">mm</xliff:g></string> <!-- Quoted name for 12pm, lowercase --> <string name="noon">"noon"</string> @@ -1629,433 +1556,15 @@ <!-- Quoted name for 12am, uppercase first letter --> <string name="Midnight">"Midnight"</string> - <!-- Date format for month and day of month. - Example: "October 9". --> - <string name="month_day">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>"</string> - - <!-- Date format for month alone. - Example: "October" --> - <string name="month">"<xliff:g id="month" example="October">%B</xliff:g>"</string> - - <!-- Date format for month, day, and year. - Example: "October 9, 2007" --> - <string name="month_day_year">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>, <xliff:g id="year" example="2007">%Y</xliff:g>"</string> - - <!-- Date format for month and year. - Example: "October 2007" --> - <string name="month_year">"<xliff:g id="month" example="October">%B</xliff:g> <xliff:g id="year" example="2007">%Y</xliff:g>"</string> - - <!-- A format string for 24-hour time of day (example "23:59"). --> - <string name="time_of_day">"<xliff:g id="hour" example="23">%H</xliff:g>:<xliff:g id="minute" example="59">%M</xliff:g>:<xliff:g id="second" example="59">%S</xliff:g>"</string> - - <!-- Format string for date and 24-hour time of day. - Example: 23:59:15 Jan 31 2008 --> - <string name="date_and_time">"<xliff:g id="hour" example="23">%H</xliff:g>:<xliff:g id="minute" example="59">%M</xliff:g>:<xliff:g id="second" example="59">%S</xliff:g> <xliff:g id="month" example="Jan">%B</xliff:g> <xliff:g id="day" example="31">%-d</xliff:g>, <xliff:g id="year" example="2008">%Y</xliff:g>"</string> - - <!-- Format indicating a range of dates in the same year. - Example: "Oct 31 - Nov 3" --> - <string name="same_year_md1_md2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of dates in the same year, with weekday. - Example: "Wed, Oct 31 - Sat, Nov 3" --> - <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of dates in the same year. - Example: "Oct 31 - Nov 3, 2007" --> - <string name="same_year_mdy1_mdy2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of dates in the same year, with weekdays. - Example: "Wed, Oct 31 - Sat, Nov 3, 2007" --> - <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of time from a time on one day to a time on another. - Example: "Oct 31, 8:00am - Nov 3, 5:00pm" --> - <string name="same_year_md1_time1_md2_time2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of time from a time on one day to a time on another, with weekdays. - Example: "Wed, Oct 31, 8:00am - Sat, Nov 3, 5:00pm" --> - <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id ="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of time from a time on one day to a time on another, with years and weekdays. - Example: "Oct 31, 2007, 8:00am - Nov 3, 2007, 5:00pm" --> - <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of time from a time on one day to a time on another. - Example: "Wed, Oct 31, 2007, 8:00am - Sat, Nov 3, 2007, 5:00pm" --> - <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - - <!-- Format indicating a range of (numeric) dates. - Example: "10/31 - 11/3" --> - <string name="numeric_md1_md2">"<xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates. - Example: "Wed, 10/31 - Sat, 11/3" --> - <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates. - Example: "10/31/2007 - 11/3/2007" --> - <string name="numeric_mdy1_mdy2">"<xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>/<xliff:g id="year1" example="2007">%4$s</xliff:g> \u2013 <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>/<xliff:g id="year2" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates. - Example: "Wed, 10/31/2007 - Sat, 11/3/2007" --> - <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>/<xliff:g id="year1" example="2007">%4$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>/<xliff:g id="year2" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates and times. - Example: "10/31, 8:00am - 11/3, 5:00pm" --> - <string name="numeric_md1_time1_md2_time2">"<xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates and times. - Example: "Wed, 10/31, 8:00am - Sat, 11/3, 5:00pm" --> - <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates and times. - Example: "10/31/2007, 8:00am - 11/3/2007, 5:00pm" --> - <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>/<xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>/<xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of (numeric) dates and times. - Example: "Wed, 10/31/2007, 8:00am - Sat, 11/3/2007, 5:00pm" --> - <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="10">%2$s</xliff:g>/<xliff:g id="day1" example="31">%3$s</xliff:g>/<xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="11">%7$s</xliff:g>/<xliff:g id="day2" example="30">%8$s</xliff:g>/<xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - - <!-- Format indicating a range of dates. - Example: "Oct 9 - 10" --> - <string name="same_month_md1_md2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="day2" example="3">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of dates. - Example: "Tue, Oct 9 - Wed, Oct 10" --> - <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>"</string> - - <!-- Format indicating a range of dates. - Example: "Oct 9 - 10, 2007" --> - <string name="same_month_mdy1_mdy2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g> \u2013 <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of dates. - Example: "Tue, Oct 9, 2007 - Wed, Oct 10, 2007" --> - <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>"</string> - - <!-- Format indicating a range of dates and times. - Example: "Oct 9, 8:00am - Oct 10, 5:00pm" --> - <string name="same_month_md1_time1_md2_time2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of dates and times. - Example: "Tue, Oct 9, 8:00am - Wed, Oct 10, 5:00pm" --> - <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of dates and times. - Example: "Oct 9, 2007, 8:00am - Oct 10, 2007, 5:00pm" --> - <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format indicating a range of dates and times. - Example: "Tue, Oct 9, 2007, 8:00am - Wed, Oct 10, 2007, 5:00pm" --> - <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="weekday1" example="Wed">%1$s</xliff:g>, <xliff:g id="month1" example="Oct">%2$s</xliff:g> <xliff:g id="day1" example="31">%3$s</xliff:g>, <xliff:g id="year1" example="2007">%4$s</xliff:g>, <xliff:g id="time1" example="8:00am">%5$s</xliff:g> \u2013 <xliff:g id="weekday2" example="Sat">%6$s</xliff:g>, <xliff:g id="month2" example="Nov">%7$s</xliff:g> <xliff:g id="day2" example="3">%8$s</xliff:g>, <xliff:g id="year2" example="2007">%9$s</xliff:g>, <xliff:g id="time2" example="5:00pm">%10$s</xliff:g>"</string> - - <!-- Format string for abbreviated month, day, and year. - Example: "Oct 9, 2007" --> - <string name="abbrev_month_day_year">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="day" example="9">%-d</xliff:g>, <xliff:g id="year" example="2007">%Y</xliff:g>"</string> - <!-- Format string for abbreviated month and year. - Example: "Oct 2007" --> - <string name="abbrev_month_year">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="year" example="2007">%Y</xliff:g>"</string> - <!-- Format string for abbreviated month and day. - Example: "Oct 9" --> - <string name="abbrev_month_day">"<xliff:g id="month" example="Oct">%b</xliff:g> <xliff:g id="day" example="31">%-d</xliff:g>"</string> - <!-- Format string for abbreviated month alone. - Example: "Oct" --> - <string name="abbrev_month">"<xliff:g id="month" example="Oct">%b</xliff:g>"</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_sunday">Sunday</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_monday">Monday</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_tuesday">Tuesday</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_wednesday">Wednesday</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_thursday">Thursday</string> - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_friday">Friday</string> - - <!-- The full spelled out version of the day of the week. --> - <string name="day_of_week_long_saturday">Saturday</string> - - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Sun" stands for Sunday --> - <string name="day_of_week_medium_sunday">Sun</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Mon" stands for Monday --> - <string name="day_of_week_medium_monday">Mon</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Tue" stands for Tuesday --> - <string name="day_of_week_medium_tuesday">Tue</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Wed" stands for Wednesday --> - <string name="day_of_week_medium_wednesday">Wed</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Thu" stands for Thursday --> - <string name="day_of_week_medium_thursday">Thu</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Fri" stands for Friday --> - <string name="day_of_week_medium_friday">Fri</string> - - <!-- An abbreviated day of the week. Three characters typically in western languages. - In US English: "Sat" stands for Saturday --> - <string name="day_of_week_medium_saturday">Sat</string> - - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Su" stands for Sunday --> - <string name="day_of_week_short_sunday">Su</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Mo" stands for Monday --> - <string name="day_of_week_short_monday">Mo</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Tu" stands for Tuesday --> - <string name="day_of_week_short_tuesday">Tu</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "We" stands for Wednesday --> - <string name="day_of_week_short_wednesday">We</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Th" stands for Thursday --> - <string name="day_of_week_short_thursday">Th</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Fr" stands for Friday --> - <string name="day_of_week_short_friday">Fr</string> - - <!-- An abbreviated day of the week. Two characters typically in western languages. - In US English: "Sa" stands for Saturday --> - <string name="day_of_week_short_saturday">Sa</string> - - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "Su" stands for Sunday --> - <string name="day_of_week_shorter_sunday">Su</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "M" stands for Monday --> - <string name="day_of_week_shorter_monday">M</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "Tu" stands for Tuesday --> - <string name="day_of_week_shorter_tuesday">Tu</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "W" stands for Wednesday --> - <string name="day_of_week_shorter_wednesday">W</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "Th" stands for Thursday --> - <string name="day_of_week_shorter_thursday">Th</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "F" stands for Friday --> - <string name="day_of_week_shorter_friday">F</string> - - <!-- An abbreviated day of the week. One character if that is unique. Two if necessary. - In US English: "Sa" stands for Saturday --> - <string name="day_of_week_shorter_saturday">Sa</string> - - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "S" stands for Sunday --> - <string name="day_of_week_shortest_sunday">S</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "M" stands for Monday --> - <string name="day_of_week_shortest_monday">M</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "T" stands for Tuesday --> - <string name="day_of_week_shortest_tuesday">T</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "W" stands for Wednesday --> - <string name="day_of_week_shortest_wednesday">W</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "T" stands for Thursday --> - <string name="day_of_week_shortest_thursday">T</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "F" stands for Friday --> - <string name="day_of_week_shortest_friday">F</string> - - <!-- An abbreviated day of the week. One character long if it makes sense. Does not have - to be unique. - In US English: "S" stands for Saturday --> - <string name="day_of_week_shortest_saturday">S</string> - - - <!-- The full spelled out version of the month. --> - <string name="month_long_january">January</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_february">February</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_march">March</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_april">April</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_may">May</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_june">June</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_july">July</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_august">August</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_september">September</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_october">October</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_november">November</string> - - <!-- The full spelled out version of the month. --> - <string name="month_long_december">December</string> - - - <!-- An abbreviated month name. - In US English: "Jan" stands for January. --> - <string name="month_medium_january">Jan</string> - - <!-- An abbreviated month name. - In US English: "Feb" stands for February. --> - <string name="month_medium_february">Feb</string> - - <!-- An abbreviated month name. - In US English: "Mar" stands for March. --> - <string name="month_medium_march">Mar</string> - - <!-- An abbreviated month name. - In US English: "Apr" stands for April. --> - <string name="month_medium_april">Apr</string> - - <!-- An abbreviated month name. - In US English: "May" stands for May. --> - <string name="month_medium_may">May</string> - - <!-- An abbreviated month name. - In US English: "Jun" stands for June. --> - <string name="month_medium_june">Jun</string> - - <!-- An abbreviated month name. - In US English: "Jul" stands for July. --> - <string name="month_medium_july">Jul</string> - - <!-- An abbreviated month name. - In US English: "Aug" stands for August. --> - <string name="month_medium_august">Aug</string> - - <!-- An abbreviated month name. - In US English: "Sep" stands for September. --> - <string name="month_medium_september">Sep</string> - - <!-- An abbreviated month name. - In US English: "Oct" stands for October. --> - <string name="month_medium_october">Oct</string> - - <!-- An abbreviated month name. - In US English: "Nov" stands for November. --> - <string name="month_medium_november">Nov</string> - - <!-- An abbreviated month name. - In US English: "Dec" stands for December. --> - <string name="month_medium_december">Dec</string> - - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "J" stands for January --> - <string name="month_shortest_january">J</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "F" stands for February. --> - <string name="month_shortest_february">F</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "M" stands for March. --> - <string name="month_shortest_march">M</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "A" stands for April. --> - <string name="month_shortest_april">A</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "M" stands for May. --> - <string name="month_shortest_may">M</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "J" stands for June. --> - <string name="month_shortest_june">J</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "J" stands for July. --> - <string name="month_shortest_july">J</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "A" stands for August. --> - <string name="month_shortest_august">A</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "S" stands for September. --> - <string name="month_shortest_september">S</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "O" stands for October. --> - <string name="month_shortest_october">O</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "N" stands for November. --> - <string name="month_shortest_november">N</string> - - <!-- An abbreviated month name. One character long if it makes sense. Does not have - to be unique. - In US English: "D" stands for December. --> - <string name="month_shortest_december">D</string> <!-- Format string for durations like "01:23" (1 minute, 23 seconds) --> <string name="elapsed_time_short_format_mm_ss"><xliff:g id="minutes" example="1">%1$02d</xliff:g>:<xliff:g id="seconds" example="23">%2$02d</xliff:g></string> @@ -2153,6 +1662,8 @@ <string name="anr_process">Process <xliff:g id="process">%1$s</xliff:g> is not responding.</string> <!-- Button allowing the user to close an application that is not responding. This will kill the application. --> <string name="force_close">Force close</string> + <!-- Button allowing the user to send a bug report for application which has encountered an error. --> + <string name="report">Report</string> <!-- Button allowing the user to choose to wait for an application that is not responding to become responsive again. --> <string name="wait">Wait</string> <!-- Button allowing a developer to connect a debugger to an application that is not responding. --> @@ -2278,6 +1789,11 @@ <!-- See EXTMEDIA_FORMAT. This is the button text to format the sd card. --> <string name="extmedia_format_button_format">Format</string> + <!-- Title of notification shown when ADB is actively connected to the phone. --> + <string name="adb_active_notification_title">USB debugging connected</string> + <!-- Message of notification shown when ADB is actively connected to the phone. --> + <string name="adb_active_notification_message">A computer is connected to your phone.</string> + <!-- Used to replace %s in urls retreived from the signin server with locales. For Some --> <!-- devices we don't support all the locales we ship to and need to replace the '%s' with a --> <!-- locale string based on mcc values. By default (0-length string) we don't replace the %s --> @@ -2296,15 +1812,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> @@ -2312,11 +1828,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> @@ -2366,10 +1882,12 @@ <!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale pairs. This is used at startup to set a default locale by checking the system property ro.carrier for the carrier-id and searching through this array --> <string-array translatable="false" name="carrier_locales"> - </string-array> -</resources> - - + </string-array> + <!-- Title for the selected state of a CompoundButton. --> + <string name="accessibility_compound_button_selected">checked</string> + <!-- Title for the unselected state of a CompoundButton. --> + <string name="accessibility_compound_button_unselected">not checked</string> +</resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 8160c9c..7d235ec 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -124,6 +124,12 @@ <item name="windowExitAnimation">@anim/shrink_fade_out_from_bottom</item> </style> + <!-- {@hide} --> + <style name="Animation.SlidingCard"> + <item name="windowEnterAnimation">@anim/slide_in_up</item> + <item name="windowExitAnimation">@anim/slide_out_down</item> + </style> + <!-- Window animations that are applied to input method overlay windows. {@hide Pending API council approval} --> <style name="Animation.InputMethod"> @@ -171,6 +177,23 @@ <item name="android:fadingEdge">vertical</item> </style> + <style name="Widget.GestureOverlayView"> + <item name="android:gestureStrokeWidth">12.0</item> + <item name="android:gestureColor">#ffffff00</item> + <item name="android:uncertainGestureColor">#48ffff00</item> + <item name="android:fadeOffset">420</item> + <item name="android:fadeDuration">150</item> + <item name="android:gestureStrokeLengthThreshold">50.0</item> + <item name="android:gestureStrokeSquarenessThreshold">0.275</item> + <item name="android:gestureStrokeAngleThreshold">40.0</item> + <item name="android:eventsInterceptionEnabled">true</item> + </style> + + <style name="Widget.GestureOverlayView.White"> + <item name="android:gestureColor">#ff00ff00</item> + <item name="android:uncertainGestureColor">#4800ff00</item> + </style> + <style name="Widget.Button"> <item name="android:background">@android:drawable/btn_default</item> <item name="android:focusable">true</item> @@ -220,7 +243,7 @@ <style name="Widget.ProgressBar"> <item name="android:indeterminateOnly">true</item> - <item name="android:indeterminateDrawable">@android:drawable/progress_medium</item> + <item name="android:indeterminateDrawable">@android:drawable/progress_medium_white</item> <item name="android:indeterminateBehavior">repeat</item> <item name="android:indeterminateDuration">3500</item> <item name="android:minWidth">48dip</item> @@ -230,7 +253,7 @@ </style> <style name="Widget.ProgressBar.Large"> - <item name="android:indeterminateDrawable">@android:drawable/progress_large</item> + <item name="android:indeterminateDrawable">@android:drawable/progress_large_white</item> <item name="android:minWidth">76dip</item> <item name="android:maxWidth">76dip</item> <item name="android:minHeight">76dip</item> @@ -238,13 +261,25 @@ </style> <style name="Widget.ProgressBar.Small"> - <item name="android:indeterminateDrawable">@android:drawable/progress_small</item> + <item name="android:indeterminateDrawable">@android:drawable/progress_small_white</item> <item name="android:minWidth">16dip</item> <item name="android:maxWidth">16dip</item> <item name="android:minHeight">16dip</item> <item name="android:maxHeight">16dip</item> </style> + <style name="Widget.ProgressBar.Inverse"> + <item name="android:indeterminateDrawable">@android:drawable/progress_medium</item> + </style> + + <style name="Widget.ProgressBar.Large.Inverse"> + <item name="android:indeterminateDrawable">@android:drawable/progress_large</item> + </style> + + <style name="Widget.ProgressBar.Small.Inverse"> + <item name="android:indeterminateDrawable">@android:drawable/progress_small</item> + </style> + <style name="Widget.ProgressBar.Small.Title"> <item name="android:indeterminateDrawable">@android:drawable/progress_small_titlebar</item> </style> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 9567523..be836eb 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -44,12 +44,14 @@ <item name="textColorSecondaryInverse">@android:color/secondary_text_light</item> <item name="textColorTertiaryInverse">@android:color/tertiary_text_light</item> <item name="textColorPrimaryDisableOnly">@android:color/primary_text_dark_disable_only</item> + <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_light_disable_only</item> <item name="textColorPrimaryNoDisable">@android:color/primary_text_dark_nodisable</item> <item name="textColorSecondaryNoDisable">@android:color/secondary_text_dark_nodisable</item> <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_light_nodisable</item> <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_light_nodisable</item> <item name="textColorHint">@android:color/hint_foreground_dark</item> <item name="textColorHintInverse">@android:color/hint_foreground_light</item> + <item name="textColorSearchUrl">@android:color/search_url_text</item> <item name="textAppearanceLarge">@android:style/TextAppearance.Large</item> <item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item> @@ -141,7 +143,8 @@ <item name="editTextStyle">@android:style/Widget.EditText</item> <item name="expandableListViewStyle">@android:style/Widget.ExpandableListView</item> <item name="galleryStyle">@android:style/Widget.Gallery</item> - <item name="gridViewStyle">@android:style/Widget.GridView</item> + <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView</item> + <item name="gridViewStyle">@android:style/Widget.GridView</item> <item name="imageButtonStyle">@android:style/Widget.ImageButton</item> <item name="imageWellStyle">@android:style/Widget.ImageWell</item> <item name="listViewStyle">@android:style/Widget.ListView</item> @@ -152,6 +155,9 @@ <item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small</item> <item name="progressBarStyleSmallTitle">@android:style/Widget.ProgressBar.Small.Title</item> <item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large</item> + <item name="progressBarStyleInverse">@android:style/Widget.ProgressBar.Inverse</item> + <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small.Inverse</item> + <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large.Inverse</item> <item name="seekBarStyle">@android:style/Widget.SeekBar</item> <item name="ratingBarStyle">@android:style/Widget.RatingBar</item> <item name="ratingBarStyleIndicator">@android:style/Widget.RatingBar.Indicator</item> @@ -181,6 +187,9 @@ <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item> <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item> <item name="preferenceLayoutChild">@android:layout/preference_child</item> + + <!-- Search widget styles --> + <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item> </style> <!-- Variant of the default (dark) theme with no title bar --> @@ -212,6 +221,7 @@ <item name="textColorSecondaryInverse">@android:color/secondary_text_dark</item> <item name="textColorTertiaryInverse">@android:color/tertiary_text_dark</item> <item name="textColorPrimaryDisableOnly">@android:color/primary_text_light_disable_only</item> + <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_dark_disable_only</item> <item name="textColorPrimaryNoDisable">@android:color/primary_text_light_nodisable</item> <item name="textColorSecondaryNoDisable">@android:color/secondary_text_light_nodisable</item> <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_dark_nodisable</item> @@ -224,9 +234,17 @@ <item name="textCheckMark">@android:drawable/indicator_check_mark_light</item> <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item> + <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView.White</item> <item name="listViewStyle">@android:style/Widget.ListView.White</item> <item name="listDivider">@drawable/divider_horizontal_bright</item> <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item> + + <item name="progressBarStyle">@android:style/Widget.ProgressBar.Inverse</item> + <item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small.Inverse</item> + <item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large.Inverse</item> + <item name="progressBarStyleInverse">@android:style/Widget.ProgressBar</item> + <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small</item> + <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large</item> </style> <!-- Variant of the light theme with no title bar --> @@ -365,6 +383,12 @@ <item name="android:backgroundDimEnabled">true</item> <item name="windowContentOverlay">@null</item> </style> + + <!-- Theme for the search input bar when doing global search. The only + difference from non-global search is that we do not dim the background. --> + <style name="Theme.GlobalSearchBar" parent="Theme.Panel"> + <item name="windowContentOverlay">@null</item> + </style> <!-- Menu Themes --> <eat-comment /> diff --git a/core/res/res/xml/eri.xml b/core/res/res/xml/eri.xml new file mode 100644 index 0000000..cd66f14 --- /dev/null +++ b/core/res/res/xml/eri.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- Note that IconMode can be only 0, ON or 1, FLASHING + The icon is turned OFF if then IconIndex = 1 --> + +<EriFile VersionNumber="1357" + NumberOfEriEntries="12" + EriFileType="1"> + + <CallPromptId Id="0" + CallPromptText="CallPromptId0"/> + + <CallPromptId Id="1" + CallPromptText="CallPromptId1"/> + + <CallPromptId Id="2" + CallPromptText="CallPromptId2"/> + + <EriInfo RoamingIndicator="64" + IconIndex="1" + IconMode="0" + EriText="T-CDMA 64" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="65" + IconIndex="65" + IconMode="0" + EriText="T-CDMA 65" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="66" + IconIndex="1" + IconMode="0" + EriText="T-CDMA Ext 66" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="67" + IconIndex="67" + IconMode="0" + EriText="T-CDMA Ext 67" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="68" + IconIndex="68" + IconMode="0" + EriText="T-CDMA Roam 68" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="69" + IconIndex="69" + IconMode="1" + EriText="T-CDMA Ext 69" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="70" + IconIndex="70" + IconMode="1" + EriText="T-CDMA Roam 70" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="71" + IconIndex="1" + IconMode="0" + EriText="T-CDMA Ext 71" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="72" + IconIndex="72" + IconMode="0" + EriText="T-CDMA Ext 72" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="73" + IconIndex="73" + IconMode="0" + EriText="T-CDMA Roam 73" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="74" + IconIndex="74" + IconMode="1" + EriText="T-CDMA Ext 74" + CallPromptId="0" + AlertId="0"/> + + <EriInfo RoamingIndicator="75" + IconIndex="75" + IconMode="1" + EriText="T-CDMA Roam 75" + CallPromptId="0" + AlertId="0"/> + +</EriFile> diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml new file mode 100644 index 0000000..859902e --- /dev/null +++ b/core/res/res/xml/power_profile.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License") +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<device name="Android"> + <item name="none">0</item> + <item name="screen.on">0.1</item> + <item name="bluetooth.active">0.1</item> + <item name="bluetooth.on">0.1</item> + <item name="screen.full">0.1</item> + <item name="wifi.on">0.1</item> + <item name="wifi.active">0.1</item> + <item name="wifi.scan">0.1</item> + <item name="cpu.idle">0.1</item> + <item name="cpu.normal">0.2</item> + <item name="cpu.full">1</item> + <item name="dsp.audio">0.1</item> + <item name="dsp.video">0.1</item> + <item name="radio.active">1</item> + <item name="gps.on">1</item> + <array name="radio.on"> <!-- Strength 0 to BINS-1 --> + <value>1</value> + <value>0.1</value> + </array> +</device> |