diff options
92 files changed, 6519 insertions, 573 deletions
@@ -53,6 +53,16 @@ Media Codecs These files are Copyright 1998 - 2009 PacketVideo, but released under the Apache2 License. + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for Additional Codecs code. == + ========================================================================= + +Additional Codecs +These files are Copyright 2003-2010 VisualOn, but released under +the Apache2 License. + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/api/current.xml b/api/current.xml index 05658e7..4006e67 100644 --- a/api/current.xml +++ b/api/current.xml @@ -29401,6 +29401,23 @@ visibility="public" > </method> +<method name="listenUsingInsecureRfcommWithServiceRecord" + return="android.bluetooth.BluetoothServerSocket" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="name" type="java.lang.String"> +</parameter> +<parameter name="uuid" type="java.util.UUID"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> <method name="listenUsingRfcommWithServiceRecord" return="android.bluetooth.BluetoothServerSocket" abstract="false" @@ -30587,6 +30604,21 @@ > <implements name="android.os.Parcelable"> </implements> +<method name="createInsecureRfcommSocketToServiceRecord" + return="android.bluetooth.BluetoothSocket" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="uuid" type="java.util.UUID"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> <method name="createRfcommSocketToServiceRecord" return="android.bluetooth.BluetoothSocket" abstract="false" @@ -45952,6 +45984,19 @@ <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> </exception> </method> +<method name="getPackageObbPaths" + return="java.lang.String[]" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="packageName" type="java.lang.String"> +</parameter> +</method> <method name="getPackagesForUid" return="java.lang.String[]" abstract="true" @@ -46423,6 +46468,21 @@ <parameter name="flags" type="int"> </parameter> </method> +<method name="setPackageObbPaths" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="packageName" type="java.lang.String"> +</parameter> +<parameter name="paths" type="java.lang.String[]"> +</parameter> +</method> <field name="COMPONENT_ENABLED_STATE_DEFAULT" type="int" transient="false" @@ -59862,6 +59922,16 @@ visibility="public" > </field> +<field name="inPreferQualityOverSpeed" + type="boolean" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="inPreferredConfig" type="android.graphics.Bitmap.Config" transient="false" @@ -59974,6 +60044,146 @@ > </field> </class> +<class name="BitmapRegionDecoder" + extends="java.lang.Object" + abstract="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<method name="decodeRegion" + return="android.graphics.Bitmap" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="rect" type="android.graphics.Rect"> +</parameter> +<parameter name="options" type="android.graphics.BitmapFactory.Options"> +</parameter> +</method> +<method name="getHeight" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getWidth" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isRecycled" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="newInstance" + return="android.graphics.BitmapRegionDecoder" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="data" type="byte[]"> +</parameter> +<parameter name="offset" type="int"> +</parameter> +<parameter name="length" type="int"> +</parameter> +<parameter name="isShareable" type="boolean"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> +<method name="newInstance" + return="android.graphics.BitmapRegionDecoder" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="fd" type="java.io.FileDescriptor"> +</parameter> +<parameter name="isShareable" type="boolean"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> +<method name="newInstance" + return="android.graphics.BitmapRegionDecoder" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="is" type="java.io.InputStream"> +</parameter> +<parameter name="isShareable" type="boolean"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> +<method name="newInstance" + return="android.graphics.BitmapRegionDecoder" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="pathName" type="java.lang.String"> +</parameter> +<parameter name="isShareable" type="boolean"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> +<method name="recycle" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +</class> <class name="BitmapShader" extends="android.graphics.Shader" abstract="false" @@ -85937,6 +86147,385 @@ </parameter> </method> </interface> +<class name="MediaMetadataRetriever" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="MediaMetadataRetriever" + type="android.media.MediaMetadataRetriever" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<method name="extractMetadata" + return="java.lang.String" + abstract="false" + native="true" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="keyCode" type="int"> +</parameter> +</method> +<method name="getEmbeddedPicture" + return="byte[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getFrameAtTime" + return="android.graphics.Bitmap" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="timeUs" type="long"> +</parameter> +<parameter name="option" type="int"> +</parameter> +</method> +<method name="getFrameAtTime" + return="android.graphics.Bitmap" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="timeUs" type="long"> +</parameter> +</method> +<method name="getFrameAtTime" + return="android.graphics.Bitmap" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="release" + return="void" + abstract="false" + native="true" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="setDataSource" + return="void" + abstract="false" + native="true" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="path" type="java.lang.String"> +</parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> +</method> +<method name="setDataSource" + return="void" + abstract="false" + native="true" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="fd" type="java.io.FileDescriptor"> +</parameter> +<parameter name="offset" type="long"> +</parameter> +<parameter name="length" type="long"> +</parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> +</method> +<method name="setDataSource" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="fd" type="java.io.FileDescriptor"> +</parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> +</method> +<method name="setDataSource" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="uri" type="android.net.Uri"> +</parameter> +<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> +</exception> +<exception name="SecurityException" type="java.lang.SecurityException"> +</exception> +</method> +<field name="METADATA_KEY_ALBUM" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_ALBUMARTIST" + type="int" + transient="false" + volatile="false" + value="13" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_ARTIST" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_AUTHOR" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_CD_TRACK_NUMBER" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_COMPILATION" + type="int" + transient="false" + volatile="false" + value="15" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_COMPOSER" + type="int" + transient="false" + volatile="false" + value="4" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_DATE" + type="int" + transient="false" + volatile="false" + value="5" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_DISC_NUMBER" + type="int" + transient="false" + volatile="false" + value="14" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_DURATION" + type="int" + transient="false" + volatile="false" + value="9" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_GENRE" + type="int" + transient="false" + volatile="false" + value="6" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_MIMETYPE" + type="int" + transient="false" + volatile="false" + value="12" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_NUM_TRACKS" + type="int" + transient="false" + volatile="false" + value="10" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_TITLE" + type="int" + transient="false" + volatile="false" + value="7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_WRITER" + type="int" + transient="false" + volatile="false" + value="11" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="METADATA_KEY_YEAR" + type="int" + transient="false" + volatile="false" + value="8" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OPTION_CLOSEST" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OPTION_CLOSEST_SYNC" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OPTION_NEXT_SYNC" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OPTION_PREVIOUS_SYNC" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> <class name="MediaPlayer" extends="java.lang.Object" abstract="false" @@ -100228,6 +100817,36 @@ deprecated="not deprecated" visibility="public" > +<method name="disableForegroundDispatch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +</method> +<method name="enableForegroundDispatch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +<parameter name="intent" type="android.app.PendingIntent"> +</parameter> +<parameter name="filters" type="android.content.IntentFilter..."> +</parameter> +</method> <method name="getDefaultAdapter" return="android.nfc.NfcAdapter" abstract="false" @@ -159105,6 +159724,19 @@ <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> </exception> </method> +<method name="getPackageObbPaths" + return="java.lang.String[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="packageName" type="java.lang.String"> +</parameter> +</method> <method name="getPackagesForUid" return="java.lang.String[]" abstract="false" @@ -159589,6 +160221,21 @@ <parameter name="path" type="java.lang.String"> </parameter> </method> +<method name="setPackageObbPaths" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="packageName" type="java.lang.String"> +</parameter> +<parameter name="paths" type="java.lang.String[]"> +</parameter> +</method> </class> <class name="MockResources" extends="android.content.res.Resources" @@ -226180,7 +226827,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index f55b746..ff92431 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -596,21 +596,19 @@ int main(int argc, char **argv) { const char *filename = argv[k]; CHECK_EQ(retriever->setDataSource(filename), (status_t)OK); - CHECK_EQ(retriever->setMode( - METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL), - (status_t)OK); - - sp<IMemory> mem = retriever->captureFrame(); + sp<IMemory> mem = + retriever->getFrameAtTime(-1, + MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); if (mem != NULL) { - printf("captureFrame(%s) => OK\n", filename); + printf("getFrameAtTime(%s) => OK\n", filename); } else { mem = retriever->extractAlbumArt(); if (mem != NULL) { printf("extractAlbumArt(%s) => OK\n", filename); } else { - printf("both captureFrame and extractAlbumArt " + printf("both getFrameAtTime and extractAlbumArt " "failed on file '%s'.\n", filename); } } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f25c4c3..a54b305 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -632,7 +632,7 @@ public class Activity extends ContextThemeWrapper /*package*/ HashMap<String,Object> mLastNonConfigurationChildInstances; Activity mParent; boolean mCalled; - private boolean mResumed; + /*package*/ boolean mResumed; private boolean mStopped; boolean mFinished; boolean mStartedActivity; @@ -3827,9 +3827,8 @@ public class Activity extends ContextThemeWrapper mLastNonConfigurationInstance = null; - // First call onResume() -before- setting mResumed, so we don't - // send out any status bar / menu notifications the client makes. mCalled = false; + // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); if (!mCalled) { throw new SuperNotCalledException( @@ -3838,7 +3837,6 @@ public class Activity extends ContextThemeWrapper } // Now really resume, and install the current status bar and menu. - mResumed = true; mCalled = false; onPostResume(); if (!mCalled) { @@ -3857,6 +3855,7 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } + mResumed = false; } final void performUserLeaving() { @@ -3891,10 +3890,12 @@ public class Activity extends ContextThemeWrapper mStopped = true; } - mResumed = false; } - final boolean isResumed() { + /** + * @hide + */ + public final boolean isResumed() { return mResumed; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 78df780..e3fa32c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -185,6 +185,9 @@ public final class ActivityThread { final HashMap<IBinder, ProviderClientRecord> mLocalProviders = new HashMap<IBinder, ProviderClientRecord>(); + final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners + = new HashMap<Activity, ArrayList<OnActivityPausedListener>>(); + final GcIdler mGcIdler = new GcIdler(); boolean mGcIdlerScheduled = false; @@ -1424,6 +1427,18 @@ public final class ActivityThread { } } + public void registerOnActivityPausedListener(Activity activity, + OnActivityPausedListener listener) { + synchronized (mOnPauseListeners) { + ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); + if (list == null) { + list = new ArrayList<OnActivityPausedListener>(); + mOnPauseListeners.put(activity, list); + } + list.add(listener); + } + } + public final ActivityInfo resolveActivityInfo(Intent intent) { ActivityInfo aInfo = intent.resolveActivityInfo( mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); @@ -2333,6 +2348,17 @@ public final class ActivityThread { } } r.paused = true; + + // Notify any outstanding on paused listeners + ArrayList<OnActivityPausedListener> listeners; + synchronized (mOnPauseListeners) { + listeners = mOnPauseListeners.remove(r.activity); + } + int size = (listeners != null ? listeners.size() : 0); + for (int i = 0; i < size; i++) { + listeners.get(i).onPaused(r.activity); + } + return state; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 7e7cd7a..18ab478 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2700,14 +2700,24 @@ class ContextImpl extends Context { } @Override - public void setPackageObbPath(String packageName, String path) { + public void setPackageObbPaths(String packageName, String[] paths) { try { - mPM.setPackageObbPath(packageName, path); + mPM.setPackageObbPaths(packageName, paths); } catch (RemoteException e) { // Should never happen! } } + @Override + public String[] getPackageObbPaths(String packageName) { + try { + return mPM.getPackageObbPaths(packageName); + } catch (RemoteException e) { + // Should never happen! + } + return null; + } + private final ContextImpl mContext; private final IPackageManager mPM; diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index b8c3aa3..5c333a2 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1146,6 +1146,7 @@ public class Instrumentation { * @param activity The activity being resumed. */ public void callActivityOnResume(Activity activity) { + activity.mResumed = true; activity.onResume(); if (mActivityMonitors != null) { diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java new file mode 100644 index 0000000..379f133 --- /dev/null +++ b/core/java/android/app/OnActivityPausedListener.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 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.app; + +/** + * A listener that is called when an Activity is paused. Since this is tracked client side + * it should not be trusted to represent the exact current state, but can be used as a hint + * for cleanup. + * + * @hide + */ +public interface OnActivityPausedListener { + /** + * Called when the given activity is paused. + */ + public void onPaused(Activity activity); +} diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 3040319..a7175e3 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -729,6 +729,15 @@ public final class BluetoothAdapter { * Create a listening, secure RFCOMM Bluetooth socket. * <p>A remote device connecting to this socket will be authenticated and * communication on this socket will be encrypted. + * <p> Use this socket only if an authenticated socket link is possible. + * Authentication refers to the authentication of the link key to + * prevent man-in-the-middle type of attacks. + * For example, for Bluetooth 2.1 devices, if any of the devices does not + * have an input and output capability or just has the ability to + * display a numeric key, a secure socket connection is not possible. + * In such a case, use {#link listenUsingInsecureRfcommOn}. + * For more details, refer to the Security Model section 5.2 (vol 3) of + * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming * connections from a listening {@link BluetoothServerSocket}. * <p>Valid RFCOMM channels are in range 1 to 30. @@ -756,6 +765,15 @@ public final class BluetoothAdapter { * Create a listening, secure RFCOMM Bluetooth socket with Service Record. * <p>A remote device connecting to this socket will be authenticated and * communication on this socket will be encrypted. + * <p> Use this socket only if an authenticated socket link is possible. + * Authentication refers to the authentication of the link key to + * prevent man-in-the-middle type of attacks. + * For example, for Bluetooth 2.1 devices, if any of the devices does not + * have an input and output capability or just has the ability to + * display a numeric key, a secure socket connection is not possible. + * In such a case, use {#link listenUsingInsecureRfcommWithServiceRecord}. + * For more details, refer to the Security Model section 5.2 (vol 3) of + * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming * connections from a listening {@link BluetoothServerSocket}. * <p>The system will assign an unused RFCOMM channel to listen on. @@ -776,6 +794,42 @@ public final class BluetoothAdapter { */ public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) throws IOException { + return createNewRfcommSocketAndRecord(name, uuid, true, true); + } + + /** + * Create a listening, insecure RFCOMM Bluetooth socket with Service Record. + * <p>The link key will be unauthenticated i.e the communication is + * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices, + * the link key will be encrypted, as encryption is mandartory. + * For legacy devices (pre Bluetooth 2.1 devices) the link key will not + * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an + * encrypted and authenticated communication channel is desired. + * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming + * connections from a listening {@link BluetoothServerSocket}. + * <p>The system will assign an unused RFCOMM channel to listen on. + * <p>The system will also register a Service Discovery + * Protocol (SDP) record with the local SDP server containing the specified + * UUID, service name, and auto-assigned channel. Remote Bluetooth devices + * can use the same UUID to query our SDP server and discover which channel + * to connect to. This SDP record will be removed when this socket is + * closed, or if this application closes unexpectedly. + * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to + * connect to this socket from another device using the same {@link UUID}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * @param name service name for SDP record + * @param uuid uuid for SDP record + * @return a listening RFCOMM BluetoothServerSocket + * @throws IOException on error, for example Bluetooth not available, or + * insufficient permissions, or channel in use. + */ + public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) + throws IOException { + return createNewRfcommSocketAndRecord(name, uuid, false, false); + } + + private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid, + boolean auth, boolean encrypt) throws IOException { RfcommChannelPicker picker = new RfcommChannelPicker(uuid); BluetoothServerSocket socket; @@ -789,7 +843,7 @@ public final class BluetoothAdapter { } socket = new BluetoothServerSocket( - BluetoothSocket.TYPE_RFCOMM, true, true, channel); + BluetoothSocket.TYPE_RFCOMM, auth, encrypt, channel); errno = socket.mSocket.bindListen(); if (errno == 0) { if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel); diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index ada3c24..aee6ad8 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -693,6 +693,15 @@ public final class BluetoothDevice implements Parcelable { * outgoing connection to this remote device on given channel. * <p>The remote device will be authenticated and communication on this * socket will be encrypted. + * <p> Use this socket only if an authenticated socket link is possible. + * Authentication refers to the authentication of the link key to + * prevent man-in-the-middle type of attacks. + * For example, for Bluetooth 2.1 devices, if any of the devices does not + * have an input and output capability or just has the ability to + * display a numeric key, a secure socket connection is not possible. + * In such a case, use {#link createInsecureRfcommSocket}. + * For more details, refer to the Security Model section 5.2 (vol 3) of + * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing * connection. * <p>Valid RFCOMM channels are in range 1 to 30. @@ -720,11 +729,20 @@ public final class BluetoothDevice implements Parcelable { * determine which channel to connect to. * <p>The remote device will be authenticated and communication on this * socket will be encrypted. + * <p> Use this socket only if an authenticated socket link is possible. + * Authentication refers to the authentication of the link key to + * prevent man-in-the-middle type of attacks. + * For example, for Bluetooth 2.1 devices, if any of the devices does not + * have an input and output capability or just has the ability to + * display a numeric key, a secure socket connection is not possible. + * In such a case, use {#link createInsecureRfcommSocketToServiceRecord}. + * For more details, refer to the Security Model section 5.2 (vol 3) of + * Bluetooth Core Specification version 2.1 + EDR. * <p>Hint: If you are connecting to a Bluetooth serial board then try * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. * However if you are connecting to an Android peer then please generate * your own unique UUID. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @param uuid service record uuid to lookup RFCOMM channel * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection @@ -737,6 +755,39 @@ public final class BluetoothDevice implements Parcelable { } /** + * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure + * outgoing connection to this remote device using SDP lookup of uuid. + * <p> The communication channel will not have an authenticated link key + * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1 + * devices, the link key will be encrypted, as encryption is mandatory. + * For legacy devices (pre Bluetooth 2.1 devices) the link key will + * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an + * encrypted and authenticated communication channel is desired. + * <p>This is designed to be used with {@link + * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer + * Bluetooth applications. + * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing + * connection. This will also perform an SDP lookup of the given uuid to + * determine which channel to connect to. + * <p>The remote device will be authenticated and communication on this + * socket will be encrypted. + * <p>Hint: If you are connecting to a Bluetooth serial board then try + * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. + * However if you are connecting to an Android peer then please generate + * your own unique UUID. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * + * @param uuid service record uuid to lookup RFCOMM channel + * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection + * @throws IOException on error, for example Bluetooth not available, or + * insufficient permissions + */ + public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException { + return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1, + new ParcelUuid(uuid)); + } + + /** * Construct an insecure RFCOMM socket ready to start an outgoing * connection. * Call #connect on the returned #BluetoothSocket to begin the connection. diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 9be4c8f..954fde5 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -129,10 +129,6 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine newState == BluetoothA2dp.STATE_DISCONNECTED) { sendMessage(TRANSITION_TO_STABLE); } - } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { - Message msg = new Message(); - msg.what = AUTO_CONNECT_PROFILES; - sendMessageDelayed(msg, AUTO_CONNECT_DELAY); } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { // This is technically not needed, but we can get stuck sometimes. // For example, if incoming A2DP fails, we are not informed by Bluez diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 4cff3bb..44b0c96 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -322,5 +322,6 @@ interface IPackageManager { boolean setInstallLocation(int loc); int getInstallLocation(); - void setPackageObbPath(String packageName, String path); + void setPackageObbPaths(in String packageName, in String[] paths); + String[] getPackageObbPaths(in String packageName); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b5d1653..a1c29f7 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2273,15 +2273,30 @@ public abstract class PackageManager { String packageName, IPackageMoveObserver observer, int flags); /** - * Sets the Opaque Binary Blob (OBB) file location. + * Sets the Opaque Binary Blob (OBB) file path associated with a package + * name. The caller must have the + * {@link android.Manifest.permission#INSTALL_PACKAGES} permission. * <p> * NOTE: The existence or format of this file is not currently checked, but * it may be in the future. * * @param packageName Name of the package with which to associate the .obb - * file - * @param path Path on the filesystem to the .obb file - * @hide + * file. + * @param paths Arrays of paths on the filesystem to the .obb files + * associated with the package. + * @see #getPackageObbPaths(String) + */ + public abstract void setPackageObbPaths(String packageName, String[] paths); + + /** + * Gets the Opaque Binary Blob (OBB) file path associated with the package. + * The caller must be the owner of the package queried or have the + * {@link android.Manifest.permission#INSTALL_PACKAGES} permission. + * + * @param packageName Name of the package with which to associate the .obb + * file. + * @return array of paths to .obb files associated with the package + * @see #setPackageObbPaths(String, String[]) */ - public abstract void setPackageObbPath(String packageName, String path); + public abstract String[] getPackageObbPaths(String packageName); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 80b8d92..16805b2 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2601,14 +2601,8 @@ public class PackageParser { int priority = sa.getInt( com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); - if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) { - Log.w(TAG, "Activity with priority > 0, forcing to 0 at " - + mArchiveSourcePath + " " - + parser.getPositionDescription()); - priority = 0; - } outInfo.setPriority(priority); - + TypedValue v = sa.peekValue( com.android.internal.R.styleable.AndroidManifestIntentFilter_label); if (v != null && (outInfo.labelRes=v.resourceId) == 0) { diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index a663fb8..cb9fc9d 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -16,6 +16,9 @@ package android.nfc; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.IntentFilter; import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.ILlcpSocket; @@ -44,6 +47,9 @@ interface INfcAdapter NdefMessage localGet(); void localSet(in NdefMessage message); void openTagConnection(in Tag tag); + void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, + in IntentFilter[] filters); + void disableForegroundDispatch(in ComponentName activity); // Non-public methods // TODO: check and complete diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index cfbe581..c0c0462 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -18,8 +18,12 @@ package android.nfc; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.Activity; import android.app.ActivityThread; +import android.app.OnActivityPausedListener; +import android.app.PendingIntent; import android.content.Context; +import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.nfc.technology.TagTechnology; @@ -100,6 +104,20 @@ public final class NfcAdapter { "android.nfc.action.TRANSACTION_DETECTED"; /** + * Broadcast Action: an RF field ON has been detected. + * @hide + */ + public static final String ACTION_RF_FIELD_ON_DETECTED = + "android.nfc.action.RF_FIELD_ON_DETECTED"; + + /** + * Broadcast Action: an RF Field OFF has been detected. + * @hide + */ + public static final String ACTION_RF_FIELD_OFF_DETECTED = + "android.nfc.action.RF_FIELD_OFF_DETECTED"; + + /** * Broadcast Action: an adapter's state changed between enabled and disabled. * * The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains @@ -197,8 +215,6 @@ public final class NfcAdapter { private static INfcAdapter sService; private static INfcTag sTagService; - private final Context mContext; - /** * Helper to check if this device has FEATURE_NFC, but without using * a context. @@ -294,7 +310,6 @@ public final class NfcAdapter { if (setupService() == null) { throw new UnsupportedOperationException(); } - mContext = context; } /** @@ -302,6 +317,7 @@ public final class NfcAdapter { * @hide */ public INfcAdapter getService() { + isEnabled(); // NOP call to recover sService if it is stale return sService; } @@ -310,6 +326,7 @@ public final class NfcAdapter { * @hide */ public INfcTag getTagService() { + isEnabled(); // NOP call to recover sTagService if it is stale return sTagService; } @@ -396,6 +413,66 @@ public final class NfcAdapter { } } + class ForegroundDispatchPausedListener implements OnActivityPausedListener { + @Override + public void onPaused(Activity activity) { + disableForegroundDispatchInternal(activity, true); + } + } + + /** + * Enables foreground dispatching to the given Activity. This will force all NFC Intents that + * match the given filters to be delivered to the activity bypassing the standard dispatch + * mechanism. + * + * This method must be called from the main thread. + * + * @param activity the Activity to dispatch to + * @param intent the PendingIntent to start for the dispatch + * @param filters the IntentFilters to override dispatching for + * @throws IllegalStateException + */ + public void enableForegroundDispatch(Activity activity, PendingIntent intent, + IntentFilter... filters) { + if (activity == null || intent == null || filters == null) { + throw new NullPointerException(); + } + if (!activity.isResumed()) { + throw new IllegalStateException("Foregorund dispatching can onlly be enabled " + + "when your activity is resumed"); + } + try { + ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, + new ForegroundDispatchPausedListener()); + sService.enableForegroundDispatch(activity.getComponentName(), intent, filters); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + + /** + * Disables foreground activity dispatching setup with + * {@link #enableForegroundDispatch}. This must be called before the Activity returns from + * it's <code>onPause()</code> or this method will throw an IllegalStateException. + * + * This method must be called from the main thread. + */ + public void disableForegroundDispatch(Activity activity) { + disableForegroundDispatchInternal(activity, false); + } + + void disableForegroundDispatchInternal(Activity activity, boolean force) { + try { + sService.disableForegroundDispatch(activity.getComponentName()); + if (!force && !activity.isResumed()) { + throw new IllegalStateException("You must disable forgeground dispatching " + + "while your activity is still resumed"); + } + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + /** * Retrieve a TagTechnology object used to interact with a Tag that is * in field. diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java index 2a76e33..6095a64 100755 --- a/core/java/android/view/WindowOrientationListener.java +++ b/core/java/android/view/WindowOrientationListener.java @@ -234,6 +234,14 @@ public abstract class WindowOrientationListener { // high time constant. private static final float MAX_DEVIATION_FROM_GRAVITY = 1.5f; + // Minimum acceleration considered, in m/s^2. Below this threshold sensor noise will have + // significant impact on the calculations and in case of the vector (0, 0, 0) there is no + // defined rotation or tilt at all. Low or zero readings can happen when space travelling + // or free falling, but more commonly when shaking or getting bad readings from the sensor. + // The accelerometer is turned off when not used and polling it too soon after it is + // turned on may result in (0, 0, 0). + private static final float MIN_ABS_ACCELERATION = 1.5f; + // Actual sampling period corresponding to SensorManager.SENSOR_DELAY_NORMAL. There's no // way to get this information from SensorManager. // Note the actual period is generally 3-30ms larger than this depending on the device, but @@ -347,6 +355,9 @@ public abstract class WindowOrientationListener { float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY); handleAccelerationDistrust(deviation); + if (magnitude < MIN_ABS_ACCELERATION) { + return; // Ignore tilt and orientation when (0, 0, 0) or low reading + } // only filter tilt when we're accelerating float alpha = 1; diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index fa47ff6..303a1bf 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -22,7 +22,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Typeface; import android.os.Handler; @@ -33,6 +32,7 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import java.lang.ref.WeakReference; import java.text.DateFormatSymbols; import java.util.Calendar; @@ -49,26 +49,41 @@ public class DigitalClock extends LinearLayout { private TextView mTimeDisplay; private AmPm mAmPm; private ContentObserver mFormatChangeObserver; - private boolean mLive = true; - private boolean mAttached; + private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced /* called by system on minute ticks */ private final Handler mHandler = new Handler(); - private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mLive && intent.getAction().equals( - Intent.ACTION_TIMEZONE_CHANGED)) { - mCalendar = Calendar.getInstance(); - } - // Post a runnable to avoid blocking the broadcast. - mHandler.post(new Runnable() { - public void run() { - updateTime(); + private BroadcastReceiver mIntentReceiver; + + private static class TimeChangedReceiver extends BroadcastReceiver { + private WeakReference<DigitalClock> mClock; + private Context mContext; + + public TimeChangedReceiver(DigitalClock clock) { + mClock = new WeakReference<DigitalClock>(clock); + mContext = clock.getContext(); + } + + @Override + public void onReceive(Context context, Intent intent) { + // Post a runnable to avoid blocking the broadcast. + final boolean timezoneChanged = + intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED); + final DigitalClock clock = mClock.get(); + if (clock != null) { + clock.mHandler.post(new Runnable() { + public void run() { + if (timezoneChanged) { + clock.mCalendar = Calendar.getInstance(); } + clock.updateTime(); + } }); + } else { + mContext.unregisterReceiver(this); } - }; + } + }; static class AmPm { private TextView mAmPm; @@ -94,14 +109,23 @@ public class DigitalClock extends LinearLayout { } } - private class FormatChangeObserver extends ContentObserver { - public FormatChangeObserver() { + private static class FormatChangeObserver extends ContentObserver { + private WeakReference<DigitalClock> mClock; + private Context mContext; + public FormatChangeObserver(DigitalClock clock) { super(new Handler()); + mClock = new WeakReference<DigitalClock>(clock); + mContext = clock.getContext(); } @Override public void onChange(boolean selfChange) { - setDateFormat(); - updateTime(); + DigitalClock digitalClock = mClock.get(); + if (digitalClock != null) { + digitalClock.setDateFormat(); + digitalClock.updateTime(); + } else { + mContext.getContentResolver().unregisterContentObserver(this); + } } } @@ -129,11 +153,11 @@ public class DigitalClock extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mAttached) return; - mAttached = true; + mAttached++; - if (mLive) { - /* monitor time ticks, time changed, timezone */ + /* monitor time ticks, time changed, timezone */ + if (mIntentReceiver == null) { + mIntentReceiver = new TimeChangedReceiver(this); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); @@ -142,9 +166,11 @@ public class DigitalClock extends LinearLayout { } /* monitor 12/24-hour display preference */ - mFormatChangeObserver = new FormatChangeObserver(); - mContext.getContentResolver().registerContentObserver( - Settings.System.CONTENT_URI, true, mFormatChangeObserver); + if (mFormatChangeObserver == null) { + mFormatChangeObserver = new FormatChangeObserver(this); + mContext.getContentResolver().registerContentObserver( + Settings.System.CONTENT_URI, true, mFormatChangeObserver); + } updateTime(); } @@ -153,16 +179,19 @@ public class DigitalClock extends LinearLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (!mAttached) return; - mAttached = false; + mAttached--; - if (mLive) { + if (mIntentReceiver != null) { mContext.unregisterReceiver(mIntentReceiver); } - mContext.getContentResolver().unregisterContentObserver( - mFormatChangeObserver); - } + if (mFormatChangeObserver != null) { + mContext.getContentResolver().unregisterContentObserver( + mFormatChangeObserver); + } + mFormatChangeObserver = null; + mIntentReceiver = null; + } void updateTime(Calendar c) { mCalendar = c; @@ -170,9 +199,7 @@ public class DigitalClock extends LinearLayout { } private void updateTime() { - if (mLive) { - mCalendar.setTimeInMillis(System.currentTimeMillis()); - } + mCalendar.setTimeInMillis(System.currentTimeMillis()); CharSequence newTime = DateFormat.format(mFormat, mCalendar); mTimeDisplay.setText(newTime); @@ -180,12 +207,8 @@ public class DigitalClock extends LinearLayout { } private void setDateFormat() { - mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) + mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12; mAmPm.setShowAmPm(mFormat.equals(M12)); } - - void setLive(boolean live) { - mLive = live; - } } diff --git a/core/jni/Android.mk b/core/jni/Android.mk index c3f393d..12b9ca5 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES:= \ android_graphics_PixelFormat.cpp \ android/graphics/Picture.cpp \ android/graphics/PorterDuff.cpp \ + android/graphics/BitmapRegionDecoder.cpp \ android/graphics/Rasterizer.cpp \ android/graphics/Region.cpp \ android/graphics/Shader.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 648d93f..d9759bf 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -53,6 +53,7 @@ extern int register_android_os_Binder(JNIEnv* env); extern int register_android_os_Process(JNIEnv* env); extern int register_android_graphics_Bitmap(JNIEnv*); extern int register_android_graphics_BitmapFactory(JNIEnv*); +extern int register_android_graphics_BitmapRegionDecoder(JNIEnv*); extern int register_android_graphics_Camera(JNIEnv* env); extern int register_android_graphics_Graphics(JNIEnv* env); extern int register_android_graphics_Interpolator(JNIEnv* env); @@ -1209,6 +1210,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_Bitmap), REG_JNI(register_android_graphics_BitmapFactory), + REG_JNI(register_android_graphics_BitmapRegionDecoder), REG_JNI(register_android_graphics_Camera), REG_JNI(register_android_graphics_Canvas), REG_JNI(register_android_graphics_ColorFilter), diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 90a0243..987dd4f 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -27,6 +27,7 @@ jfieldID gOptions_ditherFieldID; jfieldID gOptions_purgeableFieldID; jfieldID gOptions_shareableFieldID; jfieldID gOptions_nativeAllocFieldID; +jfieldID gOptions_preferQualityOverSpeedFieldID; jfieldID gOptions_widthFieldID; jfieldID gOptions_heightFieldID; jfieldID gOptions_mimeFieldID; @@ -180,6 +181,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options)); bool reportSizeToVM = optionsReportSizeToVM(env, options); + bool preferQualityOverSpeed = false; if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -194,6 +196,8 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); doDither = env->GetBooleanField(options, gOptions_ditherFieldID); + preferQualityOverSpeed = env->GetBooleanField(options, + gOptions_preferQualityOverSpeedFieldID); } SkImageDecoder* decoder = SkImageDecoder::Factory(stream); @@ -203,6 +207,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decoder->setSampleSize(sampleSize); decoder->setDitherImage(doDither); + decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); NinePatchPeeker peeker(decoder); JavaPixelAllocator javaAllocator(env, reportSizeToVM); @@ -551,6 +556,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z"); gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z"); gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z"); + gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, gOptions_class, + "inPreferQualityOverSpeed", "Z"); gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I"); gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I"); gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;"); diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h index f868434..9ae61bc 100644 --- a/core/jni/android/graphics/BitmapFactory.h +++ b/core/jni/android/graphics/BitmapFactory.h @@ -11,6 +11,7 @@ extern jfieldID gOptions_ditherFieldID; extern jfieldID gOptions_purgeableFieldID; extern jfieldID gOptions_shareableFieldID; extern jfieldID gOptions_nativeAllocFieldID; +extern jfieldID gOptions_preferQualityOverSpeedFieldID; extern jfieldID gOptions_widthFieldID; extern jfieldID gOptions_heightFieldID; extern jfieldID gOptions_mimeFieldID; diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp new file mode 100644 index 0000000..91a8202 --- /dev/null +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2010 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 "BitmapRegionDecoder" + +#include "SkBitmap.h" +#include "SkImageEncoder.h" +#include "GraphicsJNI.h" +#include "SkUtils.h" +#include "SkTemplates.h" +#include "SkPixelRef.h" +#include "SkStream.h" +#include "BitmapFactory.h" +#include "AutoDecodeCancel.h" +#include "SkBitmapRegionDecoder.h" +#include "CreateJavaOutputStreamAdaptor.h" +#include "Utils.h" + +#include <android_runtime/AndroidRuntime.h> +#include "android_util_Binder.h" +#include "android_nio_utils.h" +#include "CreateJavaOutputStreamAdaptor.h" + +#include <binder/Parcel.h> +#include <jni.h> +#include <utils/Asset.h> +#include <sys/stat.h> + +static jclass gFileDescriptor_class; +static jfieldID gFileDescriptor_descriptor; + +#if 0 + #define TRACE_BITMAP(code) code +#else + #define TRACE_BITMAP(code) +#endif + +using namespace android; + +static SkMemoryStream* buildSkMemoryStream(SkStream *stream) { + size_t bufferSize = 4096; + size_t streamLen = 0; + size_t len; + char* data = (char*)sk_malloc_throw(bufferSize); + + while ((len = stream->read(data + streamLen, + bufferSize - streamLen)) != 0) { + streamLen += len; + if (streamLen == bufferSize) { + bufferSize *= 2; + data = (char*)sk_realloc_throw(data, bufferSize); + } + } + data = (char*)sk_realloc_throw(data, streamLen); + + SkMemoryStream* streamMem = new SkMemoryStream(); + streamMem->setMemoryOwned(data, streamLen); + return streamMem; +} + +static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { + SkImageDecoder* decoder = SkImageDecoder::Factory(stream); + int width, height; + if (NULL == decoder) { + doThrowIOE(env, "Image format not supported"); + return nullObjectReturn("SkImageDecoder::Factory returned null"); + } + + JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true); + decoder->setAllocator(javaAllocator); + JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env); + decoder->setReporter(javaMemoryReporter); + javaAllocator->unref(); + javaMemoryReporter->unref(); + + if (!decoder->buildTileIndex(stream, &width, &height)) { + char msg[100]; + snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder", + decoder->getFormatName()); + doThrowIOE(env, msg); + return nullObjectReturn("decoder->buildTileIndex returned false"); + } + + SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height); + + return GraphicsJNI::createBitmapRegionDecoder(env, bm); +} + +static jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, + int offset, int length, jboolean isShareable) { + /* If isShareable we could decide to just wrap the java array and + share it, but that means adding a globalref to the java array object + For now we just always copy the array's data if isShareable. + */ + AutoJavaByteArray ar(env, byteArray); + SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true); + return doBuildTileIndex(env, stream); +} + +static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz, + jobject fileDescriptor, jboolean isShareable) { + NPE_CHECK_RETURN_ZERO(env, fileDescriptor); + + jint descriptor = env->GetIntField(fileDescriptor, + gFileDescriptor_descriptor); + SkStream *stream = NULL; + struct stat fdStat; + int newFD; + if (fstat(descriptor, &fdStat) == -1) { + doThrowIOE(env, "broken file descriptor"); + return nullObjectReturn("fstat return -1"); + } + + if (isShareable && + S_ISREG(fdStat.st_mode) && + (newFD = ::dup(descriptor)) != -1) { + SkFDStream* fdStream = new SkFDStream(newFD, true); + if (!fdStream->isValid()) { + fdStream->unref(); + return NULL; + } + stream = fdStream; + } else { + /* Restore our offset when we leave, so we can be called more than once + with the same descriptor. This is only required if we didn't dup the + file descriptor, but it is OK to do it all the time. + */ + AutoFDSeek as(descriptor); + + SkFDStream* fdStream = new SkFDStream(descriptor, false); + if (!fdStream->isValid()) { + fdStream->unref(); + return NULL; + } + stream = buildSkMemoryStream(fdStream); + fdStream->unref(); + } + + return doBuildTileIndex(env, stream); +} + +static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz, + jobject is, // InputStream + jbyteArray storage, // byte[] + jboolean isShareable) { + jobject largeBitmap = NULL; + SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024); + + if (stream) { + // for now we don't allow shareable with java inputstreams + SkMemoryStream *mStream = buildSkMemoryStream(stream); + largeBitmap = doBuildTileIndex(env, mStream); + stream->unref(); + } + return largeBitmap; +} + +static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz, + jint native_asset, // Asset + jboolean isShareable) { + SkStream* stream, *assStream; + Asset* asset = reinterpret_cast<Asset*>(native_asset); + assStream = new AssetStreamAdaptor(asset); + stream = buildSkMemoryStream(assStream); + assStream->unref(); + return doBuildTileIndex(env, stream); +} + +/* + * nine patch not supported + * + * purgeable not supported + * reportSizeToVM not supported + */ +static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd, + int start_x, int start_y, int width, int height, jobject options) { + SkImageDecoder *decoder = brd->getDecoder(); + int sampleSize = 1; + SkBitmap::Config prefConfig = SkBitmap::kNo_Config; + bool doDither = true; + bool preferQualityOverSpeed = false; + + if (NULL != options) { + sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); + // initialize these, in case we fail later on + env->SetIntField(options, gOptions_widthFieldID, -1); + env->SetIntField(options, gOptions_heightFieldID, -1); + env->SetObjectField(options, gOptions_mimeFieldID, 0); + + jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); + prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); + doDither = env->GetBooleanField(options, gOptions_ditherFieldID); + preferQualityOverSpeed = env->GetBooleanField(options, + gOptions_preferQualityOverSpeedFieldID); + } + + decoder->setDitherImage(doDither); + decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); + SkBitmap* bitmap = new SkBitmap; + SkAutoTDelete<SkBitmap> adb(bitmap); + AutoDecoderCancel adc(options, decoder); + + // To fix the race condition in case "requestCancelDecode" + // happens earlier than AutoDecoderCancel object is added + // to the gAutoDecoderCancelMutex linked list. + if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) { + return nullObjectReturn("gOptions_mCancelID");; + } + + SkIRect region; + region.fLeft = start_x; + region.fTop = start_y; + region.fRight = start_x + width; + region.fBottom = start_y + height; + + if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) { + return nullObjectReturn("decoder->decodeRegion returned false"); + } + + // update options (if any) + if (NULL != options) { + env->SetIntField(options, gOptions_widthFieldID, bitmap->width()); + env->SetIntField(options, gOptions_heightFieldID, bitmap->height()); + // TODO: set the mimeType field with the data from the codec. + // but how to reuse a set of strings, rather than allocating new one + // each time? + env->SetObjectField(options, gOptions_mimeFieldID, + getMimeTypeString(env, decoder->getFormat())); + } + + // detach bitmap from its autotdeleter, since we want to own it now + adb.detach(); + + SkPixelRef* pr; + pr = bitmap->pixelRef(); + // promise we will never change our pixels (great for sharing and pictures) + pr->setImmutable(); + // now create the java bitmap + return GraphicsJNI::createBitmap(env, bitmap, false, NULL); +} + +static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { + return brd->getHeight(); +} + +static int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { + return brd->getWidth(); +} + +static void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { + delete brd; +} + +/////////////////////////////////////////////////////////////////////////////// + +#include <android_runtime/AndroidRuntime.h> + +static JNINativeMethod gBitmapRegionDecoderMethods[] = { + { "nativeDecodeRegion", + "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;", + (void*)nativeDecodeRegion}, + + { "nativeGetHeight", "(I)I", (void*)nativeGetHeight}, + + { "nativeGetWidth", "(I)I", (void*)nativeGetWidth}, + + { "nativeClean", "(I)V", (void*)nativeClean}, + + { "nativeNewInstance", + "([BIIZ)Landroid/graphics/BitmapRegionDecoder;", + (void*)nativeNewInstanceFromByteArray + }, + + { "nativeNewInstance", + "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;", + (void*)nativeNewInstanceFromStream + }, + + { "nativeNewInstance", + "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;", + (void*)nativeNewInstanceFromFileDescriptor + }, + + { "nativeNewInstance", + "(IZ)Landroid/graphics/BitmapRegionDecoder;", + (void*)nativeNewInstanceFromAsset + }, +}; + +#define kClassPathName "android/graphics/BitmapRegionDecoder" + +static jclass make_globalref(JNIEnv* env, const char classname[]) { + jclass c = env->FindClass(classname); + SkASSERT(c); + return (jclass)env->NewGlobalRef(c); +} + +static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, + const char fieldname[], const char type[]) { + jfieldID id = env->GetFieldID(clazz, fieldname, type); + SkASSERT(id); + return id; +} + +int register_android_graphics_BitmapRegionDecoder(JNIEnv* env); +int register_android_graphics_BitmapRegionDecoder(JNIEnv* env) +{ + + gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor"); + gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I"); + return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, + gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods)); +} diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 195f4d2..9467be8 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -46,7 +46,7 @@ void doThrowOOME(JNIEnv* env, const char* msg) { } void doThrowIOE(JNIEnv* env, const char* msg) { - doThrow(env, "java/lang/IOException", msg); + doThrow(env, "java/io/IOException", msg); } bool GraphicsJNI::hasException(JNIEnv *env) { @@ -168,6 +168,9 @@ static jmethodID gBitmap_allocBufferMethodID; static jclass gBitmapConfig_class; static jfieldID gBitmapConfig_nativeInstanceID; +static jclass gBitmapRegionDecoder_class; +static jmethodID gBitmapRegionDecoder_constructorMethodID; + static jclass gCanvas_class; static jfieldID gCanvas_nativeInstanceID; @@ -374,6 +377,24 @@ jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, return obj; } +jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) +{ + SkASSERT(bitmap != NULL); + + jobject obj = env->AllocObject(gBitmapRegionDecoder_class); + if (hasException(env)) { + obj = NULL; + return obj; + } + if (obj) { + env->CallVoidMethod(obj, gBitmapRegionDecoder_constructorMethodID, (jint)bitmap); + if (hasException(env)) { + obj = NULL; + } + } + return obj; +} + jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) { SkASSERT(region != NULL); @@ -592,6 +613,9 @@ int register_android_graphics_Graphics(JNIEnv* env) gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(IZ[BI)V"); + gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); + gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V"); + gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config"); gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class, "nativeInt", "I"); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index 1f94418..d0f9125 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -4,6 +4,7 @@ #include "SkPoint.h" #include "SkRect.h" #include "SkBitmap.h" +#include "../images/SkBitmapRegionDecoder.h" #include "../images/SkImageDecoder.h" #include <jni.h> @@ -55,6 +56,8 @@ public: static jobject createRegion(JNIEnv* env, SkRegion* region); + static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap); + /** Set a pixelref for the bitmap (needs setConfig to already be called) Returns true on success. If it returns false, then it failed, and the appropriate exception will have been raised. diff --git a/core/res/res/values-ar/donottranslate-cldr.xml b/core/res/res/values-ar/donottranslate-cldr.xml new file mode 100644 index 0000000..d662590 --- /dev/null +++ b/core/res/res/values-ar/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE، d MMMM y</string> +</resources> diff --git a/core/res/res/values-bg/donottranslate-cldr.xml b/core/res/res/values-bg/donottranslate-cldr.xml new file mode 100644 index 0000000..c15e4a7 --- /dev/null +++ b/core/res/res/values-bg/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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">%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 %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">%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 %9$s, %1$s - %8$s %7$s y, %6$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">d MMM y, E</string> +</resources> diff --git a/core/res/res/values-ca/donottranslate-cldr.xml b/core/res/res/values-ca/donottranslate-cldr.xml new file mode 100644 index 0000000..a77aa38 --- /dev/null +++ b/core/res/res/values-ca/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d MMM y</string> +</resources> diff --git a/core/res/res/values-fa/donottranslate-cldr.xml b/core/res/res/values-fa/donottranslate-cldr.xml new file mode 100644 index 0000000..83f4942 --- /dev/null +++ b/core/res/res/values-fa/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">ژانویه</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_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">%-e %B %Y</string> + <string name="time_of_day">%-k:%M:%S</string> + <string name="date_and_time">%-k:%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">%-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، %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 LLLL تا %8$s LLLL</string> + <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string> + <string name="same_year_md1_time1_md2_time2">%5$s، %3$s LLLL تا %10$s، %8$s LLLL</string> + <string name="same_month_md1_time1_md2_time2">%5$s، %3$s LLLL تا %10$s، %8$s LLLL</string> + <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s، %1$s %3$s LLLL تا %10$s، %6$s %8$s LLLL</string> + <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s، %1$s %3$s LLLL تا %10$s، %6$s %8$s LLLL</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 LLL</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s LLLL تا %6$s %8$s LLLL</string> + <string name="same_year_mdy1_mdy2">%3$s LLL تا %8$s %2$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 LLL تا %6$s %8$s %2$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E d LLLL</string> + <string name="abbrev_wday_month_day_year">E d MMM y</string> +</resources> diff --git a/core/res/res/values-fi/donottranslate-cldr.xml b/core/res/res/values-fi/donottranslate-cldr.xml new file mode 100644 index 0000000..5146a0a --- /dev/null +++ b/core/res/res/values-fi/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d. MMM y</string> +</resources> diff --git a/core/res/res/values-hr/donottranslate-cldr.xml b/core/res/res/values-hr/donottranslate-cldr.xml new file mode 100644 index 0000000..23332aa --- /dev/null +++ b/core/res/res/values-hr/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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">siječanj</string> + <string name="month_long_standalone_february">veljača</string> + <string name="month_long_standalone_march">ožujak</string> + <string name="month_long_standalone_april">travanj</string> + <string name="month_long_standalone_may">svibanj</string> + <string name="month_long_standalone_june">lipanj</string> + <string name="month_long_standalone_july">srpanj</string> + <string name="month_long_standalone_august">kolovoz</string> + <string name="month_long_standalone_september">rujan</string> + <string name="month_long_standalone_october">listopad</string> + <string name="month_long_standalone_november">studeni</string> + <string name="month_long_standalone_december">prosinac</string> + + <string name="month_long_january">siječnja</string> + <string name="month_long_february">veljače</string> + <string name="month_long_march">ožujka</string> + <string name="month_long_april">travnja</string> + <string name="month_long_may">svibnja</string> + <string name="month_long_june">lipnja</string> + <string name="month_long_july">srpnja</string> + <string name="month_long_august">kolovoza</string> + <string name="month_long_september">rujna</string> + <string name="month_long_october">listopada</string> + <string name="month_long_november">studenoga</string> + <string name="month_long_december">prosinca</string> + + <string name="month_medium_january">01.</string> + <string name="month_medium_february">02.</string> + <string name="month_medium_march">03.</string> + <string name="month_medium_april">04.</string> + <string name="month_medium_may">05.</string> + <string name="month_medium_june">06.</string> + <string name="month_medium_july">07.</string> + <string name="month_medium_august">08.</string> + <string name="month_medium_september">09.</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">nedjelja</string> + <string name="day_of_week_long_monday">ponedjeljak</string> + <string name="day_of_week_long_tuesday">utorak</string> + <string name="day_of_week_long_wednesday">srijeda</string> + <string name="day_of_week_long_thursday">četvrtak</string> + <string name="day_of_week_long_friday">petak</string> + <string name="day_of_week_long_saturday">subota</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">uto</string> + <string name="day_of_week_medium_wednesday">sri</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">sub</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">uto</string> + <string name="day_of_week_short_wednesday">sri</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">sub</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">AM</string> + <string name="pm">PM</string> + <string name="yesterday">jučer</string> + <string name="today">danas</string> + <string name="tomorrow">sutra</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">%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> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d.MMM.y.</string> +</resources> diff --git a/core/res/res/values-hu/donottranslate-cldr.xml b/core/res/res/values-hu/donottranslate-cldr.xml new file mode 100644 index 0000000..996eefb --- /dev/null +++ b/core/res/res/values-hu/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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">%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 %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s. %2$s %3$s., %1$s - %9$s. %7$s %8$s., %6$s</string> + <string name="same_month_md1_md2">%2$s %3$s-%8$s.</string> + <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string> + <string name="same_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> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">y. MMM d., E</string> +</resources> diff --git a/core/res/res/values-in-rID/donottranslate-cldr.xml b/core/res/res/values-in-rID/donottranslate-cldr.xml new file mode 100644 index 0000000..4d4ebb2 --- /dev/null +++ b/core/res/res/values-in-rID/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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="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_day_year">%-e %B %Y</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> + <string name="full_wday_month_day_no_year">EEEE MMMM d</string> + <string name="abbrev_wday_month_day_year">E, d MMM yyyy</string> +</resources> diff --git a/core/res/res/values-in/donottranslate-cldr.xml b/core/res/res/values-in/donottranslate-cldr.xml new file mode 100644 index 0000000..7a58a19 --- /dev/null +++ b/core/res/res/values-in/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-iw-rIL/arrays.xml b/core/res/res/values-iw-rIL/arrays.xml new file mode 100644 index 0000000..87c1231 --- /dev/null +++ b/core/res/res/values-iw-rIL/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, 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. +*/ +--> +<resources> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>31046051</item> + <item>34851612</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-iw/donottranslate-cldr.xml b/core/res/res/values-iw/donottranslate-cldr.xml new file mode 100644 index 0000000..d373a34 --- /dev/null +++ b/core/res/res/values-iw/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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 %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, %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 %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">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-lt/donottranslate-cldr.xml b/core/res/res/values-lt/donottranslate-cldr.xml new file mode 100644 index 0000000..25458bd --- /dev/null +++ b/core/res/res/values-lt/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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">%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 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">%1$s %2$s %3$s - %6$s %7$s %8$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> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">y \'m\'. MMM d \'d\'.,E</string> +</resources> diff --git a/core/res/res/values-lv/donottranslate-cldr.xml b/core/res/res/values-lv/donottranslate-cldr.xml new file mode 100644 index 0000000..2de9367 --- /dev/null +++ b/core/res/res/values-lv/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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.mm–%8$s.mm</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.mm.%4$s.–%8$s.mm.%9$s.</string> + <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.mm.%4$s. – %6$s, %8$s.mm.%9$s.</string> + <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.mm.%4$s. - %10$s %6$s, %8$s.mm.%9$s.</string> + <string name="numeric_md1_time1_md2_time2">%5$s %3$s.mm. - %10$s %8$s.mm.</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> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, yyyy. \'g\'. dd. MMM</string> +</resources> diff --git a/core/res/res/values-rm-rCH/arrays.xml b/core/res/res/values-rm-rCH/arrays.xml new file mode 100644 index 0000000..f2982e9 --- /dev/null +++ b/core/res/res/values-rm-rCH/arrays.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2006, 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. +*/ +--> +<resources> + + <!-- Do not translate. --> + <integer-array name="maps_starting_lat_lng"> + <item>46948020</item> + <item>7448206</item> + </integer-array> + <!-- Do not translate. --> + <integer-array name="maps_starting_zoom"> + <item>4</item> + </integer-array> + +</resources> diff --git a/core/res/res/values-rm/donottranslate-cldr.xml b/core/res/res/values-rm/donottranslate-cldr.xml new file mode 100644 index 0000000..ccdb17c --- /dev/null +++ b/core/res/res/values-rm/donottranslate-cldr.xml @@ -0,0 +1,145 @@ +<?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">schaner</string> + <string name="month_long_standalone_february">favrer</string> + <string name="month_long_standalone_march">mars</string> + <string name="month_long_standalone_april">avrigl</string> + <string name="month_long_standalone_may">matg</string> + <string name="month_long_standalone_june">zercladur</string> + <string name="month_long_standalone_july">fanadur</string> + <string name="month_long_standalone_august">avust</string> + <string name="month_long_standalone_september">settember</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">schaner</string> + <string name="month_long_february">favrer</string> + <string name="month_long_march">mars</string> + <string name="month_long_april">avrigl</string> + <string name="month_long_may">matg</string> + <string name="month_long_june">zercladur</string> + <string name="month_long_july">fanadur</string> + <string name="month_long_august">avust</string> + <string name="month_long_september">settember</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">schan.</string> + <string name="month_medium_february">favr.</string> + <string name="month_medium_march">mars</string> + <string name="month_medium_april">avr.</string> + <string name="month_medium_may">matg</string> + <string name="month_medium_june">zercl.</string> + <string name="month_medium_july">fan.</string> + <string name="month_medium_august">avust</string> + <string name="month_medium_september">sett.</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">S</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">Z</string> + <string name="month_shortest_july">F</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">dumengia</string> + <string name="day_of_week_long_monday">glindesdi</string> + <string name="day_of_week_long_tuesday">mardi</string> + <string name="day_of_week_long_wednesday">mesemna</string> + <string name="day_of_week_long_thursday">gievgia</string> + <string name="day_of_week_long_friday">venderdi</string> + <string name="day_of_week_long_saturday">sonda</string> + + <string name="day_of_week_medium_sunday">du</string> + <string name="day_of_week_medium_monday">gli</string> + <string name="day_of_week_medium_tuesday">ma</string> + <string name="day_of_week_medium_wednesday">me</string> + <string name="day_of_week_medium_thursday">gie</string> + <string name="day_of_week_medium_friday">ve</string> + <string name="day_of_week_medium_saturday">so</string> + + <string name="day_of_week_short_sunday">du</string> + <string name="day_of_week_short_monday">gli</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">gie</string> + <string name="day_of_week_short_friday">ve</string> + <string name="day_of_week_short_saturday">so</string> + + <string name="day_of_week_shortest_sunday">D</string> + <string name="day_of_week_shortest_monday">G</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="yesterday">ier</string> + <string name="today">oz</string> + <string name="tomorrow">damaun</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">%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">%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 %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-ro/donottranslate-cldr.xml b/core/res/res/values-ro/donottranslate-cldr.xml new file mode 100644 index 0000000..ef34103 --- /dev/null +++ b/core/res/res/values-ro/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E, d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/res/res/values-sk/donottranslate-cldr.xml b/core/res/res/values-sk/donottranslate-cldr.xml new file mode 100644 index 0000000..b2ed9b7 --- /dev/null +++ b/core/res/res/values-sk/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E, d. MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d. MMM y</string> +</resources> diff --git a/core/res/res/values-sl/donottranslate-cldr.xml b/core/res/res/values-sl/donottranslate-cldr.xml new file mode 100644 index 0000000..372b0d5 --- /dev/null +++ b/core/res/res/values-sl/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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 %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">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s. %9$s</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">E., d. MMM. y</string> +</resources> diff --git a/core/res/res/values-sr/donottranslate-cldr.xml b/core/res/res/values-sr/donottranslate-cldr.xml new file mode 100644 index 0000000..7c5c6a9 --- /dev/null +++ b/core/res/res/values-sr/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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 %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 %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">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s.</string> + <string name="short_format_month">%b</string> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, d. MMM y.</string> +</resources> diff --git a/core/res/res/values-th/donottranslate-cldr.xml b/core/res/res/values-th/donottranslate-cldr.xml new file mode 100644 index 0000000..4e6bafe --- /dev/null +++ b/core/res/res/values-th/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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 – %6$s %8$s/%2$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> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE d MMM y</string> +</resources> diff --git a/core/res/res/values-tl/donottranslate-cldr.xml b/core/res/res/values-tl/donottranslate-cldr.xml new file mode 100644 index 0000000..e3106c7 --- /dev/null +++ b/core/res/res/values-tl/donottranslate-cldr.xml @@ -0,0 +1,123 @@ +<?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">1</string> + <string name="day_of_week_long_monday">2</string> + <string name="day_of_week_long_tuesday">3</string> + <string name="day_of_week_long_wednesday">4</string> + <string name="day_of_week_long_thursday">5</string> + <string name="day_of_week_long_friday">6</string> + <string name="day_of_week_long_saturday">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">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">%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">%H:%M:%S</string> + <string name="date_and_time">%H:%M:%S %Y %b %-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 %b %-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">%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 %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">%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> + <string name="full_wday_month_day_no_year">E MMMM d</string> + <string name="abbrev_wday_month_day_year">EEE, y MMM d</string> +</resources> diff --git a/core/res/res/values-uk/donottranslate-cldr.xml b/core/res/res/values-uk/donottranslate-cldr.xml new file mode 100644 index 0000000..0a49c20 --- /dev/null +++ b/core/res/res/values-uk/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E, d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/res/res/values-vi/donottranslate-cldr.xml b/core/res/res/values-vi/donottranslate-cldr.xml new file mode 100644 index 0000000..30e0887 --- /dev/null +++ b/core/res/res/values-vi/donottranslate-cldr.xml @@ -0,0 +1,149 @@ +<?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> + <string name="full_wday_month_day_no_year">E d MMMM</string> + <string name="abbrev_wday_month_day_year">EEE, d MMM y</string> +</resources> diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index d5f385b..c8a4593 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -47,6 +47,7 @@ import android.util.Log; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; public class PackageManagerTests extends AndroidTestCase { private static final boolean localLOGV = true; @@ -2838,6 +2839,164 @@ public class PackageManagerTests extends AndroidTestCase { installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true, fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED); } + + @LargeTest + public void testPackageObbPaths_Nonexistent() { + try { + final PackageManager pm = getPm(); + + // Invalid Java package name. + pm.getPackageObbPaths("=non-existent"); + + fail("Should not be able to get package OBB paths for non-existent package"); + } catch (IllegalArgumentException e) { + // pass + } + } + + @LargeTest + public void testPackageObbPaths_Initial() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + assertEquals("Initial obb paths should be null", + null, pm.getPackageObbPaths(ip.pkg.packageName)); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_Null() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + pm.setPackageObbPaths(ip.pkg.packageName, null); + + assertEquals("Returned paths should be null", + null, pm.getPackageObbPaths(ip.pkg.packageName)); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_Empty() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + final String[] paths = new String[0]; + + pm.setPackageObbPaths(ip.pkg.packageName, paths); + + assertEquals("Empty list should be interpreted as null", + null, pm.getPackageObbPaths(ip.pkg.packageName)); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_Single() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + final String[] paths = new String[] { + "/example/test", + }; + + pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); + + assertTrue("Previously set paths should be the same as the returned paths.", + Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_Multiple() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + final String[] paths = new String[] { + "/example/test1", + "/example/test2", + }; + + pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); + + assertTrue("Previously set paths should be the same as the returned paths.", + Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_Twice() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + final String[] paths = new String[] { + "/example/test1", + "/example/test2", + }; + + pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); + + assertTrue("Previously set paths should be the same as the returned paths.", + Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); + + paths[0] = "/example/test3"; + pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); + + assertTrue("Previously set paths should be the same as the returned paths.", + Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); + } finally { + cleanUpInstall(ip); + } + } + + @LargeTest + public void testPackageObbPaths_ReplacePackage() { + InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); + + try { + final PackageManager pm = getPm(); + + final String[] paths = new String[] { + "/example/test1", + "/example/test2", + }; + + pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); + + Log.i(TAG, "Creating replaceReceiver"); + final GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName); + + final int flags = PackageManager.INSTALL_REPLACE_EXISTING; + invokeInstallPackage(ip.packageURI, flags, receiver); + assertInstall(ip.pkg, flags, ip.pkg.installLocation); + + assertTrue("Previously set paths should be the same as the returned paths.", + Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); + } finally { + cleanUpInstall(ip); + } + } /*---------- Recommended install location tests ----*/ /* * TODO's diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 7b49bc5..3f1a566 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -206,10 +206,20 @@ public class BitmapFactory { public boolean inNativeAlloc; /** + * If inPreferQualityOverSpeed is set to true, the decoder will try to + * decode the reconstructed image to a higher quality even at the + * expense of the decoding speed. Currently the field only affects JPEG + * decode, in the case of which a more accurate, but slightly slower, + * IDCT method will be used instead. + */ + public boolean inPreferQualityOverSpeed; + + /** * The resulting width of the bitmap, set independent of the state of * inJustDecodeBounds. However, if there is an error trying to decode, * outWidth will be set to -1. */ + public int outWidth; /** diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java new file mode 100644 index 0000000..496e0c7 --- /dev/null +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -0,0 +1,263 @@ +/* Copyright (C) 2010 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.graphics; + +import android.content.res.AssetManager; + +import java.io.BufferedInputStream; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * BitmapRegionDecoder can be used to decode a rectangle region from an image. + * BitmapRegionDecoder is particularly useful when an original image is large and + * you only need parts of the image. + * + * <p>To create a BitmapRegionDecoder, call newInstance(...). + * Given a BitmapRegionDecoder, users can call decodeRegion() repeatedly + * to get a decoded Bitmap of the specified region. + * + */ +public final class BitmapRegionDecoder { + private int mNativeBitmapRegionDecoder; + private boolean mRecycled; + + /** + * Create a BitmapRegionDecoder from the specified byte array. + * Currently only the JPEG and PNG formats are supported. + * + * @param data byte array of compressed image data. + * @param offset offset into data for where the decoder should begin + * parsing. + * @param length the number of bytes, beginning at offset, to parse + * @param isShareable If this is true, then the BitmapRegionDecoder may keep a + * shallow reference to the input. If this is false, + * then the BitmapRegionDecoder will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + */ + public static BitmapRegionDecoder newInstance(byte[] data, + int offset, int length, boolean isShareable) throws IOException { + if ((offset | length) < 0 || data.length < offset + length) { + throw new ArrayIndexOutOfBoundsException(); + } + return nativeNewInstance(data, offset, length, isShareable); + } + + /** + * Create a BitmapRegionDecoder from the file descriptor. + * The position within the descriptor will not be changed when + * this returns, so the descriptor can be used again as is. + * Currently only the JPEG and PNG formats are supported. + * + * @param fd The file descriptor containing the data to decode + * @param isShareable If this is true, then the BitmapRegionDecoder may keep a + * shallow reference to the input. If this is false, + * then the BitmapRegionDecoder will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + */ + public static BitmapRegionDecoder newInstance( + FileDescriptor fd, boolean isShareable) throws IOException { + return nativeNewInstance(fd, isShareable); + } + + /** + * Create a BitmapRegionDecoder from an input stream. + * The stream's position will be where ever it was after the encoded data + * was read. + * Currently only the JPEG and PNG formats are supported. + * + * @param is The input stream that holds the raw data to be decoded into a + * BitmapRegionDecoder. + * @param isShareable If this is true, then the BitmapRegionDecoder may keep a + * shallow reference to the input. If this is false, + * then the BitmapRegionDecoder will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + */ + public static BitmapRegionDecoder newInstance(InputStream is, + boolean isShareable) throws IOException { + // we need mark/reset to work properly in JNI + + if (!is.markSupported()) { + is = new BufferedInputStream(is, 16 * 1024); + } + + if (is instanceof AssetManager.AssetInputStream) { + return nativeNewInstance( + ((AssetManager.AssetInputStream) is).getAssetInt(), + isShareable); + } else { + // pass some temp storage down to the native code. 1024 is made up, + // but should be large enough to avoid too many small calls back + // into is.read(...). + byte [] tempStorage = new byte[16 * 1024]; + return nativeNewInstance(is, tempStorage, isShareable); + } + } + + /** + * Create a BitmapRegionDecoder from a file path. + * Currently only the JPEG and PNG formats are supported. + * + * @param pathName complete path name for the file to be decoded. + * @param isShareable If this is true, then the BitmapRegionDecoder may keep a + * shallow reference to the input. If this is false, + * then the BitmapRegionDecoder will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return BitmapRegionDecoder, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + */ + public static BitmapRegionDecoder newInstance(String pathName, + boolean isShareable) throws IOException { + BitmapRegionDecoder decoder = null; + InputStream stream = null; + + try { + stream = new FileInputStream(pathName); + decoder = newInstance(stream, isShareable); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // do nothing here + } + } + } + return decoder; + } + + /* Private constructor that must receive an already allocated native + region decoder int (pointer). + + This can be called from JNI code. + */ + private BitmapRegionDecoder(int decoder) { + mNativeBitmapRegionDecoder = decoder; + mRecycled = false; + } + + /** + * Decodes a rectangle region in the image specified by rect. + * + * @param rect The rectangle that specified the region to be decode. + * @param options null-ok; Options that control downsampling. + * inPurgeable is not supported. + * @return The decoded bitmap, or null if the image data could not be + * decoded. + */ + public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { + checkRecycled("decodeRegion called on recycled region decoder"); + if (rect.left < 0 || rect.top < 0 || rect.right > getWidth() + || rect.bottom > getHeight()) + throw new IllegalArgumentException("rectangle is not inside the image"); + return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, options); + } + + /** Returns the original image's width */ + public int getWidth() { + checkRecycled("getWidth called on recycled region decoder"); + return nativeGetWidth(mNativeBitmapRegionDecoder); + } + + /** Returns the original image's height */ + public int getHeight() { + checkRecycled("getHeight called on recycled region decoder"); + return nativeGetHeight(mNativeBitmapRegionDecoder); + } + + /** + * Frees up the memory associated with this region decoder, and mark the + * region decoder as "dead", meaning it will throw an exception if decodeRegion(), + * getWidth() or getHeight() is called. + * + * <p>This operation cannot be reversed, so it should only be called if you are + * sure there are no further uses for the region decoder. This is an advanced call, + * and normally need not be called, since the normal GC process will free up this + * memory when there are no more references to this region decoder. + */ + public void recycle() { + if (!mRecycled) { + nativeClean(mNativeBitmapRegionDecoder); + mRecycled = true; + } + } + + /** + * Returns true if this region decoder has been recycled. + * If so, then it is an error to try use its method. + * + * @return true if the region decoder has been recycled + */ + public final boolean isRecycled() { + return mRecycled; + } + + /** + * Called by methods that want to throw an exception if the region decoder + * has already been recycled. + */ + private void checkRecycled(String errorMessage) { + if (mRecycled) { + throw new IllegalStateException(errorMessage); + } + } + + @Override + protected void finalize() throws Throwable { + try { + recycle(); + } finally { + super.finalize(); + } + } + + private static native Bitmap nativeDecodeRegion(int lbm, + int start_x, int start_y, int width, int height, + BitmapFactory.Options options); + private static native int nativeGetWidth(int lbm); + private static native int nativeGetHeight(int lbm); + private static native void nativeClean(int lbm); + + private static native BitmapRegionDecoder nativeNewInstance( + byte[] data, int offset, int length, boolean isShareable); + private static native BitmapRegionDecoder nativeNewInstance( + FileDescriptor fd, boolean isShareable); + private static native BitmapRegionDecoder nativeNewInstance( + InputStream is, byte[] storage, boolean isShareable); + private static native BitmapRegionDecoder nativeNewInstance( + int asset, boolean isShareable); +} diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h index 9baba8e..8e3cdbb 100644 --- a/include/media/IMediaMetadataRetriever.h +++ b/include/media/IMediaMetadataRetriever.h @@ -32,9 +32,7 @@ public: virtual void disconnect() = 0; virtual status_t setDataSource(const char* srcUrl) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setMode(int mode) = 0; - virtual status_t getMode(int* mode) const = 0; - virtual sp<IMemory> captureFrame() = 0; + virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0; virtual sp<IMemory> extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; }; diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h index ff57774..0449122 100644 --- a/include/media/MediaMetadataRetrieverInterface.h +++ b/include/media/MediaMetadataRetrieverInterface.h @@ -32,9 +32,7 @@ public: virtual ~MediaMetadataRetrieverBase() {} virtual status_t setDataSource(const char *url) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setMode(int mode) = 0; - virtual status_t getMode(int* mode) const = 0; - virtual VideoFrame* captureFrame() = 0; + virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0; virtual MediaAlbumArt* extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; }; @@ -43,35 +41,12 @@ public: class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase { public: - MediaMetadataRetrieverInterface() - : mMode(0) { - } + MediaMetadataRetrieverInterface() {} virtual ~MediaMetadataRetrieverInterface() {} - - // @param mode The intended mode of operations: - // can be any of the following: - // METADATA_MODE_NOOP: Experimental - just add and remove data source. - // METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only. - // METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only. - // METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame - // capture and meta data retrieval. - virtual status_t setMode(int mode) { - if (mode < METADATA_MODE_NOOP || - mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) { - return BAD_VALUE; - } - - mMode = mode; - return NO_ERROR; - } - - virtual status_t getMode(int* mode) const { *mode = mMode; return NO_ERROR; } - virtual VideoFrame* captureFrame() { return NULL; } + virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) { return NULL; } virtual MediaAlbumArt* extractAlbumArt() { return NULL; } virtual const char* extractMetadata(int keyCode) { return NULL; } - - uint32_t mMode; }; }; // namespace android diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index ddc07f6..e905006 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -42,37 +42,14 @@ enum { METADATA_KEY_YEAR = 8, METADATA_KEY_DURATION = 9, METADATA_KEY_NUM_TRACKS = 10, - METADATA_KEY_IS_DRM_CRIPPLED = 11, - METADATA_KEY_CODEC = 12, - METADATA_KEY_RATING = 13, - METADATA_KEY_COMMENT = 14, - METADATA_KEY_COPYRIGHT = 15, - METADATA_KEY_BIT_RATE = 16, - METADATA_KEY_FRAME_RATE = 17, - METADATA_KEY_VIDEO_FORMAT = 18, - METADATA_KEY_VIDEO_HEIGHT = 19, - METADATA_KEY_VIDEO_WIDTH = 20, - METADATA_KEY_WRITER = 21, - METADATA_KEY_MIMETYPE = 22, - METADATA_KEY_DISC_NUMBER = 23, - METADATA_KEY_ALBUMARTIST = 24, - METADATA_KEY_COMPILATION = 25, + METADATA_KEY_WRITER = 11, + METADATA_KEY_MIMETYPE = 12, + METADATA_KEY_ALBUMARTIST = 13, + METADATA_KEY_DISC_NUMBER = 14, + METADATA_KEY_COMPILATION = 15, // Add more here... }; -// The intended mode of operations:$ -// METADATA_MODE_NOOP: Experimental - just add and remove data source.$ -// METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only.$ -// METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only.$ -// METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame capture -// and meta data retrieval.$ -enum { - METADATA_MODE_NOOP = 0x00, - METADATA_MODE_METADATA_RETRIEVAL_ONLY = 0x01, - METADATA_MODE_FRAME_CAPTURE_ONLY = 0x02, - METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL = 0x03 -}; - class MediaMetadataRetriever: public RefBase { public: @@ -81,9 +58,7 @@ public: void disconnect(); status_t setDataSource(const char* dataSourceUrl); status_t setDataSource(int fd, int64_t offset, int64_t length); - status_t setMode(int mode); - status_t getMode(int* mode); - sp<IMemory> captureFrame(); + sp<IMemory> getFrameAtTime(int64_t timeUs, int option); sp<IMemory> extractAlbumArt(); const char* extractMetadata(int keyCode); diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index f6c55e4..ad9a94f 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -774,6 +774,9 @@ int Thread::_threadLoop(void* user) self->mExitPending = true; self->mLock.lock(); self->mRunning = false; + // clear thread ID so that requestExitAndWait() does not exit if + // called by a new thread using the same thread ID as this one. + self->mThread = thread_id_t(-1); self->mThreadExitedCondition.broadcast(); self->mLock.unlock(); break; diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 008528d..77e939e 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -29,7 +29,6 @@ import java.io.IOException; /** * MediaMetadataRetriever class provides a unified interface for retrieving * frame and meta data from an input media file. - * {@hide} */ public class MediaMetadataRetriever { @@ -42,41 +41,13 @@ public class MediaMetadataRetriever @SuppressWarnings("unused") private int mNativeContext; + private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF; + public MediaMetadataRetriever() { native_setup(); } /** - * Call this method before setDataSource() so that the mode becomes - * effective for subsequent operations. This method can be called only once - * at the beginning if the intended mode of operation for a - * MediaMetadataRetriever object remains the same for its whole lifetime, - * and thus it is unnecessary to call this method each time setDataSource() - * is called. If this is not never called (which is allowed), by default the - * intended mode of operation is to both capture frame and retrieve meta - * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). - * Often, this may not be what one wants, since doing this has negative - * performance impact on execution time of a call to setDataSource(), since - * both types of operations may be time consuming. - * - * @param mode The intended mode of operation. Can be any combination of - * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: - * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: - * For neither frame capture nor meta data retrieval - * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only - * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only - * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: - * For both frame capture and meta data retrieval - */ - public native void setMode(int mode); - - /** - * @return the current mode of operation. A negative return value indicates - * some runtime error has occurred. - */ - public native int getMode(); - - /** * Sets the data source (file pathname) to use. Call this * method before the rest of the methods in this class. This method may be * time-consuming. @@ -190,22 +161,99 @@ public class MediaMetadataRetriever /** * Call this method after setDataSource(). This method finds a - * representative frame if successful and returns it as a bitmap. This is - * useful for generating a thumbnail for an input media source. - * + * representative frame close to the given time position by considering + * the given option if possible, and returns it as a bitmap. This is + * useful for generating a thumbnail for an input data source or just + * obtain and display a frame at the given time position. + * + * @param timeUs The time position where the frame will be retrieved. + * When retrieving the frame at the given time position, there is no + * guarantee that the data source has a frame located at the position. + * When this happens, a frame nearby will be returned. If timeUs is + * negative, time position and option will ignored, and any frame + * that the implementation considers as representative may be returned. + * + * @param option a hint on how the frame is found. Use + * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame + * that has a timestamp earlier than or the same as timeUs. Use + * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame + * that has a timestamp later than or the same as timeUs. Use + * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame + * that has a timestamp closest to or the same as timeUs. Use + * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may + * or may not be a sync frame but is closest to or the same as timeUs. + * {@link #OPTION_CLOSEST} often has larger performance overhead compared + * to the other options if there is no sync frame located at timeUs. + * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. */ - public native Bitmap captureFrame(); + public Bitmap getFrameAtTime(long timeUs, int option) { + if (option < OPTION_PREVIOUS_SYNC || + option > OPTION_CLOSEST) { + throw new IllegalArgumentException("Unsupported option: " + option); + } + + return _getFrameAtTime(timeUs, option); + } + + /** + * Call this method after setDataSource(). This method finds a + * representative frame close to the given time position if possible, + * and returns it as a bitmap. This is useful for generating a thumbnail + * for an input data source. Call this method if one does not care + * how the frame is found as long as it is close to the given time; + * otherwise, please call {@link #getFrameAtTime(long, int)}. + * + * @param timeUs The time position where the frame will be retrieved. + * When retrieving the frame at the given time position, there is no + * guarentee that the data source has a frame located at the position. + * When this happens, a frame nearby will be returned. If timeUs is + * negative, time position and option will ignored, and any frame + * that the implementation considers as representative may be returned. + * + * @return A Bitmap containing a representative video frame, which + * can be null, if such a frame cannot be retrieved. + * + * @see #getFrameAtTime(long, int) + */ + public Bitmap getFrameAtTime(long timeUs) { + return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC); + } + + /** + * Call this method after setDataSource(). This method finds a + * representative frame at any time position if possible, + * and returns it as a bitmap. This is useful for generating a thumbnail + * for an input data source. Call this method if one does not + * care about where the frame is located; otherwise, please call + * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)} + * + * @return A Bitmap containing a representative video frame, which + * can be null, if such a frame cannot be retrieved. + * + * @see #getFrameAtTime(long) + * @see #getFrameAtTime(long, int) + */ + public Bitmap getFrameAtTime() { + return getFrameAtTime(-1, OPTION_CLOSEST_SYNC); + } + + private native Bitmap _getFrameAtTime(long timeUs, int option); + /** * Call this method after setDataSource(). This method finds the optional - * graphic or album art associated (embedded or external url linked) the - * related data source. + * graphic or album art associated associated with the data source. If + * there are more than one pictures, (any) one of them is returned. * * @return null if no such graphic is found. */ - public native byte[] extractAlbumArt(); + public byte[] getEmbeddedPicture() { + return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY); + } + + private native byte[] getEmbeddedPicture(int pictureType); /** * Call it when one is done with the object. This method releases the memory @@ -226,38 +274,129 @@ public class MediaMetadataRetriever } } - public static final int MODE_GET_METADATA_ONLY = 0x01; - public static final int MODE_CAPTURE_FRAME_ONLY = 0x02; + /** + * Option used in method {@link #getFrameAtTime(long, int)} to get a + * frame at a specified location. + * + * @see #getFrameAtTime(long, int) + */ + /* Do not change these option values without updating their counterparts + * in include/media/stagefright/MediaSource.h! + */ + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * right before or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_PREVIOUS_SYNC = 0x00; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * right after or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_NEXT_SYNC = 0x01; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * closest to (in time) or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_CLOSEST_SYNC = 0x02; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a frame (not necessarily a key frame) associated with a data source that + * is located closest to or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_CLOSEST = 0x03; /* - * Do not change these values without updating their counterparts - * in include/media/mediametadataretriever.h! + * Do not change these metadata key values without updating their + * counterparts in include/media/mediametadataretriever.h! + */ + /** + * The metadata key to retrieve the numberic string describing the + * order of the audio data source on its original recording. */ public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; + /** + * The metadata key to retrieve the information about the album title + * of the data source. + */ public static final int METADATA_KEY_ALBUM = 1; + /** + * The metadata key to retrieve the information about the artist of + * the data source. + */ public static final int METADATA_KEY_ARTIST = 2; + /** + * The metadata key to retrieve the information about the author of + * the data source. + */ public static final int METADATA_KEY_AUTHOR = 3; + /** + * The metadata key to retrieve the information about the composer of + * the data source. + */ public static final int METADATA_KEY_COMPOSER = 4; + /** + * The metadata key to retrieve the date when the data source was created + * or modified. + */ public static final int METADATA_KEY_DATE = 5; + /** + * The metadata key to retrieve the content type or genre of the data + * source. + */ public static final int METADATA_KEY_GENRE = 6; + /** + * The metadata key to retrieve the data source title. + */ public static final int METADATA_KEY_TITLE = 7; + /** + * The metadata key to retrieve the year when the data source was created + * or modified. + */ public static final int METADATA_KEY_YEAR = 8; + /** + * The metadata key to retrieve the playback duration of the data source. + */ public static final int METADATA_KEY_DURATION = 9; + /** + * The metadata key to retrieve the number of tracks, such as audio, video, + * text, in the data source, such as a mp4 or 3gpp file. + */ public static final int METADATA_KEY_NUM_TRACKS = 10; - public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11; - public static final int METADATA_KEY_CODEC = 12; - public static final int METADATA_KEY_RATING = 13; - public static final int METADATA_KEY_COMMENT = 14; - public static final int METADATA_KEY_COPYRIGHT = 15; - public static final int METADATA_KEY_BIT_RATE = 16; - public static final int METADATA_KEY_FRAME_RATE = 17; - public static final int METADATA_KEY_VIDEO_FORMAT = 18; - public static final int METADATA_KEY_VIDEO_HEIGHT = 19; - public static final int METADATA_KEY_VIDEO_WIDTH = 20; - public static final int METADATA_KEY_WRITER = 21; - public static final int METADATA_KEY_MIMETYPE = 22; - public static final int METADATA_KEY_DISCNUMBER = 23; - public static final int METADATA_KEY_ALBUMARTIST = 24; - public static final int METADATA_KEY_COMPILATION = 25; + /** + * The metadata key to retrieve the information of the writer (such as + * lyricist) of the data source. + */ + public static final int METADATA_KEY_WRITER = 11; + /** + * The metadata key to retrieve the mime type of the data source. Some + * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", + * etc. + */ + public static final int METADATA_KEY_MIMETYPE = 12; + /** + * The metadata key to retrieve the information about the performers or + * artist associated with the data source. + */ + public static final int METADATA_KEY_ALBUMARTIST = 13; + /** + * The metadata key to retrieve the numberic string that describes which + * part of a set the audio data source comes from. + */ + public static final int METADATA_KEY_DISC_NUMBER = 14; + /** + * The metadata key to retrieve the music album compilation status. + */ + public static final int METADATA_KEY_COMPILATION = 15; // Add more here... } diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java index 3d85e31..494b4cb 100644 --- a/media/java/android/media/ThumbnailUtils.java +++ b/media/java/android/media/ThumbnailUtils.java @@ -146,9 +146,8 @@ public class ThumbnailUtils { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { - retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(filePath); - bitmap = retriever.captureFrame(); + bitmap = retriever.getFrameAtTime(-1); } catch (IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 63e9dc8..c5e58f7 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -131,33 +131,9 @@ static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jo process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed"); } -static void android_media_MediaMetadataRetriever_setMode(JNIEnv *env, jobject thiz, jint mode) +static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option) { - LOGV("setMode"); - MediaMetadataRetriever* retriever = getRetriever(env, thiz); - if (retriever == 0) { - jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); - return; - } - process_media_retriever_call(env, retriever->setMode(mode), "java/lang/RuntimeException", "setMode failed"); -} - -static int android_media_MediaMetadataRetriever_getMode(JNIEnv *env, jobject thiz) -{ - LOGV("getMode"); - MediaMetadataRetriever* retriever = getRetriever(env, thiz); - if (retriever == 0) { - jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); - return -1; // Error - } - int mode = -1; - retriever->getMode(&mode); - return mode; -} - -static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jobject thiz) -{ - LOGV("captureFrame"); + LOGV("getFrameAtTime: %lld us option: %d", timeUs, option); MediaMetadataRetriever* retriever = getRetriever(env, thiz); if (retriever == 0) { jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); @@ -166,12 +142,12 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo // Call native method to retrieve a video frame VideoFrame *videoFrame = NULL; - sp<IMemory> frameMemory = retriever->captureFrame(); + sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option); if (frameMemory != 0) { // cast the shared structure to a VideoFrame object videoFrame = static_cast<VideoFrame *>(frameMemory->pointer()); } if (videoFrame == NULL) { - LOGE("captureFrame: videoFrame is a NULL pointer"); + LOGE("getFrameAtTime: videoFrame is a NULL pointer"); return NULL; } @@ -213,7 +189,7 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo // Create a SkBitmap to hold the pixels SkBitmap *bitmap = new SkBitmap(); if (bitmap == NULL) { - LOGE("captureFrame: cannot instantiate a SkBitmap object."); + LOGE("getFrameAtTime: cannot instantiate a SkBitmap object."); return NULL; } bitmap->setConfig(SkBitmap::kRGB_565_Config, videoFrame->mDisplayWidth, videoFrame->mDisplayHeight); @@ -242,21 +218,26 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo false); // filter } -static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz) +static jbyteArray android_media_MediaMetadataRetriever_getEmbeddedPicture( + JNIEnv *env, jobject thiz, jint pictureType) { - LOGV("extractAlbumArt"); + LOGV("getEmbeddedPicture: %d", pictureType); MediaMetadataRetriever* retriever = getRetriever(env, thiz); if (retriever == 0) { jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); return NULL; } MediaAlbumArt* mediaAlbumArt = NULL; + + // FIXME: + // Use pictureType to retrieve the intended embedded picture and also change + // the method name to getEmbeddedPicture(). sp<IMemory> albumArtMemory = retriever->extractAlbumArt(); if (albumArtMemory != 0) { // cast the shared structure to a MediaAlbumArt object mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer()); } if (mediaAlbumArt == NULL) { - LOGE("extractAlbumArt: Call to extractAlbumArt failed."); + LOGE("getEmbeddedPicture: Call to getEmbeddedPicture failed."); return NULL; } @@ -264,7 +245,7 @@ static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *e char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt); jbyteArray array = env->NewByteArray(len); if (!array) { // OutOfMemoryError exception has already been thrown. - LOGE("extractAlbumArt: OutOfMemoryError is thrown."); + LOGE("getEmbeddedPicture: OutOfMemoryError is thrown."); } else { jbyte* bytes = env->GetByteArrayElements(array, NULL); if (bytes != NULL) { @@ -365,11 +346,9 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje static JNINativeMethod nativeMethods[] = { {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource}, {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, - {"setMode", "(I)V", (void *)android_media_MediaMetadataRetriever_setMode}, - {"getMode", "()I", (void *)android_media_MediaMetadataRetriever_getMode}, - {"captureFrame", "()Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_captureFrame}, + {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata}, - {"extractAlbumArt", "()[B", (void *)android_media_MediaMetadataRetriever_extractAlbumArt}, + {"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture}, {"release", "()V", (void *)android_media_MediaMetadataRetriever_release}, {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize}, {"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup}, diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index e529d25..d5298c9 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -81,9 +81,7 @@ enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_DATA_SOURCE_URL, SET_DATA_SOURCE_FD, - SET_MODE, - GET_MODE, - CAPTURE_FRAME, + GET_FRAME_AT_TIME, EXTRACT_ALBUM_ART, EXTRACT_METADATA, }; @@ -124,32 +122,17 @@ public: return reply.readInt32(); } - status_t setMode(int mode) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(SET_MODE, data, &reply); - return reply.readInt32(); - } - - status_t getMode(int* mode) const - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - remote()->transact(GET_MODE, data, &reply); - *mode = reply.readInt32(); - return reply.readInt32(); - } - - sp<IMemory> captureFrame() + sp<IMemory> getFrameAtTime(int64_t timeUs, int option) { + LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option); Parcel data, reply; data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeInt64(timeUs); + data.writeInt32(option); #ifndef DISABLE_GROUP_SCHEDULE_HACK sendSchedPolicy(data); #endif - remote()->transact(CAPTURE_FRAME, data, &reply); + remote()->transact(GET_FRAME_AT_TIME, data, &reply); status_t ret = reply.readInt32(); if (ret != NO_ERROR) { return NULL; @@ -216,26 +199,15 @@ status_t BnMediaMetadataRetriever::onTransact( reply->writeInt32(setDataSource(fd, offset, length)); return NO_ERROR; } break; - case SET_MODE: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int mode = data.readInt32(); - reply->writeInt32(setMode(mode)); - return NO_ERROR; - } break; - case GET_MODE: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int mode; - status_t status = getMode(&mode); - reply->writeInt32(mode); - reply->writeInt32(status); - return NO_ERROR; - } break; - case CAPTURE_FRAME: { + case GET_FRAME_AT_TIME: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + int64_t timeUs = data.readInt64(); + int option = data.readInt32(); + LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif - sp<IMemory> bitmap = captureFrame(); + sp<IMemory> bitmap = getFrameAtTime(timeUs, option); if (bitmap != 0) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeStrongBinder(bitmap->asBinder()); diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp index e2712ba..8dfcb3b 100644 --- a/media/libmedia/mediametadataretriever.cpp +++ b/media/libmedia/mediametadataretriever.cpp @@ -123,37 +123,15 @@ status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t l return mRetriever->setDataSource(fd, offset, length); } -status_t MediaMetadataRetriever::setMode(int mode) +sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option) { - LOGV("setMode(%d)", mode); - Mutex::Autolock _l(mLock); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - return mRetriever->setMode(mode); -} - -status_t MediaMetadataRetriever::getMode(int* mode) -{ - LOGV("getMode"); - Mutex::Autolock _l(mLock); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - return mRetriever->getMode(mode); -} - -sp<IMemory> MediaMetadataRetriever::captureFrame() -{ - LOGV("captureFrame"); + LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option); Mutex::Autolock _l(mLock); if (mRetriever == 0) { LOGE("retriever is not initialized"); return NULL; } - return mRetriever->captureFrame(); + return mRetriever->getFrameAtTime(timeUs, option); } const char* MediaMetadataRetriever::extractMetadata(int keyCode) diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp index 39fce81..713e441 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp @@ -65,7 +65,6 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) mThumbnail = NULL; mAlbumArt = NULL; mRetriever = NULL; - mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL; } MetadataRetrieverClient::~MetadataRetrieverClient() @@ -80,7 +79,7 @@ status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) con char buffer[SIZE]; String8 result; result.append(" MetadataRetrieverClient\n"); - snprintf(buffer, 255, " pid(%d) mode(%d)\n", mPid, mMode); + snprintf(buffer, 255, " pid(%d)\n", mPid); result.append(buffer); write(fd, result.string(), result.size()); write(fd, "\n", 1); @@ -94,7 +93,6 @@ void MetadataRetrieverClient::disconnect() mRetriever.clear(); mThumbnail.clear(); mAlbumArt.clear(); - mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL; IPCThreadState::self()->flushCommands(); } @@ -140,10 +138,7 @@ status_t MetadataRetrieverClient::setDataSource(const char *url) LOGV("player type = %d", playerType); sp<MediaMetadataRetrieverBase> p = createRetriever(playerType); if (p == NULL) return NO_INIT; - status_t ret = p->setMode(mMode); - if (ret == NO_ERROR) { - ret = p->setDataSource(url); - } + status_t ret = p->setDataSource(url); if (ret == NO_ERROR) mRetriever = p; return ret; } @@ -181,55 +176,22 @@ status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t ::close(fd); return NO_INIT; } - status_t status = p->setMode(mMode); - if (status == NO_ERROR) { - p->setDataSource(fd, offset, length); - } + status_t status = p->setDataSource(fd, offset, length); if (status == NO_ERROR) mRetriever = p; ::close(fd); return status; } -status_t MetadataRetrieverClient::setMode(int mode) -{ - LOGV("setMode"); - Mutex::Autolock lock(mLock); - if (mode < METADATA_MODE_NOOP || - mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) { - LOGE("invalid mode %d", mode); - return BAD_VALUE; - } - mMode = mode; - return NO_ERROR; -} - -status_t MetadataRetrieverClient::getMode(int* mode) const -{ - LOGV("getMode"); - Mutex::Autolock lock(mLock); - - // TODO: - // This may not be necessary. - // If setDataSource() has not been called, return the cached value - // otherwise, return the value retrieved from the retriever - if (mRetriever == NULL) { - *mode = mMode; - } else { - mRetriever->getMode(mode); - } - return NO_ERROR; -} - -sp<IMemory> MetadataRetrieverClient::captureFrame() +sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option) { - LOGV("captureFrame"); + LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option); Mutex::Autolock lock(mLock); mThumbnail.clear(); if (mRetriever == NULL) { LOGE("retriever is not initialized"); return NULL; } - VideoFrame *frame = mRetriever->captureFrame(); + VideoFrame *frame = mRetriever->getFrameAtTime(timeUs, option); if (frame == NULL) { LOGE("failed to capture a video frame"); return NULL; diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h index 4aab94f..b834715 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.h +++ b/media/libmediaplayerservice/MetadataRetrieverClient.h @@ -43,9 +43,7 @@ public: virtual void disconnect(); virtual status_t setDataSource(const char *url); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setMode(int mode); - virtual status_t getMode(int* mode) const; - virtual sp<IMemory> captureFrame(); + virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option); virtual sp<IMemory> extractAlbumArt(); virtual const char* extractMetadata(int keyCode); @@ -60,7 +58,6 @@ private: mutable Mutex mLock; sp<MediaMetadataRetrieverBase> mRetriever; pid_t mPid; - int mMode; // Keep the shared memory copy of album art and capture frame (for thumbnail) sp<IMemory> mAlbumArt; diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index d3aa2f6..10c6e41 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -130,9 +130,7 @@ status_t StagefrightMediaScanner::processFile( return HandleMIDI(path, &client); } - if (mRetriever->setDataSource(path) == OK - && mRetriever->setMode( - METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) { + if (mRetriever->setDataSource(path) == OK) { const char *value; if ((value = mRetriever->extractMetadata( METADATA_KEY_MIMETYPE)) != NULL) { @@ -181,9 +179,7 @@ char *StagefrightMediaScanner::extractAlbumArt(int fd) { } lseek(fd, 0, SEEK_SET); - if (mRetriever->setDataSource(fd, 0, size) == OK - && mRetriever->setMode( - METADATA_MODE_FRAME_CAPTURE_ONLY) == OK) { + if (mRetriever->setDataSource(fd, 0, size) == OK) { sp<IMemory> mem = mRetriever->extractAlbumArt(); if (mem != NULL) { diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index ac208cd..e8f4839 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -108,7 +108,10 @@ status_t StagefrightMetadataRetriever::setDataSource( static VideoFrame *extractVideoFrameWithCodecFlags( OMXClient *client, const sp<MetaData> &trackMeta, - const sp<MediaSource> &source, uint32_t flags) { + const sp<MediaSource> &source, + uint32_t flags, + int64_t frameTimeUs, + int seekMode) { sp<MediaSource> decoder = OMXCodec::Create( client->interface(), source->getFormat(), false, source, @@ -130,11 +133,22 @@ static VideoFrame *extractVideoFrameWithCodecFlags( // and spurious empty buffers. MediaSource::ReadOptions options; + if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC || + seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) { + + LOGE("Unknown seek mode: %d", seekMode); + return NULL; + } + + MediaSource::ReadOptions::SeekMode mode = + static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); + int64_t thumbNailTime; - if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) { - options.setSeekTo(thumbNailTime); + if (frameTimeUs < 0 && trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) { + options.setSeekTo(thumbNailTime, mode); } else { thumbNailTime = -1; + options.setSeekTo(frameTimeUs, mode); } MediaBuffer *buffer = NULL; @@ -226,14 +240,10 @@ static VideoFrame *extractVideoFrameWithCodecFlags( return frame; } -VideoFrame *StagefrightMetadataRetriever::captureFrame() { - LOGV("captureFrame"); - - if (0 == (mMode & METADATA_MODE_FRAME_CAPTURE_ONLY)) { - LOGV("captureFrame disabled by mode (0x%08x)", mMode); +VideoFrame *StagefrightMetadataRetriever::getFrameAtTime( + int64_t timeUs, int option) { - return NULL; - } + LOGV("getFrameAtTime: %lld us option: %d", timeUs, option); if (mExtractor.get() == NULL) { LOGV("no extractor."); @@ -270,13 +280,15 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() { VideoFrame *frame = extractVideoFrameWithCodecFlags( - &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs); + &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs, + timeUs, option); if (frame == NULL) { LOGV("Software decoder failed to extract thumbnail, " "trying hardware decoder."); - frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0); + frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0, + timeUs, option); } return frame; @@ -285,12 +297,6 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() { MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO"); - if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) { - LOGV("extractAlbumArt/metadata retrieval disabled by mode"); - - return NULL; - } - if (mExtractor == NULL) { return NULL; } @@ -309,12 +315,6 @@ MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { } const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) { - if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) { - LOGV("extractAlbumArt/metadata retrieval disabled by mode"); - - return NULL; - } - if (mExtractor == NULL) { return NULL; } diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h index b80387f..07b1ec8 100644 --- a/media/libstagefright/include/StagefrightMetadataRetriever.h +++ b/media/libstagefright/include/StagefrightMetadataRetriever.h @@ -35,7 +35,7 @@ struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface { virtual status_t setDataSource(const char *url); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual VideoFrame *captureFrame(); + virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option); virtual MediaAlbumArt *extractAlbumArt(); virtual const char *extractMetadata(int keyCode); diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index d16476d..1661130 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -22,13 +22,15 @@ #include "mkvparser.hpp" +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> +#include <media/stagefright/Utils.h> #include <utils/String8.h> namespace android { @@ -81,46 +83,6 @@ private: //////////////////////////////////////////////////////////////////////////////// -#include <ctype.h> -static void hexdump(const void *_data, size_t size) { - const uint8_t *data = (const uint8_t *)_data; - size_t offset = 0; - while (offset < size) { - printf("0x%04x ", offset); - - size_t n = size - offset; - if (n > 16) { - n = 16; - } - - for (size_t i = 0; i < 16; ++i) { - if (i == 8) { - printf(" "); - } - - if (offset + i < size) { - printf("%02x ", data[offset + i]); - } else { - printf(" "); - } - } - - printf(" "); - - for (size_t i = 0; i < n; ++i) { - if (isprint(data[offset + i])) { - printf("%c", data[offset + i]); - } else { - printf("."); - } - } - - printf("\n"); - - offset += 16; - } -} - struct BlockIterator { BlockIterator(mkvparser::Segment *segment, unsigned long trackNum); @@ -156,6 +118,9 @@ struct MatroskaSource : public MediaSource { virtual status_t read( MediaBuffer **buffer, const ReadOptions *options); +protected: + virtual ~MatroskaSource(); + private: enum Type { AVC, @@ -167,9 +132,15 @@ private: size_t mTrackIndex; Type mType; BlockIterator mBlockIter; + size_t mNALSizeLen; // for type AVC + + List<MediaBuffer *> mPendingFrames; status_t advance(); + status_t readBlock(); + void clearPendingFrames(); + MatroskaSource(const MatroskaSource &); MatroskaSource &operator=(const MatroskaSource &); }; @@ -180,18 +151,35 @@ MatroskaSource::MatroskaSource( mTrackIndex(index), mType(OTHER), mBlockIter(mExtractor->mSegment, - mExtractor->mTracks.itemAt(index).mTrackNum) { + mExtractor->mTracks.itemAt(index).mTrackNum), + mNALSizeLen(0) { + sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; + const char *mime; - CHECK(mExtractor->mTracks.itemAt(index).mMeta-> - findCString(kKeyMIMEType, &mime)); + CHECK(meta->findCString(kKeyMIMEType, &mime)); if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { mType = AVC; + + uint32_t dummy; + const uint8_t *avcc; + size_t avccSize; + CHECK(meta->findData( + kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); + + CHECK_GE(avccSize, 5u); + + mNALSizeLen = 1 + (avcc[4] & 3); + LOGV("mNALSizeLen = %d", mNALSizeLen); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { mType = AAC; } } +MatroskaSource::~MatroskaSource() { + clearPendingFrames(); +} + status_t MatroskaSource::start(MetaData *params) { mBlockIter.reset(); @@ -199,6 +187,8 @@ status_t MatroskaSource::start(MetaData *params) { } status_t MatroskaSource::stop() { + clearPendingFrames(); + return OK; } @@ -276,66 +266,313 @@ int64_t BlockIterator::blockTimeUs() const { //////////////////////////////////////////////////////////////////////////////// -status_t MatroskaSource::read( - MediaBuffer **out, const ReadOptions *options) { - *out = NULL; +static unsigned U24_AT(const uint8_t *ptr) { + return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; +} - int64_t seekTimeUs; - ReadOptions::SeekMode mode; - if (options && options->getSeekTo(&seekTimeUs, &mode)) { - mBlockIter.seek(seekTimeUs); +static size_t clz(uint8_t x) { + size_t numLeadingZeroes = 0; + + while (!(x & 0x80)) { + ++numLeadingZeroes; + x = x << 1; } + return numLeadingZeroes; +} + +void MatroskaSource::clearPendingFrames() { + while (!mPendingFrames.empty()) { + MediaBuffer *frame = *mPendingFrames.begin(); + mPendingFrames.erase(mPendingFrames.begin()); + + frame->release(); + frame = NULL; + } +} + +#define BAIL(err) \ + do { \ + if (bigbuf) { \ + bigbuf->release(); \ + bigbuf = NULL; \ + } \ + \ + return err; \ + } while (0) + +status_t MatroskaSource::readBlock() { + CHECK(mPendingFrames.empty()); + if (mBlockIter.eos()) { return ERROR_END_OF_STREAM; } const mkvparser::Block *block = mBlockIter.block(); + size_t size = block->GetSize(); int64_t timeUs = mBlockIter.blockTimeUs(); + int32_t isSync = block->IsKey(); - MediaBuffer *buffer = new MediaBuffer(size + 2); - buffer->meta_data()->setInt64(kKeyTime, timeUs); - buffer->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); + MediaBuffer *bigbuf = new MediaBuffer(size); long res = block->Read( - mExtractor->mReader, (unsigned char *)buffer->data() + 2); + mExtractor->mReader, (unsigned char *)bigbuf->data()); if (res != 0) { + bigbuf->release(); + bigbuf = NULL; + return ERROR_END_OF_STREAM; } - buffer->set_range(2, size); + mBlockIter.advance(); + + bigbuf->meta_data()->setInt64(kKeyTime, timeUs); + bigbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync); - if (mType == AVC) { - CHECK(size >= 2); + unsigned lacing = (block->Flags() >> 1) & 3; - uint8_t *data = (uint8_t *)buffer->data(); + if (lacing == 0) { + mPendingFrames.push_back(bigbuf); + return OK; + } - unsigned NALsize = data[2] << 8 | data[3]; - CHECK_EQ(size, NALsize + 2); + LOGV("lacing = %u, size = %d", lacing, size); - memcpy(data, "\x00\x00\x00\x01", 4); - buffer->set_range(0, size + 2); - } else if (mType == AAC) { - // There's strange junk at the beginning... + const uint8_t *data = (const uint8_t *)bigbuf->data(); + // hexdump(data, size); - const uint8_t *data = (const uint8_t *)buffer->data() + 2; - size_t offset = 0; - while (offset < size && data[offset] != 0x21) { - ++offset; - } - buffer->set_range(2 + offset, size - offset); + if (size == 0) { + BAIL(ERROR_MALFORMED); } - *out = buffer; + unsigned numFrames = (unsigned)data[0] + 1; + ++data; + --size; + + Vector<uint64_t> frameSizes; + + switch (lacing) { + case 1: // Xiph + { + for (size_t i = 0; i < numFrames - 1; ++i) { + size_t frameSize = 0; + uint8_t byte; + do { + if (size == 0) { + BAIL(ERROR_MALFORMED); + } + byte = data[0]; + ++data; + --size; + + frameSize += byte; + } while (byte == 0xff); + + frameSizes.push(frameSize); + } + + break; + } + + case 2: // fixed-size + { + if ((size % numFrames) != 0) { + BAIL(ERROR_MALFORMED); + } + + size_t frameSize = size / numFrames; + for (size_t i = 0; i < numFrames - 1; ++i) { + frameSizes.push(frameSize); + } + + break; + } + + case 3: // EBML + { + uint64_t lastFrameSize = 0; + for (size_t i = 0; i < numFrames - 1; ++i) { + uint8_t byte; + + if (size == 0) { + BAIL(ERROR_MALFORMED); + } + byte = data[0]; + ++data; + --size; + + size_t numLeadingZeroes = clz(byte); + + uint64_t frameSize = byte & ~(0x80 >> numLeadingZeroes); + for (size_t j = 0; j < numLeadingZeroes; ++j) { + if (size == 0) { + BAIL(ERROR_MALFORMED); + } + + frameSize = frameSize << 8; + frameSize |= data[0]; + ++data; + --size; + } + + if (i == 0) { + frameSizes.push(frameSize); + } else { + size_t shift = + 7 - numLeadingZeroes + 8 * numLeadingZeroes; + + int64_t delta = + (int64_t)frameSize - (1ll << (shift - 1)) + 1; + + frameSize = lastFrameSize + delta; + + frameSizes.push(frameSize); + } + + lastFrameSize = frameSize; + } + break; + } + + default: + TRESPASS(); + } #if 0 - hexdump((const uint8_t *)buffer->data() + buffer->range_offset(), - buffer->range_length()); + AString out; + for (size_t i = 0; i < frameSizes.size(); ++i) { + if (i > 0) { + out.append(", "); + } + out.append(StringPrintf("%llu", frameSizes.itemAt(i))); + } + LOGV("sizes = [%s]", out.c_str()); #endif - mBlockIter.advance(); + for (size_t i = 0; i < frameSizes.size(); ++i) { + uint64_t frameSize = frameSizes.itemAt(i); + + if (size < frameSize) { + BAIL(ERROR_MALFORMED); + } + + MediaBuffer *mbuf = new MediaBuffer(frameSize); + mbuf->meta_data()->setInt64(kKeyTime, timeUs); + mbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync); + memcpy(mbuf->data(), data, frameSize); + mPendingFrames.push_back(mbuf); + + data += frameSize; + size -= frameSize; + } + + size_t offset = bigbuf->range_length() - size; + bigbuf->set_range(offset, size); + + mPendingFrames.push_back(bigbuf); + + return OK; +} + +#undef BAIL + +status_t MatroskaSource::read( + MediaBuffer **out, const ReadOptions *options) { + *out = NULL; + + int64_t seekTimeUs; + ReadOptions::SeekMode mode; + if (options && options->getSeekTo(&seekTimeUs, &mode)) { + clearPendingFrames(); + mBlockIter.seek(seekTimeUs); + } + +again: + while (mPendingFrames.empty()) { + status_t err = readBlock(); + + if (err != OK) { + clearPendingFrames(); + + return err; + } + } + + MediaBuffer *frame = *mPendingFrames.begin(); + mPendingFrames.erase(mPendingFrames.begin()); + + size_t size = frame->range_length(); + + if (mType != AVC) { + *out = frame; + + return OK; + } + + if (size < mNALSizeLen) { + frame->release(); + frame = NULL; + + return ERROR_MALFORMED; + } + + // In the case of AVC content, each NAL unit is prefixed by + // mNALSizeLen bytes of length. We want to prefix the data with + // a four-byte 0x00000001 startcode instead of the length prefix. + // mNALSizeLen ranges from 1 through 4 bytes, so add an extra + // 3 bytes of padding to the buffer start. + static const size_t kPadding = 3; + + MediaBuffer *buffer = new MediaBuffer(size + kPadding); + + int64_t timeUs; + CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); + int32_t isSync; + CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); + + buffer->meta_data()->setInt64(kKeyTime, timeUs); + buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); + + memcpy((uint8_t *)buffer->data() + kPadding, + (const uint8_t *)frame->data() + frame->range_offset(), + size); + + buffer->set_range(kPadding, size); + + frame->release(); + frame = NULL; + + uint8_t *data = (uint8_t *)buffer->data(); + + size_t NALsize; + switch (mNALSizeLen) { + case 1: NALsize = data[kPadding]; break; + case 2: NALsize = U16_AT(&data[kPadding]); break; + case 3: NALsize = U24_AT(&data[kPadding]); break; + case 4: NALsize = U32_AT(&data[kPadding]); break; + default: + TRESPASS(); + } + + if (size < NALsize + mNALSizeLen) { + buffer->release(); + buffer = NULL; + + return ERROR_MALFORMED; + } + + if (size > NALsize + mNALSizeLen) { + LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen); + } + + // actual data starts at &data[kPadding + mNALSizeLen] + + memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4); + buffer->set_range(mNALSizeLen - 1, NALsize + 4); + + *out = buffer; return OK; } diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp index 455b1d6..7448d96 100644 --- a/media/libstagefright/matroska/mkvparser.cpp +++ b/media/libstagefright/matroska/mkvparser.cpp @@ -4474,6 +4474,9 @@ bool Block::IsKey() const return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
}
+unsigned char Block::Flags() const {
+ return m_flags;
+}
void Block::SetKey(bool bKey)
{
diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp index c46d349..f7d8948 100644 --- a/media/libstagefright/matroska/mkvparser.hpp +++ b/media/libstagefright/matroska/mkvparser.hpp @@ -80,6 +80,8 @@ public: bool IsKey() const;
void SetKey(bool);
+ unsigned char Flags() const;
+
long long GetOffset() const;
long GetSize() const;
long Read(IMkvReader*, unsigned char*) const;
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp index b0d2c64..bbde516 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp @@ -18,18 +18,381 @@ #include "ARTPSource.h" +#include <media/stagefright/foundation/hexdump.h> +#include <media/stagefright/foundation/ABitReader.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/MediaErrors.h> + +#include <ctype.h> namespace android { -AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> ¬ify) +static bool GetAttribute(const char *s, const char *key, AString *value) { + value->clear(); + + size_t keyLen = strlen(key); + + for (;;) { + while (isspace(*s)) { + ++s; + } + + const char *colonPos = strchr(s, ';'); + + size_t len = + (colonPos == NULL) ? strlen(s) : colonPos - s; + + if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { + value->setTo(&s[keyLen + 1], len - keyLen - 1); + return true; + } + + if (colonPos == NULL) { + return false; + } + + s = colonPos + 1; + } +} + +static sp<ABuffer> decodeHex(const AString &s) { + if ((s.size() % 2) != 0) { + return NULL; + } + + size_t outLen = s.size() / 2; + sp<ABuffer> buffer = new ABuffer(outLen); + uint8_t *out = buffer->data(); + + uint8_t accum = 0; + for (size_t i = 0; i < s.size(); ++i) { + char c = s.c_str()[i]; + unsigned value; + if (c >= '0' && c <= '9') { + value = c - '0'; + } else if (c >= 'a' && c <= 'f') { + value = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + value = c - 'A' + 10; + } else { + return NULL; + } + + accum = (accum << 4) | value; + + if (i & 1) { + *out++ = accum; + + accum = 0; + } + } + + return buffer; +} + +static status_t parseAudioObjectType( + ABitReader *bits, unsigned *audioObjectType) { + *audioObjectType = bits->getBits(5); + if ((*audioObjectType) == 31) { + *audioObjectType = 32 + bits->getBits(6); + } + + return OK; +} + +static status_t parseGASpecificConfig( + ABitReader *bits, + unsigned audioObjectType, unsigned channelConfiguration) { + unsigned frameLengthFlag = bits->getBits(1); + unsigned dependsOnCoreCoder = bits->getBits(1); + if (dependsOnCoreCoder) { + /* unsigned coreCoderDelay = */bits->getBits(1); + } + unsigned extensionFlag = bits->getBits(1); + + if (!channelConfiguration) { + // program_config_element + return ERROR_UNSUPPORTED; // XXX to be implemented + } + + if (audioObjectType == 6 || audioObjectType == 20) { + /* unsigned layerNr = */bits->getBits(3); + } + + if (extensionFlag) { + if (audioObjectType == 22) { + /* unsigned numOfSubFrame = */bits->getBits(5); + /* unsigned layerLength = */bits->getBits(11); + } else if (audioObjectType == 17 || audioObjectType == 19 + || audioObjectType == 20 || audioObjectType == 23) { + /* unsigned aacSectionDataResilienceFlag = */bits->getBits(1); + /* unsigned aacScalefactorDataResilienceFlag = */bits->getBits(1); + /* unsigned aacSpectralDataResilienceFlag = */bits->getBits(1); + } + + unsigned extensionFlag3 = bits->getBits(1); + CHECK_EQ(extensionFlag3, 0u); // TBD in version 3 + } + + return OK; +} + +static status_t parseAudioSpecificConfig(ABitReader *bits) { + unsigned audioObjectType; + CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK); + + unsigned samplingFreqIndex = bits->getBits(4); + if (samplingFreqIndex == 0x0f) { + /* unsigned samplingFrequency = */bits->getBits(24); + } + + unsigned channelConfiguration = bits->getBits(4); + + unsigned extensionAudioObjectType = 0; + unsigned sbrPresent = 0; + + if (audioObjectType == 5) { + extensionAudioObjectType = audioObjectType; + sbrPresent = 1; + unsigned extensionSamplingFreqIndex = bits->getBits(4); + if (extensionSamplingFreqIndex == 0x0f) { + /* unsigned extensionSamplingFrequency = */bits->getBits(24); + } + CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK); + } + + CHECK((audioObjectType >= 1 && audioObjectType <= 4) + || (audioObjectType >= 6 && audioObjectType <= 7) + || audioObjectType == 17 + || (audioObjectType >= 19 && audioObjectType <= 23)); + + CHECK_EQ(parseGASpecificConfig( + bits, audioObjectType, channelConfiguration), (status_t)OK); + + if (audioObjectType == 17 + || (audioObjectType >= 19 && audioObjectType <= 27)) { + unsigned epConfig = bits->getBits(2); + if (epConfig == 2 || epConfig == 3) { + // ErrorProtectionSpecificConfig + return ERROR_UNSUPPORTED; // XXX to be implemented + + if (epConfig == 3) { + unsigned directMapping = bits->getBits(1); + CHECK_EQ(directMapping, 1u); + } + } + } + +#if 0 + // This is not supported here as the upper layers did not explicitly + // signal the length of AudioSpecificConfig. + + if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) { + unsigned syncExtensionType = bits->getBits(11); + if (syncExtensionType == 0x2b7) { + CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType), + (status_t)OK); + + sbrPresent = bits->getBits(1); + + if (sbrPresent == 1) { + unsigned extensionSamplingFreqIndex = bits->getBits(4); + if (extensionSamplingFreqIndex == 0x0f) { + /* unsigned extensionSamplingFrequency = */bits->getBits(24); + } + } + } + } +#endif + + return OK; +} + +static status_t parseStreamMuxConfig( + ABitReader *bits, + unsigned *numSubFrames, + unsigned *frameLengthType, + bool *otherDataPresent, + unsigned *otherDataLenBits) { + unsigned audioMuxVersion = bits->getBits(1); + + unsigned audioMuxVersionA = 0; + if (audioMuxVersion == 1) { + audioMuxVersionA = bits->getBits(1); + } + + CHECK_EQ(audioMuxVersionA, 0u); // otherwise future spec + + if (audioMuxVersion != 0) { + return ERROR_UNSUPPORTED; // XXX to be implemented; + } + CHECK_EQ(audioMuxVersion, 0u); // XXX to be implemented + + unsigned allStreamsSameTimeFraming = bits->getBits(1); + CHECK_EQ(allStreamsSameTimeFraming, 1u); // There's only one stream. + + *numSubFrames = bits->getBits(6); + unsigned numProgram = bits->getBits(4); + CHECK_EQ(numProgram, 0u); // disabled in RTP LATM + + unsigned numLayer = bits->getBits(3); + CHECK_EQ(numLayer, 0u); // disabled in RTP LATM + + if (audioMuxVersion == 0) { + // AudioSpecificConfig + CHECK_EQ(parseAudioSpecificConfig(bits), (status_t)OK); + } else { + TRESPASS(); // XXX to be implemented + } + + *frameLengthType = bits->getBits(3); + switch (*frameLengthType) { + case 0: + { + /* unsigned bufferFullness = */bits->getBits(8); + + // The "coreFrameOffset" does not apply since there's only + // a single layer. + break; + } + + case 1: + { + /* unsigned frameLength = */bits->getBits(9); + break; + } + + case 3: + case 4: + case 5: + { + /* unsigned CELPframeLengthTableIndex = */bits->getBits(6); + break; + } + + case 6: + case 7: + { + /* unsigned HVXCframeLengthTableIndex = */bits->getBits(1); + break; + } + + default: + break; + } + + *otherDataPresent = bits->getBits(1); + *otherDataLenBits = 0; + if (*otherDataPresent) { + if (audioMuxVersion == 1) { + TRESPASS(); // XXX to be implemented + } else { + *otherDataLenBits = 0; + + unsigned otherDataLenEsc; + do { + (*otherDataLenBits) <<= 8; + otherDataLenEsc = bits->getBits(1); + unsigned otherDataLenTmp = bits->getBits(8); + (*otherDataLenBits) += otherDataLenTmp; + } while (otherDataLenEsc); + } + } + + unsigned crcCheckPresent = bits->getBits(1); + if (crcCheckPresent) { + /* unsigned crcCheckSum = */bits->getBits(8); + } + + return OK; +} + +sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) { + CHECK(!mMuxConfigPresent); // XXX to be implemented + + sp<ABuffer> out = new ABuffer(buffer->size()); + out->setRange(0, 0); + + size_t offset = 0; + uint8_t *ptr = buffer->data(); + + for (size_t i = 0; i <= mNumSubFrames; ++i) { + // parse PayloadLengthInfo + + unsigned payloadLength = 0; + + switch (mFrameLengthType) { + case 0: + { + unsigned muxSlotLengthBytes = 0; + unsigned tmp; + do { + CHECK_LT(offset, buffer->size()); + tmp = ptr[offset++]; + muxSlotLengthBytes += tmp; + } while (tmp == 0xff); + + payloadLength = muxSlotLengthBytes; + break; + } + + default: + TRESPASS(); // XXX to be implemented + break; + } + + CHECK_LE(offset + payloadLength, buffer->size()); + + memcpy(out->data() + out->size(), &ptr[offset], payloadLength); + out->setRange(0, out->size() + payloadLength); + + offset += payloadLength; + + if (mOtherDataPresent) { + // We want to stay byte-aligned. + + CHECK((mOtherDataLenBits % 8) == 0); + CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size()); + offset += mOtherDataLenBits / 8; + } + } + + CHECK_EQ(offset, buffer->size()); + + return out; +} + +AMPEG4AudioAssembler::AMPEG4AudioAssembler( + const sp<AMessage> ¬ify, const AString ¶ms) : mNotifyMsg(notify), + mMuxConfigPresent(false), mAccessUnitRTPTime(0), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0), mAccessUnitDamaged(false) { + AString val; + if (!GetAttribute(params.c_str(), "cpresent", &val)) { + mMuxConfigPresent = true; + } else if (val == "0") { + mMuxConfigPresent = false; + } else { + CHECK(val == "1"); + mMuxConfigPresent = true; + } + + CHECK(GetAttribute(params.c_str(), "config", &val)); + + sp<ABuffer> config = decodeHex(val); + CHECK(config != NULL); + + ABitReader bits(config->data(), config->size()); + status_t err = parseStreamMuxConfig( + &bits, &mNumSubFrames, &mFrameLengthType, + &mOtherDataPresent, &mOtherDataLenBits); + + CHECK_EQ(err, (status_t)NO_ERROR); } AMPEG4AudioAssembler::~AMPEG4AudioAssembler() { @@ -108,13 +471,7 @@ void AMPEG4AudioAssembler::submitAccessUnit() { while (it != mPackets.end()) { const sp<ABuffer> &unit = *it; - size_t n = 0; - while (unit->data()[n] == 0xff) { - ++n; - } - ++n; - - totalSize += unit->size() - n; + totalSize += unit->size(); ++it; } @@ -124,20 +481,13 @@ void AMPEG4AudioAssembler::submitAccessUnit() { while (it != mPackets.end()) { const sp<ABuffer> &unit = *it; - size_t n = 0; - while (unit->data()[n] == 0xff) { - ++n; - } - ++n; - memcpy((uint8_t *)accessUnit->data() + offset, - unit->data() + n, unit->size() - n); - - offset += unit->size() - n; + unit->data(), unit->size()); ++it; } + accessUnit = removeLATMFraming(accessUnit); CopyTimes(accessUnit, *mPackets.begin()); #if 0 diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h index bf9f204..9cef94c 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h @@ -27,9 +27,11 @@ namespace android { struct AMessage; +struct AString; struct AMPEG4AudioAssembler : public ARTPAssembler { - AMPEG4AudioAssembler(const sp<AMessage> ¬ify); + AMPEG4AudioAssembler( + const sp<AMessage> ¬ify, const AString ¶ms); protected: virtual ~AMPEG4AudioAssembler(); @@ -40,6 +42,13 @@ protected: private: sp<AMessage> mNotifyMsg; + + bool mMuxConfigPresent; + unsigned mNumSubFrames; + unsigned mFrameLengthType; + bool mOtherDataPresent; + unsigned mOtherDataLenBits; + uint32_t mAccessUnitRTPTime; bool mNextExpectedSeqNoValid; uint32_t mNextExpectedSeqNo; @@ -49,6 +58,8 @@ private: AssemblyStatus addPacket(const sp<ARTPSource> &source); void submitAccessUnit(); + sp<ABuffer> removeLATMFraming(const sp<ABuffer> &buffer); + DISALLOW_EVIL_CONSTRUCTORS(AMPEG4AudioAssembler); }; diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp index 2518264..5aae4e7 100644 --- a/media/libstagefright/rtsp/ARTPSource.cpp +++ b/media/libstagefright/rtsp/ARTPSource.cpp @@ -57,7 +57,7 @@ ARTPSource::ARTPSource( mAssembler = new AAVCAssembler(notify); mIssueFIRRequests = true; } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) { - mAssembler = new AMPEG4AudioAssembler(notify); + mAssembler = new AMPEG4AudioAssembler(notify, params); } else if (!strncmp(desc.c_str(), "H263-1998/", 10) || !strncmp(desc.c_str(), "H263-2000/", 10)) { mAssembler = new AH263Assembler(notify); diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index 5ec03b2..e936923 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -23,11 +23,13 @@ #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/base64.h> #include <media/stagefright/MediaErrors.h> #include <arpa/inet.h> #include <fcntl.h> #include <netdb.h> +#include <openssl/md5.h> #include <sys/socket.h> namespace android { @@ -37,6 +39,7 @@ const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll; ARTSPConnection::ARTSPConnection() : mState(DISCONNECTED), + mAuthType(NONE), mSocket(-1), mConnectionID(0), mNextCSeq(0), @@ -114,10 +117,13 @@ void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) { // static bool ARTSPConnection::ParseURL( - const char *url, AString *host, unsigned *port, AString *path) { + const char *url, AString *host, unsigned *port, AString *path, + AString *user, AString *pass) { host->clear(); *port = 0; path->clear(); + user->clear(); + pass->clear(); if (strncasecmp("rtsp://", url, 7)) { return false; @@ -133,7 +139,25 @@ bool ARTSPConnection::ParseURL( path->setTo(slashPos); } - char *colonPos = strchr(host->c_str(), ':'); + ssize_t atPos = host->find("@"); + + if (atPos >= 0) { + // Split of user:pass@ from hostname. + + AString userPass(*host, 0, atPos); + host->erase(0, atPos + 1); + + ssize_t colonPos = userPass.find(":"); + + if (colonPos < 0) { + *user = userPass; + } else { + user->setTo(userPass, 0, colonPos); + pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1); + } + } + + const char *colonPos = strchr(host->c_str(), ':'); if (colonPos != NULL) { unsigned long x; @@ -187,7 +211,12 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) { AString host, path; unsigned port; - if (!ParseURL(url.c_str(), &host, &port, &path)) { + if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass) + || (mUser.size() > 0 && mPass.size() == 0)) { + // If we have a user name but no password we have to give up + // right here, since we currently have no way of asking the user + // for this information. + LOGE("Malformed rtsp url %s", url.c_str()); reply->setInt32("result", ERROR_MALFORMED); @@ -197,6 +226,10 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) { return; } + if (mUser.size() > 0) { + LOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str()); + } + struct hostent *ent = gethostbyname(host.c_str()); if (ent == NULL) { LOGE("Unknown host %s", host.c_str()); @@ -262,6 +295,11 @@ void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) { reply->setInt32("result", OK); mState = DISCONNECTED; + mUser.clear(); + mPass.clear(); + mAuthType = NONE; + mNonce.clear(); + reply->post(); } @@ -335,6 +373,12 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) { AString request; CHECK(msg->findString("request", &request)); + // Just in case we need to re-issue the request with proper authentication + // later, stash it away. + reply->setString("original-request", request.c_str(), request.size()); + + addAuthentication(&request); + // Find the boundary between headers and the body. ssize_t i = request.find("\r\n\r\n"); CHECK_GE(i, 0); @@ -347,7 +391,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) { request.insert(cseqHeader, i + 2); - LOGV("%s", request.c_str()); + LOGV("request: '%s'", request.c_str()); size_t numBytesSent = 0; while (numBytesSent < request.size()) { @@ -612,6 +656,30 @@ bool ARTSPConnection::receiveRTSPReponse() { } } + if (response->mStatusCode == 401) { + if (mAuthType == NONE && mUser.size() > 0 + && parseAuthMethod(response)) { + ssize_t i; + CHECK_EQ((status_t)OK, findPendingRequest(response, &i)); + CHECK_GE(i, 0); + + sp<AMessage> reply = mPendingRequests.valueAt(i); + mPendingRequests.removeItemsAt(i); + + AString request; + CHECK(reply->findString("original-request", &request)); + + sp<AMessage> msg = new AMessage(kWhatSendRequest, id()); + msg->setMessage("reply", reply); + msg->setString("request", request.c_str(), request.size()); + + LOGI("re-sending request with authentication headers..."); + onSendRequest(msg); + + return true; + } + } + return notifyResponseListener(response); } @@ -628,26 +696,47 @@ bool ARTSPConnection::ParseSingleUnsignedLong( return true; } -bool ARTSPConnection::notifyResponseListener( - const sp<ARTSPResponse> &response) { +status_t ARTSPConnection::findPendingRequest( + const sp<ARTSPResponse> &response, ssize_t *index) const { + *index = 0; + ssize_t i = response->mHeaders.indexOfKey("cseq"); if (i < 0) { - return true; + // This is an unsolicited server->client message. + return OK; } AString value = response->mHeaders.valueAt(i); unsigned long cseq; if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) { - return false; + return ERROR_MALFORMED; } i = mPendingRequests.indexOfKey(cseq); if (i < 0) { - // Unsolicited response? - TRESPASS(); + return -ENOENT; + } + + *index = i; + + return OK; +} + +bool ARTSPConnection::notifyResponseListener( + const sp<ARTSPResponse> &response) { + ssize_t i; + status_t err = findPendingRequest(response, &i); + + if (err == OK && i < 0) { + // An unsolicited server response is not a problem. + return true; + } + + if (err != OK) { + return false; } sp<AMessage> reply = mPendingRequests.valueAt(i); @@ -660,4 +749,160 @@ bool ARTSPConnection::notifyResponseListener( return true; } +bool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) { + ssize_t i = response->mHeaders.indexOfKey("www-authenticate"); + + if (i < 0) { + return false; + } + + AString value = response->mHeaders.valueAt(i); + + if (!strncmp(value.c_str(), "Basic", 5)) { + mAuthType = BASIC; + } else { +#if !defined(HAVE_ANDROID_OS) + // We don't have access to the MD5 implementation on the simulator, + // so we won't support digest authentication. + return false; +#endif + + CHECK(!strncmp(value.c_str(), "Digest", 6)); + mAuthType = DIGEST; + + i = value.find("nonce="); + CHECK_GE(i, 0); + CHECK_EQ(value.c_str()[i + 6], '\"'); + ssize_t j = value.find("\"", i + 7); + CHECK_GE(j, 0); + + mNonce.setTo(value, i + 7, j - i - 7); + } + + return true; +} + +#if defined(HAVE_ANDROID_OS) +static void H(const AString &s, AString *out) { + out->clear(); + + MD5_CTX m; + MD5_Init(&m); + MD5_Update(&m, s.c_str(), s.size()); + + uint8_t key[16]; + MD5_Final(key, &m); + + for (size_t i = 0; i < 16; ++i) { + char nibble = key[i] >> 4; + if (nibble <= 9) { + nibble += '0'; + } else { + nibble += 'a' - 10; + } + out->append(&nibble, 1); + + nibble = key[i] & 0x0f; + if (nibble <= 9) { + nibble += '0'; + } else { + nibble += 'a' - 10; + } + out->append(&nibble, 1); + } +} +#endif + +static void GetMethodAndURL( + const AString &request, AString *method, AString *url) { + ssize_t space1 = request.find(" "); + CHECK_GE(space1, 0); + + ssize_t space2 = request.find(" ", space1 + 1); + CHECK_GE(space2, 0); + + method->setTo(request, 0, space1); + url->setTo(request, space1 + 1, space2 - space1); +} + +void ARTSPConnection::addAuthentication(AString *request) { + if (mAuthType == NONE) { + return; + } + + // Find the boundary between headers and the body. + ssize_t i = request->find("\r\n\r\n"); + CHECK_GE(i, 0); + + if (mAuthType == BASIC) { + AString tmp; + tmp.append(mUser); + tmp.append(":"); + tmp.append(mPass); + + AString out; + encodeBase64(tmp.c_str(), tmp.size(), &out); + + AString fragment; + fragment.append("Authorization: Basic "); + fragment.append(out); + fragment.append("\r\n"); + + request->insert(fragment, i + 2); + + return; + } + +#if defined(HAVE_ANDROID_OS) + CHECK_EQ((int)mAuthType, (int)DIGEST); + + AString method, url; + GetMethodAndURL(*request, &method, &url); + + AString A1; + A1.append(mUser); + A1.append(":"); + A1.append("Streaming Server"); + A1.append(":"); + A1.append(mPass); + + AString A2; + A2.append(method); + A2.append(":"); + A2.append(url); + + AString HA1, HA2; + H(A1, &HA1); + H(A2, &HA2); + + AString tmp; + tmp.append(HA1); + tmp.append(":"); + tmp.append(mNonce); + tmp.append(":"); + tmp.append(HA2); + + AString digest; + H(tmp, &digest); + + AString fragment; + fragment.append("Authorization: Digest "); + fragment.append("nonce=\""); + fragment.append(mNonce); + fragment.append("\", "); + fragment.append("username=\""); + fragment.append(mUser); + fragment.append("\", "); + fragment.append("uri=\""); + fragment.append(url); + fragment.append("\", "); + fragment.append("response=\""); + fragment.append(digest); + fragment.append("\""); + fragment.append("\r\n"); + + request->insert(fragment, i + 2); +#endif +} + } // namespace android diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h index 96e0d5b..19be2a6 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.h +++ b/media/libstagefright/rtsp/ARTSPConnection.h @@ -42,6 +42,10 @@ struct ARTSPConnection : public AHandler { void observeBinaryData(const sp<AMessage> &reply); + static bool ParseURL( + const char *url, AString *host, unsigned *port, AString *path, + AString *user, AString *pass); + protected: virtual ~ARTSPConnection(); virtual void onMessageReceived(const sp<AMessage> &msg); @@ -62,9 +66,18 @@ private: kWhatObserveBinaryData = 'obin', }; + enum AuthType { + NONE, + BASIC, + DIGEST + }; + static const int64_t kSelectTimeoutUs; State mState; + AString mUser, mPass; + AuthType mAuthType; + AString mNonce; int mSocket; int32_t mConnectionID; int32_t mNextCSeq; @@ -90,8 +103,11 @@ private: sp<ABuffer> receiveBinaryData(); bool notifyResponseListener(const sp<ARTSPResponse> &response); - static bool ParseURL( - const char *url, AString *host, unsigned *port, AString *path); + bool parseAuthMethod(const sp<ARTSPResponse> &response); + void addAuthentication(AString *request); + + status_t findPendingRequest( + const sp<ARTSPResponse> &response, ssize_t *index) const; static bool ParseSingleUnsignedLong( const char *from, unsigned long *x); diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp index 0db3595..0d0234b 100644 --- a/media/libstagefright/rtsp/ASessionDescription.cpp +++ b/media/libstagefright/rtsp/ASessionDescription.cpp @@ -53,21 +53,30 @@ bool ASessionDescription::parse(const void *data, size_t size) { mFormats.push(AString("[root]")); AString desc((const char *)data, size); - LOGI("%s", desc.c_str()); size_t i = 0; for (;;) { - ssize_t eolPos = desc.find("\r\n", i); + ssize_t eolPos = desc.find("\n", i); + if (eolPos < 0) { break; } - AString line(desc, i, eolPos - i); + AString line; + if ((size_t)eolPos > i && desc.c_str()[eolPos - 1] == '\r') { + // We accept both '\n' and '\r\n' line endings, if it's + // the latter, strip the '\r' as well. + line.setTo(desc, i, eolPos - i - 1); + } else { + line.setTo(desc, i, eolPos - i); + } if (line.size() < 2 || line.c_str()[1] != '=') { return false; } + LOGI("%s", line.c_str()); + switch (line.c_str()[0]) { case 'v': { @@ -141,7 +150,7 @@ bool ASessionDescription::parse(const void *data, size_t size) { } } - i = eolPos + 2; + i = eolPos + 1; } return true; @@ -245,7 +254,7 @@ bool ASessionDescription::getDurationUs(int64_t *durationUs) const { return false; } - if (value == "npt=now-") { + if (value == "npt=now-" || value == "npt=0-") { return false; } @@ -256,15 +265,17 @@ bool ASessionDescription::getDurationUs(int64_t *durationUs) const { const char *s = value.c_str() + 4; char *end; double from = strtod(s, &end); - CHECK_GT(end, s); - CHECK_EQ(*end, '-'); + + if (end == s || *end != '-') { + return false; + } s = end + 1; double to = strtod(s, &end); - CHECK_GT(end, s); - CHECK_EQ(*end, '\0'); - CHECK_GE(to, from); + if (end == s || *end != '\0' || to < from) { + return false; + } *durationUs = (int64_t)((to - from) * 1E6); diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk index 081ae32..0bbadc1 100644 --- a/media/libstagefright/rtsp/Android.mk +++ b/media/libstagefright/rtsp/Android.mk @@ -23,6 +23,7 @@ LOCAL_C_INCLUDES:= \ $(JNI_H_INCLUDE) \ $(TOP)/frameworks/base/include/media/stagefright/openmax \ $(TOP)/frameworks/base/media/libstagefright/include \ + $(TOP)/external/openssl/include LOCAL_MODULE:= libstagefright_rtsp diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 1bc9925..8f8e10a 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -96,6 +96,7 @@ struct MyHandler : public AHandler { mNetLooper(new ALooper), mConn(new ARTSPConnection), mRTPConn(new ARTPConnection), + mOriginalSessionURL(url), mSessionURL(url), mSetupTracksSuccessful(false), mSeekPending(false), @@ -113,6 +114,23 @@ struct MyHandler : public AHandler { mNetLooper->start(false /* runOnCallingThread */, false /* canCallJava */, PRIORITY_HIGHEST); + + // Strip any authentication info from the session url, we don't + // want to transmit user/pass in cleartext. + AString host, path, user, pass; + unsigned port; + if (ARTSPConnection::ParseURL( + mSessionURL.c_str(), &host, &port, &path, &user, &pass) + && user.size() > 0) { + mSessionURL.clear(); + mSessionURL.append("rtsp://"); + mSessionURL.append(host); + mSessionURL.append(":"); + mSessionURL.append(StringPrintf("%u", port)); + mSessionURL.append(path); + + LOGI("rewritten session url: '%s'", mSessionURL.c_str()); + } } void connect(const sp<AMessage> &doneMsg) { @@ -126,7 +144,7 @@ struct MyHandler : public AHandler { mConn->observeBinaryData(notify); sp<AMessage> reply = new AMessage('conn', id()); - mConn->connect(mSessionURL.c_str(), reply); + mConn->connect(mOriginalSessionURL.c_str(), reply); } void disconnect(const sp<AMessage> &doneMsg) { @@ -312,7 +330,7 @@ struct MyHandler : public AHandler { int32_t reconnect; if (msg->findInt32("reconnect", &reconnect) && reconnect) { sp<AMessage> reply = new AMessage('conn', id()); - mConn->connect(mSessionURL.c_str(), reply); + mConn->connect(mOriginalSessionURL.c_str(), reply); } else { (new AMessage('quit', id()))->post(); } @@ -922,7 +940,7 @@ struct MyHandler : public AHandler { CHECK(GetAttribute(range.c_str(), "npt", &val)); float npt1, npt2; - if (val == "now-") { + if (val == "now-" || val == "0-") { // This is a live stream and therefore not seekable. return; } else { @@ -992,6 +1010,7 @@ private: sp<ARTSPConnection> mConn; sp<ARTPConnection> mRTPConn; sp<ASessionDescription> mSessionDesc; + AString mOriginalSessionURL; // This one still has user:pass@ AString mSessionURL; AString mBaseURL; AString mSessionID; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java index 0c0974c..2eea206 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java @@ -532,7 +532,7 @@ public class CodecTest { e.printStackTrace(); return false; } - Bitmap outThumbnail = mMediaMetadataRetriever.captureFrame(); + Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1); //Verify the thumbnail Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java index 95dbb97..6ded74d 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java @@ -202,7 +202,6 @@ public class MediaMetadataTest extends AndroidTestCase { } String value = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); try { retriever.setDataSource(meta_data_file[fileIndex][0]); } catch(Exception e) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java index 7174e2b..dec21d7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -36,13 +36,12 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // Test album art extraction. @MediumTest - public static void testAlbumArt() throws Exception { - Log.v(TAG, "testAlbumArt starts."); + public static void testGetEmbeddedPicture() throws Exception { + Log.v(TAG, "testGetEmbeddedPicture starts."); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); boolean supportWMA = MediaProfileReader.getWMAEnable(); boolean hasFailed = false; boolean supportWMV = MediaProfileReader.getWMVEnable(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) { try { Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]); @@ -53,13 +52,13 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { continue; } retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]); - byte[] albumArt = retriever.extractAlbumArt(); + byte[] albumArt = retriever.getEmbeddedPicture(); // TODO: // A better test would be to compare the retrieved album art with the // known result. if (albumArt == null) { // Do we have expect in JUnit? - Log.e(TAG, "Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]); + Log.e(TAG, "Fails to get embedded picture for " + MediaNames.ALBUMART_TEST_FILES[i]); hasFailed = true; } } catch(Exception e) { @@ -69,7 +68,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { Thread.yield(); // Don't be evil } retriever.release(); - Log.v(TAG, "testAlbumArt completes."); + Log.v(TAG, "testGetEmbeddedPicture completes."); assertTrue(!hasFailed); } @@ -92,7 +91,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { continue; } retriever.setDataSource(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]); - Bitmap bitmap = retriever.captureFrame(); + Bitmap bitmap = retriever.getFrameAtTime(-1); assertTrue(bitmap != null); try { java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i] + ".jpg"); @@ -120,7 +119,6 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { boolean supportWMV = MediaProfileReader.getWMVEnable(); boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) { try { Log.v(TAG, "File " + i + ": " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]); @@ -148,12 +146,9 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { public static void testBasicNormalMethodCallSequence() throws Exception { boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); try { retriever.setDataSource(MediaNames.TEST_PATH_1); - /* - * captureFrame() fails due to lack of permission to access hardware decoder devices - Bitmap bitmap = retriever.captureFrame(); + Bitmap bitmap = retriever.getFrameAtTime(-1); assertTrue(bitmap != null); try { java.io.OutputStream stream = new FileOutputStream("/sdcard/thumbnailout.jpg"); @@ -162,7 +157,6 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { } catch (Exception e) { throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.TEST_PATH_1, e); } - */ extractAllSupportedMetadataValues(retriever); } catch(Exception e) { Log.e(TAG, "Fails to setDataSource for " + MediaNames.TEST_PATH_1, e); @@ -172,18 +166,17 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { assertTrue(!hasFailed); } - // If setDataSource() has not been called, both captureFrame() and extractMetadata() must + // If setDataSource() has not been called, both getFrameAtTime() and extractMetadata() must // return null. @MediumTest public static void testBasicAbnormalMethodCallSequence() { boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) { Log.e(TAG, "No album metadata expected, but is available"); hasFailed = true; } - if (retriever.captureFrame() != null) { + if (retriever.getFrameAtTime(-1) != null) { Log.e(TAG, "No frame expected, but is available"); hasFailed = true; } @@ -194,7 +187,6 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { @MediumTest public static void testSetDataSource() { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); boolean hasFailed = false; // Null pointer argument @@ -259,14 +251,13 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // By default, capture frame and retrieve metadata MediaMetadataRetriever retriever = new MediaMetadataRetriever(); boolean hasFailed = false; - // retriever.setDataSource(MediaNames.TEST_PATH_1); - // assertTrue(retriever.captureFrame() != null); - // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); + retriever.setDataSource(MediaNames.TEST_PATH_1); + assertTrue(retriever.getFrameAtTime(-1) != null); + assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); // Do not capture frame or retrieve metadata - retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY & MediaMetadataRetriever.MODE_GET_METADATA_ONLY); retriever.setDataSource(MediaNames.TEST_PATH_1); - if (retriever.captureFrame() != null) { + if (retriever.getFrameAtTime(-1) != null) { Log.e(TAG, "No frame expected, but is available"); hasFailed = true; } @@ -276,23 +267,20 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { } // Capture frame only - // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); - // retriever.setDataSource(MediaNames.TEST_PATH_1); - // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null); + retriever.setDataSource(MediaNames.TEST_PATH_1); + assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null); // Retriever metadata only - retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); retriever.setDataSource(MediaNames.TEST_PATH_1); - if (retriever.captureFrame() != null) { + if (retriever.getFrameAtTime(-1) != null) { Log.e(TAG, "No frame expected, but is available"); hasFailed = true; } // Capture frame and retrieve metadata - // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY | MediaMetadataRetriever.MODE_GET_METADATA_ONLY); - // retriever.setDataSource(MediaNames.TEST_PATH_1); - // assertTrue(retriever.captureFrame() != null); - // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); + retriever.setDataSource(MediaNames.TEST_PATH_1); + assertTrue(retriever.getFrameAtTime(-1) != null); + assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); retriever.release(); assertTrue(!hasFailed); } diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png Binary files differindex 01c7e2a..6bc6201 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png Binary files differindex 4f0d1f1..aa2000e 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java index 840c5e1..c4feefd 100644 --- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -62,8 +62,8 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree */ private static final int AWAKE_POKE_MILLIS = 30000; - private final KeyguardScreenCallback mCallback; - private final LockPatternUtils mLockPatternUtils; + private KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; private KeyguardUpdateMonitor mUpdateMonitor; private TextView mTopHeader; @@ -159,7 +159,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree if (mCheckingDialog != null) { mCheckingDialog.hide(); } - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mCallback = null; + mLockPatternUtils = null; + mUpdateMonitor = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index 1f06dcc..5e33f05 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -221,8 +221,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac final AlertDialog.Builder ab = new AlertDialog.Builder(mContext); ab.setAdapter(mAdapter, this) - .setInverseBackgroundForced(true) - .setTitle(R.string.global_actions); + .setInverseBackgroundForced(true); final AlertDialog dialog = ab.create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); @@ -249,6 +248,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } else { mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); } + mDialog.setTitle(R.string.global_actions); } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index ba1d7f5..708e89d 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -223,8 +223,8 @@ public class KeyguardViewManager implements KeyguardWindowController { mKeyguardHost.postDelayed(new Runnable() { public void run() { synchronized (KeyguardViewManager.this) { - mKeyguardHost.removeView(lastView); lastView.cleanUp(); + mKeyguardHost.removeView(lastView); } } }, 500); diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 27706ef..f3d07ab 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -495,8 +495,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public void cleanUp() { ((KeyguardScreen) mLockScreen).onPause(); ((KeyguardScreen) mLockScreen).cleanUp(); + this.removeView(mLockScreen); ((KeyguardScreen) mUnlockScreen).onPause(); ((KeyguardScreen) mUnlockScreen).cleanUp(); + this.removeView(mUnlockScreen); } private boolean isSecure() { diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 635b7d3..5a20b93 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -55,9 +55,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM private Status mStatus = Status.Normal; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; private TextView mCarrier; private SlidingTab mSelector; @@ -225,8 +225,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM setFocusableInTouchMode(true); setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - updateMonitor.registerInfoCallback(this); - updateMonitor.registerSimStateCallback(this); + mUpdateMonitor.registerInfoCallback(this); + mUpdateMonitor.registerSimStateCallback(this); mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mSilentMode = isSilentMode(); @@ -668,7 +668,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM /** {@inheritDoc} */ public void cleanUp() { - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java index 418e243..ffd0a47 100644 --- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -66,9 +66,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient private int mTotalFailedPatternAttempts = 0; private CountDownTimer mCountdownTimer = null; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; /** * whether there is a fallback option available when the pattern is forgotten. @@ -478,6 +478,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** {@inheritDoc} */ public void cleanUp() { mUpdateMonitor.removeCallback(this); + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } @Override diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java index e47de13..a8b2840 100644 --- a/services/java/com/android/server/IntentResolver.java +++ b/services/java/com/android/server/IntentResolver.java @@ -346,7 +346,7 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { int num = 0; while (i.hasNext()) { - String name = (String)i.next(); + String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); String baseName = name; @@ -395,7 +395,7 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { int num = 0; while (i.hasNext()) { - String name = (String)i.next(); + String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); String baseName = name; @@ -534,8 +534,8 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { // Sorts a List of IntentFilter objects into descending priority order. private static final Comparator mResolvePrioritySorter = new Comparator() { public int compare(Object o1, Object o2) { - float q1 = ((IntentFilter)o1).getPriority(); - float q2 = ((IntentFilter)o2).getPriority(); + final int q1 = ((IntentFilter) o1).getPriority(); + final int q2 = ((IntentFilter) o2).getPriority(); return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); } }; diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index cb9dfc8..39c7540 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -102,6 +102,7 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.lang.reflect.Array; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -2881,13 +2882,13 @@ class PackageManagerService extends IPackageManager.Stub { SharedUserSetting suid = null; PackageSetting pkgSetting = null; - if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) { + if (!isSystemApp(pkg)) { // Only system apps can use these features. pkg.mOriginalPackages = null; pkg.mRealPackage = null; pkg.mAdoptPermissions = null; } - + synchronized (mPackages) { // Check all shared libraries and map to their actual file path. if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) { @@ -4080,6 +4081,7 @@ class PackageManagerService extends IPackageManager.Stub { } public final void addActivity(PackageParser.Activity a, String type) { + final boolean systemApp = isSystemApp(a.info.applicationInfo); mActivities.put(a.getComponentName(), a); if (SHOW_INFO || Config.LOGV) Log.v( TAG, " " + type + " " + @@ -4088,6 +4090,11 @@ class PackageManagerService extends IPackageManager.Stub { int NI = a.intents.size(); for (int j=0; j<NI; j++) { PackageParser.ActivityIntentInfo intent = a.intents.get(j); + if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) { + intent.setPriority(0); + Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity " + + a.className + " with priority > 0, forcing to 0"); + } if (SHOW_INFO || Config.LOGV) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); @@ -4566,16 +4573,52 @@ class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } - public void setPackageObbPath(String packageName, String path) { + public void setPackageObbPaths(String packageName, String[] paths) { if (DEBUG_OBB) - Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path); - PackageSetting pkgSetting; + Log.v(TAG, "Setting .obb paths for " + packageName + " to: " + Arrays.toString(paths)); final int uid = Binder.getCallingUid(); final int permission = mContext.checkCallingPermission( android.Manifest.permission.INSTALL_PACKAGES); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); + if (!allowedByPermission) { + throw new SecurityException("Permission denial: attempt to set .obb file from pid=" + + Binder.getCallingPid()); + } synchronized (mPackages) { - pkgSetting = mSettings.mPackages.get(packageName); + final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); + if (pkgSetting == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + + if (paths != null) { + if (paths.length == 0) { + // Don't bother storing an empty array. + paths = null; + } else { + // Don't allow the caller to manipulate our copy of the + // list. + paths = paths.clone(); + } + } + + // Only write settings file if the new and old settings are not the + // same. + if (!Arrays.equals(paths, pkgSetting.obbPathStrings)) { + pkgSetting.obbPathStrings = paths; + mSettings.writeLP(); + } + } + } + + public String[] getPackageObbPaths(String packageName) { + if (DEBUG_OBB) + Log.v(TAG, "Getting .obb paths for " + packageName); + final int uid = Binder.getCallingUid(); + final int permission = mContext.checkCallingPermission( + android.Manifest.permission.INSTALL_PACKAGES); + final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); + synchronized (mPackages) { + final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null) { throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -4584,8 +4627,7 @@ class PackageManagerService extends IPackageManager.Stub { + Binder.getCallingPid() + ", uid=" + uid + ", package uid=" + pkgSetting.userId); } - pkgSetting.obbPathString = path; - mSettings.writeLP(); + return pkgSetting.obbPathStrings; } } @@ -5952,6 +5994,10 @@ class PackageManagerService extends IPackageManager.Stub { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + private static boolean isSystemApp(ApplicationInfo info) { + return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + private static boolean isUpdatedSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; } @@ -7154,7 +7200,7 @@ class PackageManagerService extends IPackageManager.Stub { pw.print(" codePath="); pw.println(ps.codePathString); pw.print(" resourcePath="); pw.println(ps.resourcePathString); pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString); - pw.print(" obbPath="); pw.println(ps.obbPathString); + pw.print(" obbPaths="); pw.println(Arrays.toString(ps.obbPathStrings)); pw.print(" versionCode="); pw.println(ps.versionCode); if (ps.pkg != null) { pw.print(" versionName="); pw.println(ps.pkg.mVersionName); @@ -7362,6 +7408,12 @@ class PackageManagerService extends IPackageManager.Stub { static class PackageSignatures { private Signature[] mSignatures; + PackageSignatures(PackageSignatures orig) { + if (orig != null && orig.mSignatures != null) { + mSignatures = orig.mSignatures.clone(); + } + } + PackageSignatures(Signature[] sigs) { assignSignatures(sigs); } @@ -7697,6 +7749,15 @@ class PackageManagerService extends IPackageManager.Stub { setFlags(pkgFlags); } + GrantedPermissions(GrantedPermissions base) { + pkgFlags = base.pkgFlags; + grantedPermissions = (HashSet<String>) base.grantedPermissions.clone(); + + if (base.gids != null) { + gids = base.gids.clone(); + } + } + void setFlags(int pkgFlags) { this.pkgFlags = pkgFlags & ( ApplicationInfo.FLAG_SYSTEM | @@ -7717,14 +7778,14 @@ class PackageManagerService extends IPackageManager.Stub { File resourcePath; String resourcePathString; String nativeLibraryPathString; - String obbPathString; + String[] obbPathStrings; long timeStamp; long firstInstallTime; long lastUpdateTime; int versionCode; boolean uidError; - + PackageSignatures signatures = new PackageSignatures(); boolean permissionsFixed; @@ -7750,6 +7811,48 @@ class PackageManagerService extends IPackageManager.Stub { init(codePath, resourcePath, nativeLibraryPathString, pVersionCode); } + /** + * New instance of PackageSetting with one-level-deep cloning. + */ + PackageSettingBase(PackageSettingBase base) { + super(base); + + name = base.name; + realName = base.realName; + codePath = base.codePath; + codePathString = base.codePathString; + resourcePath = base.resourcePath; + resourcePathString = base.resourcePathString; + nativeLibraryPathString = base.nativeLibraryPathString; + + if (base.obbPathStrings != null) { + obbPathStrings = base.obbPathStrings.clone(); + } + + timeStamp = base.timeStamp; + firstInstallTime = base.firstInstallTime; + lastUpdateTime = base.lastUpdateTime; + versionCode = base.versionCode; + + uidError = base.uidError; + + signatures = new PackageSignatures(base.signatures); + + permissionsFixed = base.permissionsFixed; + haveGids = base.haveGids; + + disabledComponents = (HashSet<String>) base.disabledComponents.clone(); + + enabledComponents = (HashSet<String>) base.enabledComponents.clone(); + + enabled = base.enabled; + installStatus = base.installStatus; + + origPackage = base.origPackage; + + installerPackageName = base.installerPackageName; + } + void init(File codePath, File resourcePath, String nativeLibraryPathString, int pVersionCode) { this.codePath = codePath; @@ -7780,6 +7883,9 @@ class PackageManagerService extends IPackageManager.Stub { timeStamp = newStamp; } + /** + * Make a shallow copy of this package settings. + */ public void copyFrom(PackageSettingBase base) { grantedPermissions = base.grantedPermissions; gids = base.gids; @@ -7839,10 +7945,16 @@ class PackageManagerService extends IPackageManager.Stub { pkgFlags); } + /** + * New instance of PackageSetting replicating the original settings. + * Note that it keeps the same PackageParser.Package instance. + */ PackageSetting(PackageSetting orig) { - super(orig.name, orig.realName, orig.codePath, orig.resourcePath, - orig.nativeLibraryPathString, orig.versionCode, orig.pkgFlags); - copyFrom(orig); + super(orig); + + userId = orig.userId; + pkg = orig.pkg; + sharedUser = orig.sharedUser; } @Override @@ -8074,7 +8186,7 @@ class PackageManagerService extends IPackageManager.Stub { // a little trick... when we install the new package, we don't // want to modify the existing PackageSetting for the built-in // version. so at this point we need a new PackageSetting that - // is okay to much with. + // is okay to muck with. PackageSetting newp = new PackageSetting(p); replacePackageLP(name, newp); return true; @@ -8775,8 +8887,15 @@ class PackageManagerService extends IPackageManager.Stub { if (pkg.installerPackageName != null) { serializer.attribute(null, "installer", pkg.installerPackageName); } - if (pkg.obbPathString != null) { - serializer.attribute(null, "obbPath", pkg.obbPathString); + if (pkg.obbPathStrings != null && pkg.obbPathStrings.length > 0) { + int N = pkg.obbPathStrings.length; + serializer.startTag(null, "obbs"); + for (int i = 0; i < N; i++) { + serializer.startTag(null, "obb"); + serializer.attribute(null, "path", pkg.obbPathStrings[i]); + serializer.endTag(null, "obb"); + } + serializer.endTag(null, "obbs"); } pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { @@ -9180,7 +9299,6 @@ class PackageManagerService extends IPackageManager.Stub { String codePathStr = null; String resourcePathStr = null; String nativeLibraryPathStr = null; - String obbPathStr = null; String systemStr = null; String installerPackageName = null; String uidError = null; @@ -9200,7 +9318,6 @@ class PackageManagerService extends IPackageManager.Stub { codePathStr = parser.getAttributeValue(null, "codePath"); resourcePathStr = parser.getAttributeValue(null, "resourcePath"); nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); - obbPathStr = parser.getAttributeValue(null, "obbPath"); version = parser.getAttributeValue(null, "version"); if (version != null) { try { @@ -9325,7 +9442,6 @@ class PackageManagerService extends IPackageManager.Stub { packageSetting.uidError = "true".equals(uidError); packageSetting.installerPackageName = installerPackageName; packageSetting.nativeLibraryPathString = nativeLibraryPathStr; - packageSetting.obbPathString = obbPathStr; final String enabledStr = parser.getAttributeValue(null, "enabled"); if (enabledStr != null) { if (enabledStr.equalsIgnoreCase("true")) { @@ -9373,6 +9489,8 @@ class PackageManagerService extends IPackageManager.Stub { readGrantedPermissionsLP(parser, packageSetting.grantedPermissions); packageSetting.permissionsFixed = true; + } else if (tagName.equals("obbs")) { + readObbPathsLP(packageSetting, parser); } else { reportSettingsProblem(Log.WARN, "Unknown element under <package>: " @@ -9577,6 +9695,34 @@ class PackageManagerService extends IPackageManager.Stub { } } + private void readObbPathsLP(PackageSettingBase packageSetting, XmlPullParser parser) + throws XmlPullParserException, IOException { + final List<String> obbPaths = new ArrayList<String>(); + final int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + final String tagName = parser.getName(); + if (tagName.equals("obb")) { + final String path = parser.getAttributeValue(null, "path"); + obbPaths.add(path); + } else { + reportSettingsProblem(Log.WARN, "Unknown element under <obbs>: " + + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + } + if (obbPaths.size() == 0) { + return; + } else { + packageSetting.obbPathStrings = obbPaths.toArray(new String[obbPaths.size()]); + } + } + // Returns -1 if we could not find an available UserId to assign private int newUserIdLP(Object obj) { // Let's be stupidly inefficient for now... diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index f0cbaa0..4a18b3e 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -490,8 +490,17 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } - @Override public void setPackageObbPath(String packageName, String path) { throw new UnsupportedOperationException(); } + + @Override + public void setPackageObbPaths(String packageName, String[] paths) { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getPackageObbPaths(String packageName) { + throw new UnsupportedOperationException(); + } } diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java index f8fd2b7..c7e18df 100644 --- a/voip/java/android/net/sip/SipProfile.java +++ b/voip/java/android/net/sip/SipProfile.java @@ -49,6 +49,7 @@ public class SipProfile implements Parcelable, Serializable, Cloneable { private String mDomain; private String mProtocol = UDP; private String mProfileName; + private String mAuthUserName; private int mPort = DEFAULT_PORT; private boolean mSendKeepAlive = false; private boolean mAutoRegistration = true; @@ -147,6 +148,18 @@ public class SipProfile implements Parcelable, Serializable, Cloneable { } /** + * Sets the username used for authentication. + * + * @param name auth. name of the profile + * @return this builder object + * @hide // TODO: remove when we make it public + */ + public Builder setAuthUserName(String name) { + mProfile.mAuthUserName = name; + return this; + } + + /** * Sets the name of the profile. This name is given by user. * * @param name name of the profile @@ -300,6 +313,7 @@ public class SipProfile implements Parcelable, Serializable, Cloneable { mAutoRegistration = (in.readInt() == 0) ? false : true; mCallingUid = in.readInt(); mPort = in.readInt(); + mAuthUserName = in.readString(); } @Override @@ -314,6 +328,7 @@ public class SipProfile implements Parcelable, Serializable, Cloneable { out.writeInt(mAutoRegistration ? 1 : 0); out.writeInt(mCallingUid); out.writeInt(mPort); + out.writeString(mAuthUserName); } @Override @@ -375,6 +390,17 @@ public class SipProfile implements Parcelable, Serializable, Cloneable { } /** + * Gets the username for authentication. If it is null, then the username + * should be used in authentication instead. + * + * @return the auth. username + * @hide // TODO: remove when we make it public + */ + public String getAuthUserName() { + return mAuthUserName; + } + + /** * Gets the password. * * @return the password diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java index 3275317..aa616a9 100644 --- a/voip/java/com/android/server/sip/SipSessionGroup.java +++ b/voip/java/com/android/server/sip/SipSessionGroup.java @@ -895,7 +895,9 @@ class SipSessionGroup implements SipListener { challengedTransaction, String realm) { return new UserCredentials() { public String getUserName() { - return mLocalProfile.getUserName(); + String username = mLocalProfile.getAuthUserName(); + return (!TextUtils.isEmpty(username) ? username : + mLocalProfile.getUserName()); } public String getPassword() { |
